1+ import scala .util .Try
2+
3+ trait InlineNumeric [T ] extends Numeric [T ]:
4+ transparent inline def plus (x : T , y : T ): T
5+ transparent inline def minus (x : T , y : T ): T
6+ transparent inline def times (x : T , y : T ): T
7+ transparent inline def negate (x : T ): T
8+ transparent inline def fromInt (x : Int ): T
9+ transparent inline def parseString (str : String ): Option [T ]
10+ transparent inline def toInt (x : T ): Int
11+ transparent inline def toLong (x : T ): Long
12+ transparent inline def toFloat (x : T ): Float
13+ transparent inline def toDouble (x : T ): Double
14+
15+ // error overriding method abs in trait InlineNumeric of type (x: T): T;
16+ // method abs in trait Numeric of type (x: T): T is not inline, cannot implement an inline method
17+ // transparent inline def abs(x: T): T
18+ // transparent inline def sign(x: T): T
19+
20+ // Deferred inline method fromInt in trait InlineNumeric cannot be invoked
21+ // transparent inline def zero = fromInt(0)
22+ // transparent inline def one = fromInt(1)
23+
24+ object InlineNumeric :
25+ extension [T ](x : T )(using num : InlineNumeric [T ])
26+ transparent inline def + (y : T ): T = num.plus(x, y)
27+ transparent inline def - (y : T ) = num.minus(x, y)
28+ transparent inline def * (y : T ): T = num.times(x, y)
29+ transparent inline def unary_- = num.negate(x)
30+ transparent inline def toInt : Int = num.toInt(x)
31+ transparent inline def toLong : Long = num.toLong(x)
32+ transparent inline def toFloat : Float = num.toFloat(x)
33+ transparent inline def toDouble : Double = num.toDouble(x)
34+ transparent inline def abs : T = num.abs(x)
35+ transparent inline def sign : T = num.sign(x)
36+
37+ trait InlineIntegral [T ] extends InlineNumeric [T ]:
38+ transparent inline def quot (x : T , y : T ): T
39+ transparent inline def rem (x : T , y : T ): T
40+
41+ object InlineIntegral :
42+ extension [T ](lhs : T )(using int : InlineIntegral [T ])
43+ transparent inline def / (rhs : T ) = int.quot(lhs, rhs)
44+ transparent inline def % (rhs : T ) = int.rem(lhs, rhs)
45+ transparent inline def /% (rhs : T ) = (int.quot(lhs, rhs), int.rem(lhs, rhs))
46+
47+ trait InlineFractional [T ] extends InlineNumeric [T ]:
48+ transparent inline def div (x : T , y : T ): T
49+
50+ object InlineFractional :
51+ extension [T ](lhs : T )(using frac : InlineFractional [T ])
52+ transparent inline def / (rhs : T ) = frac.div(lhs, rhs)
53+
54+ given IntIsInlineIntegral : InlineIntegral [Int ] with Ordering .IntOrdering with
55+ transparent inline def plus (x : Int , y : Int ): Int = x + y
56+ transparent inline def minus (x : Int , y : Int ): Int = x - y
57+ transparent inline def times (x : Int , y : Int ): Int = x * y
58+ transparent inline def negate (x : Int ): Int = - x
59+ transparent inline def fromInt (x : Int ): Int = x
60+ transparent inline def parseString (str : String ): Option [Int ] = str.toIntOption
61+ transparent inline def toInt (x : Int ): Int = x
62+ transparent inline def toLong (x : Int ): Long = x.toLong
63+ transparent inline def toFloat (x : Int ): Float = x.toFloat
64+ transparent inline def toDouble (x : Int ): Double = x.toDouble
65+ transparent override inline def abs (x : Int ): Int = math.abs(x)
66+ transparent override inline def sign (x : Int ): Int = math.signum(x)
67+
68+ transparent inline def quot (x : Int , y : Int ): Int = x / y
69+ transparent inline def rem (x : Int , y : Int ): Int = x % y
70+
71+ given BigIntIsInlineIntegral : InlineIntegral [BigInt ] with Ordering .BigIntOrdering with
72+ transparent inline def plus (x : BigInt , y : BigInt ): BigInt = x + y
73+ transparent inline def minus (x : BigInt , y : BigInt ): BigInt = x - y
74+ transparent inline def times (x : BigInt , y : BigInt ): BigInt = x * y
75+ transparent inline def negate (x : BigInt ): BigInt = - x
76+ transparent inline def fromInt (x : Int ): BigInt = BigInt (x)
77+ transparent inline def parseString (str : String ): Option [BigInt ] = Try (BigInt (str)).toOption
78+ transparent inline def toInt (x : BigInt ): Int = x.intValue
79+ transparent inline def toLong (x : BigInt ): Long = x.longValue
80+ transparent inline def toFloat (x : BigInt ): Float = x.floatValue
81+ transparent inline def toDouble (x : BigInt ): Double = x.doubleValue
82+ transparent override inline def abs (x : BigInt ): BigInt = x.abs
83+ transparent override inline def sign (x : BigInt ): BigInt = x.sign
84+
85+ transparent inline def quot (x : BigInt , y : BigInt ): BigInt = x / y
86+ transparent inline def rem (x : BigInt , y : BigInt ): BigInt = x % y
87+
88+ given ShortIsInlineIntegral : InlineIntegral [Short ] with Ordering .ShortOrdering with
89+ transparent inline def plus (x : Short , y : Short ): Short = (x + y).toShort
90+ transparent inline def minus (x : Short , y : Short ): Short = (x - y).toShort
91+ transparent inline def times (x : Short , y : Short ): Short = (x * y).toShort
92+ transparent inline def negate (x : Short ): Short = (- x).toShort
93+ transparent inline def fromInt (x : Int ): Short = x.toShort
94+ transparent inline def parseString (str : String ): Option [Short ] = str.toShortOption
95+ transparent inline def toInt (x : Short ): Int = x.toInt
96+ transparent inline def toLong (x : Short ): Long = x.toLong
97+ transparent inline def toFloat (x : Short ): Float = x.toFloat
98+ transparent inline def toDouble (x : Short ): Double = x.toDouble
99+ transparent override inline def abs (x : Short ): Short = math.abs(x).toShort
100+ transparent override inline def sign (x : Short ): Short = math.signum(x).toShort
101+
102+ transparent inline def quot (x : Short , y : Short ): Short = (x / y).toShort
103+ transparent inline def rem (x : Short , y : Short ): Short = (x % y).toShort
104+
105+ given ByteIsInlineIntegral : InlineIntegral [Byte ] with Ordering .ByteOrdering with
106+ transparent inline def plus (x : Byte , y : Byte ): Byte = (x + y).toByte
107+ transparent inline def minus (x : Byte , y : Byte ): Byte = (x - y).toByte
108+ transparent inline def times (x : Byte , y : Byte ): Byte = (x * y).toByte
109+ transparent inline def negate (x : Byte ): Byte = (- x).toByte
110+ transparent inline def fromInt (x : Int ): Byte = x.toByte
111+ transparent inline def parseString (str : String ): Option [Byte ] = str.toByteOption
112+ transparent inline def toInt (x : Byte ): Int = x.toInt
113+ transparent inline def toLong (x : Byte ): Long = x.toLong
114+ transparent inline def toFloat (x : Byte ): Float = x.toFloat
115+ transparent inline def toDouble (x : Byte ): Double = x.toDouble
116+ transparent override inline def abs (x : Byte ): Byte = math.abs(x).toByte
117+ transparent override inline def sign (x : Byte ): Byte = math.signum(x).toByte
118+
119+ transparent inline def quot (x : Byte , y : Byte ): Byte = (x / y).toByte
120+ transparent inline def rem (x : Byte , y : Byte ): Byte = (x % y).toByte
121+
122+ given CharIsInlineIntegral : InlineIntegral [Char ] with Ordering .CharOrdering with
123+ transparent inline def plus (x : Char , y : Char ): Char = (x + y).toChar
124+ transparent inline def minus (x : Char , y : Char ): Char = (x - y).toChar
125+ transparent inline def times (x : Char , y : Char ): Char = (x * y).toChar
126+ transparent inline def negate (x : Char ): Char = (- x).toChar
127+ transparent inline def fromInt (x : Int ): Char = x.toChar
128+ transparent inline def parseString (str : String ): Option [Char ] = Try (str.toInt.toChar).toOption
129+ transparent inline def toInt (x : Char ): Int = x.toInt
130+ transparent inline def toLong (x : Char ): Long = x.toLong
131+ transparent inline def toFloat (x : Char ): Float = x.toFloat
132+ transparent inline def toDouble (x : Char ): Double = x.toDouble
133+ transparent override inline def abs (x : Char ): Char = math.abs(x).toChar
134+ transparent override inline def sign (x : Char ): Char = math.signum(x).toChar
135+
136+ transparent inline def quot (x : Char , y : Char ): Char = (x / y).toChar
137+ transparent inline def rem (x : Char , y : Char ): Char = (x % y).toChar
138+
139+ given LongIsInlineIntegral : InlineIntegral [Long ] with Ordering .LongOrdering with
140+ transparent inline def plus (x : Long , y : Long ): Long = x + y
141+ transparent inline def minus (x : Long , y : Long ): Long = x - y
142+ transparent inline def times (x : Long , y : Long ): Long = x * y
143+ transparent inline def negate (x : Long ): Long = - x
144+ transparent inline def fromInt (x : Int ): Long = x.toLong
145+ transparent inline def parseString (str : String ): Option [Long ] = str.toLongOption
146+ transparent inline def toInt (x : Long ): Int = x.toInt
147+ transparent inline def toLong (x : Long ): Long = x
148+ transparent inline def toFloat (x : Long ): Float = x.toFloat
149+ transparent inline def toDouble (x : Long ): Double = x.toDouble
150+ transparent override inline def abs (x : Long ): Long = math.abs(x)
151+ transparent override inline def sign (x : Long ): Long = math.signum(x)
152+
153+ transparent inline def quot (x : Long , y : Long ): Long = (x / y).toLong
154+ transparent inline def rem (x : Long , y : Long ): Long = (x % y).toLong
155+
156+ given FloatIsInlineFractional : InlineFractional [Float ] with Ordering .Float .IeeeOrdering with
157+ transparent inline def plus (x : Float , y : Float ): Float = x + y
158+ transparent inline def minus (x : Float , y : Float ): Float = x - y
159+ transparent inline def times (x : Float , y : Float ): Float = x * y
160+ transparent inline def negate (x : Float ): Float = - x
161+ transparent inline def fromInt (x : Int ): Float = x.toFloat
162+ transparent inline def parseString (str : String ): Option [Float ] = str.toFloatOption
163+ transparent inline def toInt (x : Float ): Int = x.toInt
164+ transparent inline def toLong (x : Float ): Long = x.toLong
165+ transparent inline def toFloat (x : Float ): Float = x
166+ transparent inline def toDouble (x : Float ): Double = x.toDouble
167+ transparent override inline def abs (x : Float ): Float = math.abs(x)
168+ transparent override inline def sign (x : Float ): Float = math.signum(x)
169+
170+ transparent inline def div (x : Float , y : Float ): Float = x / y
171+
172+ given DoubleIsInlineFractional : InlineFractional [Double ] with Ordering .Double .IeeeOrdering with
173+ transparent inline def plus (x : Double , y : Double ): Double = x + y
174+ transparent inline def minus (x : Double , y : Double ): Double = x - y
175+ transparent inline def times (x : Double , y : Double ): Double = x * y
176+ transparent inline def negate (x : Double ): Double = - x
177+ transparent inline def fromInt (x : Int ): Double = x.toDouble
178+ transparent inline def parseString (str : String ): Option [Double ] = str.toDoubleOption
179+ transparent inline def toInt (x : Double ): Int = x.toInt
180+ transparent inline def toLong (x : Double ): Long = x.toLong
181+ transparent inline def toFloat (x : Double ): Float = x.toFloat
182+ transparent inline def toDouble (x : Double ): Double = x
183+ transparent override inline def abs (x : Double ): Double = math.abs(x)
184+ transparent override inline def sign (x : Double ): Double = math.signum(x)
185+
186+ transparent inline def div (x : Double , y : Double ): Double = x / y
187+
188+ trait BigDecimalIsConflicted extends InlineNumeric [BigDecimal ] with Ordering .BigDecimalOrdering :
189+ transparent inline def plus (x : BigDecimal , y : BigDecimal ): BigDecimal = x + y
190+ transparent inline def minus (x : BigDecimal , y : BigDecimal ): BigDecimal = x - y
191+ transparent inline def times (x : BigDecimal , y : BigDecimal ): BigDecimal = x * y
192+ transparent inline def negate (x : BigDecimal ): BigDecimal = - x
193+ transparent inline def fromInt (x : Int ): BigDecimal = BigDecimal (x)
194+ transparent inline def parseString (str : String ): Option [BigDecimal ] = Try (BigDecimal (str)).toOption
195+ transparent inline def toInt (x : BigDecimal ): Int = x.intValue
196+ transparent inline def toLong (x : BigDecimal ): Long = x.longValue
197+ transparent inline def toFloat (x : BigDecimal ): Float = x.floatValue
198+ transparent inline def toDouble (x : BigDecimal ): Double = x.doubleValue
199+ transparent override inline def abs (x : BigDecimal ): BigDecimal = x.abs
200+ transparent override inline def sign (x : BigDecimal ): BigDecimal = x.sign
201+
202+ given BigDecimalIsInlineFractional : BigDecimalIsConflicted with InlineFractional [BigDecimal ] with
203+ transparent inline def div (x : BigDecimal , y : BigDecimal ): BigDecimal = x / y
204+
205+ given BigDecimalAsIfInlineIntegral : BigDecimalIsConflicted with InlineIntegral [BigDecimal ] with
206+ transparent inline def quot (x : BigDecimal , y : BigDecimal ): BigDecimal = x quot y
207+ transparent inline def rem (x : BigDecimal , y : BigDecimal ): BigDecimal = x remainder y
208+
209+ object tests :
210+ import InlineNumeric .*
211+ import InlineIntegral .{/ => ¦ , % }
212+ import InlineFractional ./
213+
214+ inline def foo [T : InlineNumeric ](a : T , b : T ) =
215+ a + b * b
216+
217+ inline def div [T : InlineIntegral ](a : T , b : T ) =
218+ a ¦ b % b
219+
220+ inline def div [T : InlineFractional ](a : T , b : T ) =
221+ a / b + a
222+
223+ inline def bar [T : InlineNumeric ](a : T ) = a.toInt
224+
225+ inline def sign [T : InlineNumeric ](a : T ) = a.sign
226+
227+ def test (a : Int , b : Int ) =
228+ val v1 = foo(a, b) // should be a + b * b // can check with -Xprint:inlining
229+ val v2 = foo(a.toShort, b.toShort) // should be a + b * b
230+
231+ val v3 = div(BigDecimal (a), BigDecimal (b))(using BigDecimalAsIfInlineIntegral ) // should be BigDecimal(a) quot BigDecimal(b) remainder BigDecimal(b)
232+ val v4 = div(BigDecimal (a), BigDecimal (b))(using BigDecimalIsInlineFractional ) // should be BigDecimal(a) / BigDecimal(b) + BigDecimal(a)
233+
234+ val v5 = bar(a.toFloat) // should be a.toFloat.toInt
235+ val v6 = bar(a) // should be a
236+
237+ val v7 = sign(a)
238+ val v8 = sign(a.toChar)
239+ val v9 = sign(- 7F )
240+
241+ val v10 = sign(BigDecimal (a))(using BigDecimalAsIfInlineIntegral )
242+ val v11 = sign(BigDecimal (a))(using BigDecimalIsInlineFractional ) // the condition with isNan() should be removed, i.e. it should be equivalent to v10
0 commit comments