@@ -158,10 +158,6 @@ object RuntimeLong {
158
158
159
159
// Bitwise operations
160
160
161
- @ inline
162
- def not (a : RuntimeLong ): RuntimeLong =
163
- new RuntimeLong (~ a.lo, ~ a.hi)
164
-
165
161
@ inline
166
162
def or (a : RuntimeLong , b : RuntimeLong ): RuntimeLong =
167
163
new RuntimeLong (a.lo | b.lo, a.hi | b.hi)
@@ -272,31 +268,31 @@ object RuntimeLong {
272
268
273
269
// Arithmetic operations
274
270
275
- @ inline
276
- def neg (a : RuntimeLong ): RuntimeLong = {
277
- val lo = a.lo
278
- val hi = a.hi
279
- new RuntimeLong (inline_lo_unary_-(lo), inline_hi_unary_-(lo, hi))
280
- }
281
-
282
271
@ inline
283
272
def add (a : RuntimeLong , b : RuntimeLong ): RuntimeLong = {
273
+ // Hacker's Delight, Section 2-16
284
274
val alo = a.lo
285
- val ahi = a.hi
286
- val bhi = b.hi
287
- val lo = alo + b.lo
275
+ val blo = b.lo
276
+ val lo = alo + blo
288
277
new RuntimeLong (lo,
289
- if (inlineUnsignedInt_<(lo, alo)) ahi + bhi + 1 else ahi + bhi )
278
+ a.hi + b.hi + ((( alo & blo) | ((alo | blo) & ~ lo)) >>> 31 ) )
290
279
}
291
280
292
281
@ inline
293
282
def sub (a : RuntimeLong , b : RuntimeLong ): RuntimeLong = {
283
+ /* Hacker's Delight, Section 2-16
284
+ *
285
+ * We deviate a bit from the original algorithm. Hacker's Delight uses
286
+ * `- (... >>> 31)`. Instead, we use `+ (... >> 31)`. These are equivalent,
287
+ * since `(x >> 31) == -(x >>> 31)` for all x. The variant with `+` folds
288
+ * better when `a.hi` and `b.hi` are both known to be 0. This happens in
289
+ * practice when `a` and `b` are 0-extended from `Int` values.
290
+ */
294
291
val alo = a.lo
295
- val ahi = a.hi
296
- val bhi = b.hi
297
- val lo = alo - b.lo
292
+ val blo = b.lo
293
+ val lo = alo - blo
298
294
new RuntimeLong (lo,
299
- if (inlineUnsignedInt_>(lo, alo)) ahi - bhi - 1 else ahi - bhi )
295
+ a.hi - b.hi + ((( ~ alo & blo) | ( ~ (alo ^ blo) & lo)) >> 31 ) )
300
296
}
301
297
302
298
@ inline
@@ -548,7 +544,8 @@ object RuntimeLong {
548
544
if (isInt32(lo, hi)) {
549
545
lo.toString()
550
546
} else if (hi < 0 ) {
551
- " -" + toUnsignedString(inline_lo_unary_-(lo), inline_hi_unary_-(lo, hi))
547
+ val neg = inline_negate(lo, hi)
548
+ " -" + toUnsignedString(neg.lo, neg.hi)
552
549
} else {
553
550
toUnsignedString(lo, hi)
554
551
}
@@ -656,8 +653,8 @@ object RuntimeLong {
656
653
private def toDouble (lo : Int , hi : Int ): Double = {
657
654
if (hi < 0 ) {
658
655
// We do asUint() on the hi part specifically for MinValue
659
- - (asUint(inline_hi_unary_-( lo, hi)) * TwoPow32 +
660
- asUint(inline_lo_unary_-(lo) ))
656
+ val neg = inline_negate( lo, hi)
657
+ - (asUint(neg.hi) * TwoPow32 + asUint(neg.lo ))
661
658
} else {
662
659
hi * TwoPow32 + asUint(lo)
663
660
}
@@ -900,7 +897,7 @@ object RuntimeLong {
900
897
val bAbs = inline_abs(blo, bhi)
901
898
val absRLo = unsigned_/(aAbs.lo, aAbs.hi, bAbs.lo, bAbs.hi)
902
899
if ((ahi ^ bhi) >= 0 ) absRLo // a and b have the same sign bit
903
- else inline_hiReturn_unary_- (absRLo, hiReturn)
900
+ else inline_negate_hiReturn (absRLo, hiReturn)
904
901
}
905
902
}
906
903
@@ -993,7 +990,7 @@ object RuntimeLong {
993
990
val aAbs = inline_abs(alo, ahi)
994
991
val bAbs = inline_abs(blo, bhi)
995
992
val absRLo = unsigned_%(aAbs.lo, aAbs.hi, bAbs.lo, bAbs.hi)
996
- if (ahi < 0 ) inline_hiReturn_unary_- (absRLo, hiReturn)
993
+ if (ahi < 0 ) inline_negate_hiReturn (absRLo, hiReturn)
997
994
else absRLo
998
995
}
999
996
}
@@ -1124,12 +1121,6 @@ object RuntimeLong {
1124
1121
}
1125
1122
}
1126
1123
1127
- @ inline
1128
- private def inline_hiReturn_unary_- (lo : Int , hi : Int ): Int = {
1129
- hiReturn = inline_hi_unary_-(lo, hi)
1130
- inline_lo_unary_-(lo)
1131
- }
1132
-
1133
1124
@ inline
1134
1125
private def substring (s : String , start : Int ): String = {
1135
1126
import scala .scalajs .js .JSStringOps .enableJSStringOps
@@ -1222,17 +1213,20 @@ object RuntimeLong {
1222
1213
(a ^ 0x80000000 ) >= (b ^ 0x80000000 )
1223
1214
1224
1215
@ inline
1225
- def inline_lo_unary_- (lo : Int ) : Int =
1226
- - lo
1216
+ def inline_negate (lo : Int , hi : Int ) : RuntimeLong =
1217
+ sub( new RuntimeLong ( 0 , 0 ), new RuntimeLong (lo, hi))
1227
1218
1228
1219
@ inline
1229
- def inline_hi_unary_- (lo : Int , hi : Int ): Int =
1230
- if (lo != 0 ) ~ hi else - hi
1220
+ def inline_negate_hiReturn (lo : Int , hi : Int ): Int = {
1221
+ val n = inline_negate(lo, hi)
1222
+ hiReturn = n.hi
1223
+ n.lo
1224
+ }
1231
1225
1232
1226
@ inline
1233
1227
def inline_abs (lo : Int , hi : Int ): RuntimeLong = {
1234
1228
if (hi < 0 )
1235
- new RuntimeLong (inline_lo_unary_-(lo), inline_hi_unary_-(lo, hi) )
1229
+ inline_negate(lo, hi )
1236
1230
else
1237
1231
new RuntimeLong (lo, hi)
1238
1232
}
0 commit comments