Skip to content

Commit 80a77a6

Browse files
committed
Make sure all integer ops return smallest representation, patch from Christophe Grand
fixed inc/dec long for max/min values
1 parent 49063a9 commit 80a77a6

File tree

1 file changed

+160
-6
lines changed

1 file changed

+160
-6
lines changed

src/jvm/clojure/lang/Numbers.java

Lines changed: 160 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ static interface Ops{
2929

3030
Ops opsWith(IntegerOps x);
3131

32+
Ops opsWith(LongOps x);
33+
3234
Ops opsWith(FloatOps x);
3335

3436
Ops opsWith(DoubleOps x);
@@ -265,10 +267,11 @@ else if(x instanceof BigDecimal)
265267
}
266268

267269
static public Number reduce(BigInteger val){
268-
if(val.bitLength() < 32)
270+
int bitLength = val.bitLength();
271+
if(bitLength < 32)
269272
return val.intValue();
270-
// else if(val.bitLength() < 64)
271-
// return val.longValue();
273+
else if(bitLength < 64)
274+
return val.longValue();
272275
else
273276
return val;
274277
}
@@ -357,6 +360,10 @@ final public Ops opsWith(IntegerOps x){
357360
return this;
358361
}
359362

363+
final public Ops opsWith(LongOps x){
364+
return LONG_OPS;
365+
}
366+
360367
final public Ops opsWith(FloatOps x){
361368
return FLOAT_OPS;
362369
}
@@ -468,6 +475,132 @@ public Number dec(Number x){
468475
}
469476
}
470477

478+
final static class LongOps implements Ops{
479+
public Ops combine(Ops y){
480+
return y.opsWith(this);
481+
}
482+
483+
final public Ops opsWith(IntegerOps x){
484+
return this;
485+
}
486+
487+
final public Ops opsWith(LongOps x){
488+
return this;
489+
}
490+
491+
final public Ops opsWith(FloatOps x){
492+
return FLOAT_OPS;
493+
}
494+
495+
final public Ops opsWith(DoubleOps x){
496+
return DOUBLE_OPS;
497+
}
498+
499+
final public Ops opsWith(RatioOps x){
500+
return RATIO_OPS;
501+
}
502+
503+
final public Ops opsWith(BigIntegerOps x){
504+
return BIGINTEGER_OPS;
505+
}
506+
507+
final public Ops opsWith(BigDecimalOps x){
508+
return BIGDECIMAL_OPS;
509+
}
510+
511+
public boolean isZero(Number x){
512+
return x.longValue() == 0;
513+
}
514+
515+
public boolean isPos(Number x){
516+
return x.longValue() > 0;
517+
}
518+
519+
public boolean isNeg(Number x){
520+
return x.longValue() < 0;
521+
}
522+
523+
final public Number add(Number x, Number y){
524+
long lx = x.longValue(), ly = y.longValue();
525+
long ret = lx + ly;
526+
if ((ret ^ lx) < 0 && (ret ^ ly) < 0)
527+
return BIGINTEGER_OPS.add(x, y);
528+
return ret;
529+
}
530+
531+
final public Number multiply(Number x, Number y){
532+
long lx = x.longValue(), ly = y.longValue();
533+
long ret = lx * ly;
534+
if (ly != 0 && ret/ly != lx)
535+
return BIGINTEGER_OPS.multiply(x, y);
536+
return ret;
537+
}
538+
539+
static long gcd(long u, long v){
540+
while(v != 0)
541+
{
542+
long r = u % v;
543+
u = v;
544+
v = r;
545+
}
546+
return u;
547+
}
548+
549+
public Number divide(Number x, Number y){
550+
long n = x.longValue();
551+
long val = y.longValue();
552+
long gcd = gcd(n, val);
553+
if(gcd == 0)
554+
return 0;
555+
556+
n = n / gcd;
557+
long d = val / gcd;
558+
if(d == 1)
559+
return n;
560+
if(d < 0)
561+
{
562+
n = -n;
563+
d = -d;
564+
}
565+
return new Ratio(BigInteger.valueOf(n), BigInteger.valueOf(d));
566+
}
567+
568+
public Number quotient(Number x, Number y){
569+
return x.longValue() / y.longValue();
570+
}
571+
572+
public Number remainder(Number x, Number y){
573+
return x.longValue() % y.longValue();
574+
}
575+
576+
public boolean equiv(Number x, Number y){
577+
return x.longValue() == y.longValue();
578+
}
579+
580+
public boolean lt(Number x, Number y){
581+
return x.longValue() < y.longValue();
582+
}
583+
584+
//public Number subtract(Number x, Number y);
585+
final public Number negate(Number x){
586+
return -x.longValue();
587+
}
588+
589+
public Number inc(Number x){
590+
long val = x.longValue();
591+
if(val < Long.MAX_VALUE)
592+
return val + 1;
593+
return BIGINTEGER_OPS.inc(x);
594+
}
595+
596+
public Number dec(Number x){
597+
long val = x.longValue();
598+
if(val > Long.MIN_VALUE)
599+
return val - 1;
600+
return BIGINTEGER_OPS.dec(x);
601+
}
602+
}
603+
471604
final static class FloatOps implements Ops{
472605
public Ops combine(Ops y){
473606
return y.opsWith(this);
@@ -477,6 +610,10 @@ final public Ops opsWith(IntegerOps x){
477610
return this;
478611
}
479612

613+
final public Ops opsWith(LongOps x){
614+
return this;
615+
}
616+
480617
final public Ops opsWith(FloatOps x){
481618
return this;
482619
}
@@ -560,6 +697,10 @@ final public Ops opsWith(IntegerOps x){
560697
return this;
561698
}
562699

700+
final public Ops opsWith(LongOps x){
701+
return this;
702+
}
703+
563704
final public Ops opsWith(FloatOps x){
564705
return this;
565706
}
@@ -643,6 +784,10 @@ final public Ops opsWith(IntegerOps x){
643784
return this;
644785
}
645786

787+
final public Ops opsWith(LongOps x){
788+
return this;
789+
}
790+
646791
final public Ops opsWith(FloatOps x){
647792
return FLOAT_OPS;
648793
}
@@ -754,6 +899,10 @@ final public Ops opsWith(IntegerOps x){
754899
return this;
755900
}
756901

902+
final public Ops opsWith(LongOps x){
903+
return this;
904+
}
905+
757906
final public Ops opsWith(FloatOps x){
758907
return FLOAT_OPS;
759908
}
@@ -844,6 +993,10 @@ final public Ops opsWith(IntegerOps x){
844993
return this;
845994
}
846995

996+
final public Ops opsWith(LongOps x){
997+
return this;
998+
}
999+
8471000
final public Ops opsWith(FloatOps x){
8481001
return FLOAT_OPS;
8491002
}
@@ -1180,6 +1333,7 @@ public Number shiftRight(Number x, int n){
11801333
}
11811334

11821335
static final IntegerOps INTEGER_OPS = new IntegerOps();
1336+
static final LongOps LONG_OPS = new LongOps();
11831337
static final FloatOps FLOAT_OPS = new FloatOps();
11841338
static final DoubleOps DOUBLE_OPS = new DoubleOps();
11851339
static final RatioOps RATIO_OPS = new RatioOps();
@@ -1202,7 +1356,7 @@ else if(xc == Float.class)
12021356
else if(xc == BigInteger.class)
12031357
return BIGINTEGER_OPS;
12041358
else if(xc == Long.class)
1205-
return BIGINTEGER_OPS;
1359+
return LONG_OPS;
12061360
else if(xc == Ratio.class)
12071361
return RATIO_OPS;
12081362
else if(xc == BigDecimal.class)
@@ -1699,13 +1853,13 @@ static public long minus(long x){
16991853
}
17001854

17011855
static public long inc(long x){
1702-
if(x == Integer.MAX_VALUE)
1856+
if(x == Long.MAX_VALUE)
17031857
return throwIntOverflow();
17041858
return x + 1;
17051859
}
17061860

17071861
static public long dec(long x){
1708-
if(x == Integer.MIN_VALUE)
1862+
if(x == Long.MIN_VALUE)
17091863
return throwIntOverflow();
17101864
return x - 1;
17111865
}

0 commit comments

Comments
 (0)