Skip to content

Commit 66a6231

Browse files
committed
Make Field inherit from DivisionRing
Addresses typelevel/algebra#246 (comment)
1 parent 1ec9e21 commit 66a6231

File tree

3 files changed

+41
-28
lines changed

3 files changed

+41
-28
lines changed

algebra-core/src/main/scala/algebra/ring/DivisionRing.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@ import scala.{specialized => sp}
66
trait DivisionRing[@sp(Byte, Short, Int, Long, Float, Double) A] extends Any with Ring[A] with MultiplicativeGroup[A] {
77
self =>
88

9-
def fromDouble(a: Double): A = Field.defaultFromDouble[A](a)(self, self)
9+
/**
10+
* This is implemented in terms of basic Ring ops. However, this is
11+
* probably significantly less efficient than can be done with a
12+
* specific type. So, it is recommended that this method be
13+
* overriden.
14+
*
15+
* This is possible because a Double is a rational number.
16+
*/
17+
def fromDouble(a: Double): A = DivisionRing.defaultFromDouble[A](a)(self, self)
1018

1119
}
1220

algebra-core/src/main/scala/algebra/ring/Field.scala

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ package ring
33

44
import scala.{specialized => sp}
55

6-
trait Field[@sp(Int, Long, Float, Double) A] extends Any with EuclideanRing[A] with MultiplicativeCommutativeGroup[A] {
6+
trait Field[@sp(Int, Long, Float, Double) A]
7+
extends Any
8+
with EuclideanRing[A]
9+
with DivisionRing[A]
10+
with MultiplicativeCommutativeGroup[A] {
711
self =>
812

913
// default implementations for GCD
@@ -19,15 +23,9 @@ trait Field[@sp(Int, Long, Float, Double) A] extends Any with EuclideanRing[A] w
1923
def emod(a: A, b: A): A = zero
2024
override def equotmod(a: A, b: A): (A, A) = (div(a, b), zero)
2125

22-
/**
23-
* This is implemented in terms of basic Field ops. However, this is
24-
* probably significantly less efficient than can be done with a
25-
* specific type. So, it is recommended that this method be
26-
* overriden.
27-
*
28-
* This is possible because a Double is a rational number.
29-
*/
30-
def fromDouble(a: Double): A = Field.defaultFromDouble(a)(self, self)
26+
// needed for bin-compat
27+
override def fromDouble(a: Double): A =
28+
DivisionRing.defaultFromDouble[A](a)(self, self)
3129

3230
}
3331

algebra-laws/shared/src/main/scala/algebra/laws/RingLaws.scala

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,29 @@ trait RingLaws[A] extends GroupLaws[A] { self =>
256256
}
257257
)
258258

259+
def divisionRing(implicit A: DivisionRing[A]) = new RingProperties(
260+
name = "division ring",
261+
al = additiveCommutativeGroup,
262+
ml = multiplicativeGroup,
263+
parents = Seq(ring),
264+
"fromDouble" -> forAll { (n: Double) =>
265+
if (Platform.isJvm) {
266+
// TODO: BigDecimal(n) is busted in scalajs, so we skip this test.
267+
val bd = new java.math.BigDecimal(n)
268+
val unscaledValue = new BigInt(bd.unscaledValue)
269+
val expected =
270+
if (bd.scale > 0) {
271+
A.div(A.fromBigInt(unscaledValue), A.fromBigInt(BigInt(10).pow(bd.scale)))
272+
} else {
273+
A.fromBigInt(unscaledValue * BigInt(10).pow(-bd.scale))
274+
}
275+
DivisionRing.fromDouble[A](n) ?== expected
276+
} else {
277+
Prop(true)
278+
}
279+
}
280+
)
281+
259282
// boolean rings
260283

261284
def boolRng(implicit A: BoolRng[A]) = RingProperties.fromParent(
@@ -285,23 +308,7 @@ trait RingLaws[A] extends GroupLaws[A] { self =>
285308
name = "field",
286309
al = additiveCommutativeGroup,
287310
ml = multiplicativeCommutativeGroup,
288-
parents = Seq(euclideanRing),
289-
"fromDouble" -> forAll { (n: Double) =>
290-
if (Platform.isJvm) {
291-
// TODO: BigDecimal(n) is busted in scalajs, so we skip this test.
292-
val bd = new java.math.BigDecimal(n)
293-
val unscaledValue = new BigInt(bd.unscaledValue)
294-
val expected =
295-
if (bd.scale > 0) {
296-
A.div(A.fromBigInt(unscaledValue), A.fromBigInt(BigInt(10).pow(bd.scale)))
297-
} else {
298-
A.fromBigInt(unscaledValue * BigInt(10).pow(-bd.scale))
299-
}
300-
Field.fromDouble[A](n) ?== expected
301-
} else {
302-
Prop(true)
303-
}
304-
}
311+
parents = Seq(euclideanRing, divisionRing)
305312
)
306313

307314
// Approximate fields such a Float or Double, even through filtered using FPFilter, do not work well with

0 commit comments

Comments
 (0)