Skip to content

Commit

Permalink
Created Math multiplyHigh method
Browse files Browse the repository at this point in the history
  • Loading branch information
jspenger committed Sep 25, 2023
1 parent 5d28d3e commit 3151a7f
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
18 changes: 18 additions & 0 deletions javalib/src/main/scala/java/lang/Math.scala
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,24 @@ object Math {
else overflow.value
}

@alwaysinline def multiplyHigh(a: scala.Long, b: scala.Long): scala.Long = {
/* Algorithm from Hacker's Delight, "8–2. Multiply high signed."
* Here, `a` is replaced with `u`, and `b` with `v`, and reassignment of
* variables with suffix `p`. Unsigned ints correspond to shifting with
* `>>>` and performing the `& 0xffffffffL` operations.
*/
val u0 = a & 0xffffffffL
val u1 = a >> 32
val v0 = b & 0xffffffffL
val v1 = b >> 32
val w0 = u0 * v0
val t = u1 * v0 + (w0 >>> 32)
val w1 = t & 0xffffffffL
val w2 = t >> 32
val w1p = u0 * v1 + w1
u1 * v1 + w2 + (w1p >> 32)
}

@alwaysinline def multiplyExact(a: scala.Long, b: scala.Int): scala.Long =
multiplyExact(a, b.toLong)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,57 @@ class MathTest {
}
}

@Test def multiplyHighTests(): Unit = {
case class MulHighTestCase(a: Long, b: Long, expected: Long)
val maxval = Long.MAX_VALUE
val minval = Long.MIN_VALUE
val halfmax = maxval >> 32
val halfmin = minval >> 32

val testcases: List[MulHighTestCase] =
MulHighTestCase(maxval, maxval, 4611686018427387903L) ::
MulHighTestCase(maxval, minval, -4611686018427387904L) ::
MulHighTestCase(minval, minval, 4611686018427387904L) ::
MulHighTestCase(maxval, 0L, 0L) ::
MulHighTestCase(minval, 0L, 0L) ::
MulHighTestCase(0L, 0L, 0L) ::
MulHighTestCase(maxval, halfmax, 1073741823L) ::
MulHighTestCase(maxval, halfmin, -1073741824L) ::
MulHighTestCase(halfmax, halfmin, -1L) ::
MulHighTestCase(halfmin, halfmin, 0L) ::
MulHighTestCase(halfmax, 127L, 0L) ::
MulHighTestCase(halfmax * 42L, halfmax * 1337L, 14038L) ::
MulHighTestCase(halfmin * 42L, halfmax * 1337L, -14039L) ::
MulHighTestCase(13L, 37L, 0L) ::
MulHighTestCase(123456789123456789L, 987654321L, 6609981L) ::
MulHighTestCase(
123123456456789789L,
998877665544332211L,
6667044887047954L
) ::
MulHighTestCase(
-123123456456789789L,
998877665544332211L,
-6667044887047955L
) ::
MulHighTestCase(
123123456456789789L,
-998877665544332211L,
-6667044887047955L
) ::
MulHighTestCase(
-123123456456789789L,
-998877665544332211L,
6667044887047954L
) ::
Nil

for (tc <- testcases) {
val result = Math.multiplyHigh(tc.a, tc.b)
assertTrue(
s"Math.multiplyHigh(${tc.a}, ${tc.b}) result: ${result} != expected: ${tc.expected}",
Math.multiplyHigh(tc.a, tc.b) == tc.expected
)
}
}
}

0 comments on commit 3151a7f

Please sign in to comment.