Project

Profile

Help

Revision 34a8541f

Added by Michael Kay almost 13 years ago

Fix bug 2510104 - multiplying large integers

View differences:

latest9.1/bj/net/sf/saxon/value/Int64Value.java
539 539
    public IntegerValue times(IntegerValue other) {
540 540
        // if either of the values is large, we use BigInteger arithmetic to be on the safe side
541 541
        if (other instanceof Int64Value) {
542
            long topa = value >> 32;
543
            if (topa != 0 && topa != 0xffffffff) {
544
                return new BigIntegerValue(value).times(new BigIntegerValue(((Int64Value)other).value));
545
            }
546
            long topb = (((Int64Value)other).value >> 32);
547
            if (topb != 0 && topb != 0xffffffff) {
542
            if (isLong() || ((Int64Value)other).isLong()) {
548 543
                return new BigIntegerValue(value).times(new BigIntegerValue(((Int64Value)other).value));
544
            } else {
545
                return makeIntegerValue(value * ((Int64Value)other).value);
549 546
            }
550
            return makeIntegerValue(value * ((Int64Value)other).value);
551 547
        } else {
552 548
            return new BigIntegerValue(value).times(other);
553 549
        }
......
560 556
    public NumericValue div(IntegerValue other) throws XPathException {
561 557
        // if either of the values is large, we use BigInteger arithmetic to be on the safe side
562 558
        if (other instanceof Int64Value) {
563
            long topa = value >> 32;
564
            if (topa != 0 && topa != 0xffffffff) {
565
                return new BigIntegerValue(value).div(new BigIntegerValue(((Int64Value)other).value));
559
            long quotient = ((Int64Value)other).value;
560
            if (quotient == 0) {
561
                throw new XPathException("Integer division by zero", "FOAR0001");
566 562
            }
567
            long topb = ((Int64Value)other).value >> 32;
568
            if (topb != 0 && topb != 0xffffffff) {
569
                return new BigIntegerValue(value).div(new BigIntegerValue(((Int64Value)other).value));
563
            if (isLong() || ((Int64Value)other).isLong()) {
564
                return new BigIntegerValue(value).div(new BigIntegerValue(quotient));
570 565
            }
566

  
571 567
            // the result of dividing two integers is a decimal; but if
572 568
            // one divides exactly by the other, we implement it as an integer
573
            long quotient = ((Int64Value) other).value;
574
            if (quotient == 0) {
575
                throw new XPathException("Integer division by zero", "FOAR0001");
576
            }
577 569
            if (value % quotient == 0) {
578 570
                return makeIntegerValue(value / quotient);
579
            }
580
            return (NumericValue)Calculator.DECIMAL_DECIMAL[Calculator.DIV].compute(
571
            } else {
572
                return (NumericValue)Calculator.DECIMAL_DECIMAL[Calculator.DIV].compute(
581 573
                            new DecimalValue(value), new DecimalValue(quotient), null);
574
            }
582 575
        } else {
583 576
            return new BigIntegerValue(value).div(other);
584 577
        }
......
591 584
    public IntegerValue mod(IntegerValue other) throws XPathException {
592 585
        // if either of the values is large, we use BigInteger arithmetic to be on the safe side
593 586
        if (other instanceof Int64Value) {
594
            long topa = value >> 32;
595
            if (topa != 0 && topa != 0xffffffff) {
596
                return new BigIntegerValue(value).mod(new BigIntegerValue(((Int64Value)other).value));
597
            }
598 587
            long quotient = ((Int64Value) other).value;
599 588
            if (quotient == 0) {
600 589
                throw new XPathException("Integer modulo zero", "FOAR0001");
601 590
            }
602
            long topb = quotient >> 32;
603
            if (topb != 0 && topb != 0xffffffff) {       
591
            if (isLong() || ((Int64Value)other).isLong()) {
604 592
                return new BigIntegerValue(value).mod(new BigIntegerValue(((Int64Value)other).value));
593
            } else {
594
                return makeIntegerValue(value % quotient);
605 595
            }
606
            return makeIntegerValue(value % quotient);
607 596
        } else {
608 597
            return new BigIntegerValue(value).mod(other);
609 598
        }
......
616 605
    public IntegerValue idiv(IntegerValue other) throws XPathException {
617 606
       // if either of the values is large, we use BigInteger arithmetic to be on the safe side
618 607
        if (other instanceof Int64Value) {
619
            long topa = (value >> 32);
620
            if (topa != 0 && topa != 0xffffffff) {
621
                return new BigIntegerValue(value).idiv(new BigIntegerValue(((Int64Value)other).value));
622
            }
623
            long topb = (((Int64Value)other).value >> 32);
624
            if (topb != 0 && topb != 0xffffffff) {
608
            if (isLong() || ((Int64Value)other).isLong()) {
625 609
                return new BigIntegerValue(value).idiv(new BigIntegerValue(((Int64Value)other).value));
626 610
            }
627 611
            try {
......
637 621
            }
638 622
        } else {
639 623
            return new BigIntegerValue(value).idiv(other);
640
        }        
624
        }
625
    }
626

  
627
    /**
628
     * Test whether this value needs a long to hold it. Specifically, whether
629
     * the absolute value is > 2^31.
630
     */
631

  
632
    private boolean isLong() {
633
        long top = value >> 31;
634
        return top != 0 && top != 0x1ffffffffL;
641 635
    }
642 636

  
643 637
    /**

Also available in: Unified diff