1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
|
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala
package math
import scala.language.implicitConversions
/**
* @since 2.8
*/
object Numeric {
trait ExtraImplicits {
/** These implicits create conversions from a value for which an implicit Numeric
* exists to the inner class which creates infix operations. Once imported, you
* can write methods as follows:
* {{{
* def plus[T: Numeric](x: T, y: T) = x + y
* }}}
*/
implicit def infixNumericOps[T](x: T)(implicit num: Numeric[T]): Numeric[T]#Ops = new num.Ops(x)
}
object Implicits extends ExtraImplicits { }
trait BigIntIsIntegral extends Integral[BigInt] {
def plus(x: BigInt, y: BigInt): BigInt = x + y
def minus(x: BigInt, y: BigInt): BigInt = x - y
def times(x: BigInt, y: BigInt): BigInt = x * y
def quot(x: BigInt, y: BigInt): BigInt = x / y
def rem(x: BigInt, y: BigInt): BigInt = x % y
def negate(x: BigInt): BigInt = -x
def fromInt(x: Int): BigInt = BigInt(x)
def toInt(x: BigInt): Int = x.intValue
def toLong(x: BigInt): Long = x.longValue
def toFloat(x: BigInt): Float = x.floatValue
def toDouble(x: BigInt): Double = x.doubleValue
}
implicit object BigIntIsIntegral extends BigIntIsIntegral with Ordering.BigIntOrdering
trait IntIsIntegral extends Integral[Int] {
def plus(x: Int, y: Int): Int = x + y
def minus(x: Int, y: Int): Int = x - y
def times(x: Int, y: Int): Int = x * y
def quot(x: Int, y: Int): Int = x / y
def rem(x: Int, y: Int): Int = x % y
def negate(x: Int): Int = -x
def fromInt(x: Int): Int = x
def toInt(x: Int): Int = x
def toLong(x: Int): Long = x.toLong
def toFloat(x: Int): Float = x.toFloat
def toDouble(x: Int): Double = x.toDouble
}
implicit object IntIsIntegral extends IntIsIntegral with Ordering.IntOrdering
trait ShortIsIntegral extends Integral[Short] {
def plus(x: Short, y: Short): Short = (x + y).toShort
def minus(x: Short, y: Short): Short = (x - y).toShort
def times(x: Short, y: Short): Short = (x * y).toShort
def quot(x: Short, y: Short): Short = (x / y).toShort
def rem(x: Short, y: Short): Short = (x % y).toShort
def negate(x: Short): Short = (-x).toShort
def fromInt(x: Int): Short = x.toShort
def toInt(x: Short): Int = x.toInt
def toLong(x: Short): Long = x.toLong
def toFloat(x: Short): Float = x.toFloat
def toDouble(x: Short): Double = x.toDouble
}
implicit object ShortIsIntegral extends ShortIsIntegral with Ordering.ShortOrdering
trait ByteIsIntegral extends Integral[Byte] {
def plus(x: Byte, y: Byte): Byte = (x + y).toByte
def minus(x: Byte, y: Byte): Byte = (x - y).toByte
def times(x: Byte, y: Byte): Byte = (x * y).toByte
def quot(x: Byte, y: Byte): Byte = (x / y).toByte
def rem(x: Byte, y: Byte): Byte = (x % y).toByte
def negate(x: Byte): Byte = (-x).toByte
def fromInt(x: Int): Byte = x.toByte
def toInt(x: Byte): Int = x.toInt
def toLong(x: Byte): Long = x.toLong
def toFloat(x: Byte): Float = x.toFloat
def toDouble(x: Byte): Double = x.toDouble
}
implicit object ByteIsIntegral extends ByteIsIntegral with Ordering.ByteOrdering
trait CharIsIntegral extends Integral[Char] {
def plus(x: Char, y: Char): Char = (x + y).toChar
def minus(x: Char, y: Char): Char = (x - y).toChar
def times(x: Char, y: Char): Char = (x * y).toChar
def quot(x: Char, y: Char): Char = (x / y).toChar
def rem(x: Char, y: Char): Char = (x % y).toChar
def negate(x: Char): Char = (-x).toChar
def fromInt(x: Int): Char = x.toChar
def toInt(x: Char): Int = x.toInt
def toLong(x: Char): Long = x.toLong
def toFloat(x: Char): Float = x.toFloat
def toDouble(x: Char): Double = x.toDouble
}
implicit object CharIsIntegral extends CharIsIntegral with Ordering.CharOrdering
trait LongIsIntegral extends Integral[Long] {
def plus(x: Long, y: Long): Long = x + y
def minus(x: Long, y: Long): Long = x - y
def times(x: Long, y: Long): Long = x * y
def quot(x: Long, y: Long): Long = x / y
def rem(x: Long, y: Long): Long = x % y
def negate(x: Long): Long = -x
def fromInt(x: Int): Long = x.toLong
def toInt(x: Long): Int = x.toInt
def toLong(x: Long): Long = x
def toFloat(x: Long): Float = x.toFloat
def toDouble(x: Long): Double = x.toDouble
}
implicit object LongIsIntegral extends LongIsIntegral with Ordering.LongOrdering
trait FloatIsConflicted extends Numeric[Float] {
def plus(x: Float, y: Float): Float = x + y
def minus(x: Float, y: Float): Float = x - y
def times(x: Float, y: Float): Float = x * y
def negate(x: Float): Float = -x
def fromInt(x: Int): Float = x.toFloat
def toInt(x: Float): Int = x.toInt
def toLong(x: Float): Long = x.toLong
def toFloat(x: Float): Float = x
def toDouble(x: Float): Double = x.toDouble
// logic in Numeric base trait mishandles abs(-0.0f)
override def abs(x: Float): Float = math.abs(x)
}
trait FloatIsFractional extends FloatIsConflicted with Fractional[Float] {
def div(x: Float, y: Float): Float = x / y
}
trait FloatAsIfIntegral extends FloatIsConflicted with Integral[Float] {
def quot(x: Float, y: Float): Float = (BigDecimal(x) quot BigDecimal(y)).floatValue
def rem(x: Float, y: Float): Float = (BigDecimal(x) remainder BigDecimal(y)).floatValue
}
implicit object FloatIsFractional extends FloatIsFractional with Ordering.FloatOrdering
object FloatAsIfIntegral extends FloatAsIfIntegral with Ordering.FloatOrdering {
}
trait DoubleIsConflicted extends Numeric[Double] {
def plus(x: Double, y: Double): Double = x + y
def minus(x: Double, y: Double): Double = x - y
def times(x: Double, y: Double): Double = x * y
def negate(x: Double): Double = -x
def fromInt(x: Int): Double = x.toDouble
def toInt(x: Double): Int = x.toInt
def toLong(x: Double): Long = x.toLong
def toFloat(x: Double): Float = x.toFloat
def toDouble(x: Double): Double = x
// logic in Numeric base trait mishandles abs(-0.0)
override def abs(x: Double): Double = math.abs(x)
}
trait DoubleIsFractional extends DoubleIsConflicted with Fractional[Double] {
def div(x: Double, y: Double): Double = x / y
}
trait DoubleAsIfIntegral extends DoubleIsConflicted with Integral[Double] {
def quot(x: Double, y: Double): Double = (BigDecimal(x) quot BigDecimal(y)).doubleValue
def rem(x: Double, y: Double): Double = (BigDecimal(x) remainder BigDecimal(y)).doubleValue
}
trait BigDecimalIsConflicted extends Numeric[BigDecimal] {
def plus(x: BigDecimal, y: BigDecimal): BigDecimal = x + y
def minus(x: BigDecimal, y: BigDecimal): BigDecimal = x - y
def times(x: BigDecimal, y: BigDecimal): BigDecimal = x * y
def negate(x: BigDecimal): BigDecimal = -x
def fromInt(x: Int): BigDecimal = BigDecimal(x)
def toInt(x: BigDecimal): Int = x.intValue
def toLong(x: BigDecimal): Long = x.longValue
def toFloat(x: BigDecimal): Float = x.floatValue
def toDouble(x: BigDecimal): Double = x.doubleValue
}
trait BigDecimalIsFractional extends BigDecimalIsConflicted with Fractional[BigDecimal] {
def div(x: BigDecimal, y: BigDecimal): BigDecimal = x / y
}
trait BigDecimalAsIfIntegral extends BigDecimalIsConflicted with Integral[BigDecimal] {
def quot(x: BigDecimal, y: BigDecimal): BigDecimal = x quot y
def rem(x: BigDecimal, y: BigDecimal): BigDecimal = x remainder y
}
// For Double and BigDecimal we offer implicit Fractional objects, but also one
// which acts like an Integral type, which is useful in NumericRange.
implicit object BigDecimalIsFractional extends BigDecimalIsFractional with Ordering.BigDecimalOrdering
object BigDecimalAsIfIntegral extends BigDecimalAsIfIntegral with Ordering.BigDecimalOrdering
implicit object DoubleIsFractional extends DoubleIsFractional with Ordering.DoubleOrdering
object DoubleAsIfIntegral extends DoubleAsIfIntegral with Ordering.DoubleOrdering
}
trait Numeric[T] extends Ordering[T] {
def plus(x: T, y: T): T
def minus(x: T, y: T): T
def times(x: T, y: T): T
def negate(x: T): T
def fromInt(x: Int): T
def toInt(x: T): Int
def toLong(x: T): Long
def toFloat(x: T): Float
def toDouble(x: T): Double
def zero = fromInt(0)
def one = fromInt(1)
def abs(x: T): T = if (lt(x, zero)) negate(x) else x
def signum(x: T): Int =
if (lt(x, zero)) -1
else if (gt(x, zero)) 1
else 0
class Ops(lhs: T) {
def +(rhs: T) = plus(lhs, rhs)
def -(rhs: T) = minus(lhs, rhs)
def *(rhs: T) = times(lhs, rhs)
def unary_-() = negate(lhs)
def abs(): T = Numeric.this.abs(lhs)
def signum(): Int = Numeric.this.signum(lhs)
def toInt(): Int = Numeric.this.toInt(lhs)
def toLong(): Long = Numeric.this.toLong(lhs)
def toFloat(): Float = Numeric.this.toFloat(lhs)
def toDouble(): Double = Numeric.this.toDouble(lhs)
}
implicit def mkNumericOps(lhs: T): Ops = new Ops(lhs)
}
|