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