Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha Premium Member lorezyra's Avatar
    Join Date
    Dec 2007
    Location
    Japan -- 日本
    Posts
    638
    Vote Rating
    18
    lorezyra will become famous soon enough lorezyra will become famous soon enough

      0  

    Default ExtJS does not handle LARGE numbers

    ExtJS does not handle LARGE numbers


    As JavaScript does not handle very large numbers very well...
    JavaScript only stores 53 significant bits, and then it uses some
    more bits to tell how many zeroes comes after those.

    That is why
    Math.pow(2,52) != Math.pow(2,52)+1
    but
    Math.pow(2,53) == Math.pow(2,53)+1

    It needs 54 bits to represent 2^53+1 precisely. Since there are only 53 bits
    available, the least significant bit is lost.

    (There are some extra details about how the bits are really used, but
    I think they would only confuze matters here
    I recommend that we add BigInteger into the framework.

    From: https://github.com/silentmatt/javasc.../biginteger.js
    PHP Code:
    /*
        JavaScript BigInteger library version 0.9
        http://silentmatt.com/biginteger/

        Copyright (c) 2009 Matthew Crumley <email@matthewcrumley.com>
        Copyright (c) 2010,2011 by John Tobey <John.Tobey@gmail.com>
        Licensed under the MIT license.

        Support for arbitrary internal representation base was added by
        Vitaly Magerya.
    */
    /*
        File: biginteger.js

        Exports:

            <BigInteger>
    */
    /*
        Class: BigInteger
        An arbitrarily-large integer.

        <BigInteger> objects should be considered immutable. None of the "built-in"
        methods modify *this* or their arguments. All properties should be
        considered private.

        All the methods of <BigInteger> instances can be called "statically". The
        static versions are convenient if you don't already have a <BigInteger>
        object.

        As an example, these calls are equivalent.

        > BigInteger(4).multiply(5); // returns BigInteger(20);
        > BigInteger.multiply(4, 5); // returns BigInteger(20);

        > var a = 42;
        > var a = BigInteger.toJSValue("0b101010"); // Not completely useless...
    */
    // IE doesn't support Array.prototype.map
    if (!Array.prototype.map) {
        Array.
    prototype.map = function (fun /*, thisp*/ ) {
            var 
    len this.length >>> 0;
            if (
    typeof fun !== "function") {
                throw new 
    TypeError();
            }

            var 
    res = new Array(len);
            var 
    thisp arguments[1];
            for (var 
    0leni++) {
                if (
    i in this) {
                    
    res[i] = fun.call(thispthis[i], ithis);
                }
            }

            return 
    res;
        };
    }

    /*
        Constructor: BigInteger()
        Convert a value to a <BigInteger>.

        Although <BigInteger()> is the constructor for <BigInteger> objects, it is
        best not to call it as a constructor. If *n* is a <BigInteger> object, it is
        simply returned as-is. Otherwise, <BigInteger()> is equivalent to <parse>
        without a radix argument.

        > var n0 = BigInteger();      // Same as <BigInteger.ZERO>
        > var n1 = BigInteger("123"); // Create a new <BigInteger> with value 123
        > var n2 = BigInteger(123);   // Create a new <BigInteger> with value 123
        > var n3 = BigInteger(n2);    // Return n2, unchanged

        The constructor form only takes an array and a sign. *n* must be an
        array of numbers in little-endian order, where each digit is between 0
        and BigInteger.base.  The second parameter sets the sign: -1 for
        negative, +1 for positive, or 0 for zero. The array is *not copied and
        may be modified*. If the array contains only zeros, the sign parameter
        is ignored and is forced to zero.

        > new BigInteger([5], -1): create a new BigInteger with value -5

        Parameters:

            n - Value to convert to a <BigInteger>.

        Returns:

            A <BigInteger> value.

        See Also:

            <parse>, <BigInteger>
    */
    function BigInteger(ns) {
        if (!(
    this instanceof BigInteger)) {
            if (
    instanceof BigInteger) {
                return 
    n;
            } else if (
    typeof n === "undefined") {
                return 
    BigInteger.ZERO;
            }
            return 
    BigInteger.parse(n);
        }

        
    || []; // Provide the nullary constructor for subclasses.
        
    while (n.length && !n[n.length 1]) {
            --
    n.length;
        }
        
    this._d n;
        
    this._s n.length ? (|| 1) : 0;
    }

    // Base-10 speedup hacks in parse, toString, exp10 and log functions
    // require base to be a power of 10. 10^7 is the largest such power
    // that won't cause a precision loss when digits are multiplied.
    BigInteger.base 10000000;
    BigInteger.base_log10 7;

    // Constant: ZERO
    // <BigInteger> 0.
    BigInteger.ZERO = new BigInteger([], 0);

    // Constant: ONE
    // <BigInteger> 1.
    BigInteger.ONE = new BigInteger([1], 1);

    // Constant: M_ONE
    // <BigInteger> -1.
    BigInteger.M_ONE = new BigInteger(BigInteger.ONE._d, -1);

    // Constant: _0
    // Shortcut for <ZERO>.
    BigInteger._0 BigInteger.ZERO;

    // Constant: _1
    // Shortcut for <ONE>.
    BigInteger._1 BigInteger.ONE;

    /*
        Constant: small
        Array of <BigIntegers> from 0 to 36.

        These are used internally for parsing, but useful when you need a "small"
        <BigInteger>.

        See Also:

            <ZERO>, <ONE>, <_0>, <_1>
    */
    BigInteger.small = [
    BigInteger.ZEROBigInteger.ONE,
    /* Assuming BigInteger.base > 36 */
    new BigInteger([2], 1), new BigInteger([3], 1), new BigInteger([4], 1), new BigInteger([5], 1), new BigInteger([6], 1), new BigInteger([7], 1), new BigInteger([8], 1), new BigInteger([9], 1), new BigInteger([10], 1), new BigInteger([11], 1), new BigInteger([12], 1), new BigInteger([13], 1), new BigInteger([14], 1), new BigInteger([15], 1), new BigInteger([16], 1), new BigInteger([17], 1), new BigInteger([18], 1), new BigInteger([19], 1), new BigInteger([20], 1), new BigInteger([21], 1), new BigInteger([22], 1), new BigInteger([23], 1), new BigInteger([24], 1), new BigInteger([25], 1), new BigInteger([26], 1), new BigInteger([27], 1), new BigInteger([28], 1), new BigInteger([29], 1), new BigInteger([30], 1), new BigInteger([31], 1), new BigInteger([32], 1), new BigInteger([33], 1), new BigInteger([34], 1), new BigInteger([35], 1), new BigInteger([36], 1)];

    // Used for parsing/radix conversion
    BigInteger.digits "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");

    /*
        Method: toString
        Convert a <BigInteger> to a string.

        When *base* is greater than 10, letters are upper case.

        Parameters:

            base - Optional base to represent the number in (default is base 10).
                   Must be between 2 and 36 inclusive, or an Error will be thrown.

        Returns:

            The string representation of the <BigInteger>.
    */
    BigInteger.prototype.toString = function (base) {
        
    base = +base || 10;
        if (
    base || base 36) {
            throw new 
    Error("illegal radix " base ".");
        }
        if (
    this._s === 0) {
            return 
    "0";
        }
        if (
    base === 10) {
            var 
    str this._s "-" "";
            
    str += this._d[this._d.length 1].toString();
            for (var 
    this._d.length 2>= 0i--) {
                var 
    group this._d[i].toString();
                while (
    group.length BigInteger.base_log10group '0' group;
                
    str += group;
            }
            return 
    str;
        } else {
            var 
    numerals BigInteger.digits;
            
    base BigInteger.small[base];
            var 
    sign this._s;

            var 
    this.abs();
            var 
    digits = [];
            var 
    digit;

            while (
    n._s !== 0) {
                var 
    divmod n.divRem(base);
                
    divmod[0];
                
    digit divmod[1];
                
    // TODO: This could be changed to unshift instead of reversing at the end.
                // Benchmark both to compare speeds.
                
    digits.push(numerals[digit.valueOf()]);
            }
            return (
    sign "-" "") + digits.reverse().join("");
        }
    };

    // Verify strings for parsing
    BigInteger.radixRegex = [/^$/, /^$/, /^[01]*$/, /^[012]*$/, /^[0-3]*$/, /^[0-4]*$/, /^[0-5]*$/, /^[0-6]*$/, /^[0-7]*$/, /^[0-8]*$/, /^[0-9]*$/, /^[0-9aA]*$/, /^[0-9abAB]*$/, /^[0-9abcABC]*$/, /^[0-9a-dA-D]*$/, /^[0-9a-eA-E]*$/, /^[0-9a-fA-F]*$/, /^[0-9a-gA-G]*$/, /^[0-9a-hA-H]*$/, /^[0-9a-iA-I]*$/, /^[0-9a-jA-J]*$/, /^[0-9a-kA-K]*$/, /^[0-9a-lA-L]*$/, /^[0-9a-mA-M]*$/, /^[0-9a-nA-N]*$/, /^[0-9a-oA-O]*$/, /^[0-9a-pA-P]*$/, /^[0-9a-qA-Q]*$/, /^[0-9a-rA-R]*$/, /^[0-9a-sA-S]*$/, /^[0-9a-tA-T]*$/, /^[0-9a-uA-U]*$/, /^[0-9a-vA-V]*$/, /^[0-9a-wA-W]*$/, /^[0-9a-xA-X]*$/, /^[0-9a-yA-Y]*$/, /^[0-9a-zA-Z]*$/];

    /*
        Function: parse
        Parse a string into a <BigInteger>.

        *base* is optional but, if provided, must be from 2 to 36 inclusive. If
        *base* is not provided, it will be guessed based on the leading characters
        of *s* as follows:

        - "0x" or "0X": *base* = 16
        - "0c" or "0C": *base* = 8
        - "0b" or "0B": *base* = 2
        - else: *base* = 10

        If no base is provided, or *base* is 10, the number can be in exponential
        form. For example, these are all valid:

        > BigInteger.parse("1e9");              // Same as "1000000000"
        > BigInteger.parse("1.234*10^3");       // Same as 1234
        > BigInteger.parse("56789 * 10 ** -2"); // Same as 567

        If any characters fall outside the range defined by the radix, an exception
        will be thrown.

        Parameters:

            s - The string to parse.
            base - Optional radix (default is to guess based on *s*).

        Returns:

            a <BigInteger> instance.
    */
    BigInteger.parse = function (sbase) {
        
    // Expands a number in exponential form to decimal form.
        // expandExponential("-13.441*10^5") === "1344100";
        // expandExponential("1.12300e-1") === "0.112300";
        // expandExponential(1000000000000000000000000000000) === "1000000000000000000000000000000";
        
    function expandExponential(str) {
            
    str str.replace(/\s*[*xX]\s*10\s*(\^|\*\*)\s*/, "e");

            return 
    str.replace(/^([+\-])?(\d+)\.?(\d*)[eE]([+\-]?\d+)$/, function (xsnfc) {
                
    = +c;
                var 
    0;
                var 
    n.length c;
                
    = (f).length;
                
    = ((Math.abs(c)) >= 0);
                var 
    = (new Array(1)).join("0");
                var 
    f;
                return (
    || "") + (+= z).substr(0+= z.length 0) + (r.length "." r.substr(i) : "");
            });
        }

        
    s.toString();
        if (
    typeof base === "undefined" || +base === 10) {
            
    expandExponential(s);
        }

        var 
    parts = /^([+\-]?)(0[xXcCbB])?([0-9A-Za-z]*)(?:\.\d*)?$/.exec(s);
        if (
    parts) {
            var 
    sign parts[1] || "+";
            var 
    baseSection parts[2] || "";
            var 
    digits parts[3] || "";

            if (
    typeof base === "undefined") {
                
    // Guess base
                
    if (baseSection === "0x" || baseSection === "0X") { // Hex
                    
    base 16;
                } else if (
    baseSection === "0c" || baseSection === "0C") { // Octal
                    
    base 8;
                } else if (
    baseSection === "0b" || baseSection === "0B") { // Binary
                    
    base 2;
                } else {
                    
    base 10;
                }
            } else if (
    base || base 36) {
                throw new 
    Error("Illegal radix " base ".");
            }

            
    base = +base;

            
    // Check for digits outside the range
            
    if (!(BigInteger.radixRegex[base].test(digits))) {
                throw new 
    Error("Bad digit for radix " base);
            }

            
    // Strip leading zeros, and convert to array
            
    digits digits.replace(/^0+/, "").split("");
            if (
    digits.length === 0) {
                return 
    BigInteger.ZERO;
            }

            
    // Get the sign (we know it's not zero)
            
    sign = (sign === "-") ? -1;

            
    // Optimize 10
            
    if (base == 10) {
                var 
    = [];
                while (
    digits.length >= BigInteger.base_log10) {
                    
    d.push(parseInt(digits.splice(-BigInteger.base_log10).join(''), 10));
                }
                
    d.push(parseInt(digits.join(''), 10));
                return new 
    BigInteger(dsign);
            }

            
    // Optimize base
            
    if (base === BigInteger.base) {
                return new 
    BigInteger(digits.map(Number).reverse(), sign);
            }

            
    // Do the conversion
            
    var BigInteger.ZERO;
            
    base BigInteger.small[base];
            var 
    small BigInteger.small;
            for (var 
    0digits.lengthi++) {
                
    d.multiply(base).add(small[parseInt(digits[i], 36)]);
            }
            return new 
    BigInteger(d._dsign);
        } else {
            throw new 
    Error("Invalid BigInteger format: " s);
        }
    };

    /*
        Function: add
        Add two <BigIntegers>.

        Parameters:

            n - The number to add to *this*. Will be converted to a <BigInteger>.

        Returns:

            The numbers added together.

        See Also:

            <subtract>, <multiply>, <quotient>, <next>
    */
    BigInteger.prototype.add = function (n) {
        if (
    this._s === 0) {
            return 
    BigInteger(n);
        }

        
    BigInteger(n);
        if (
    n._s === 0) {
            return 
    this;
        }
        if (
    this._s !== n._s) {
            
    n.negate();
            return 
    this.subtract(n);
        }

        var 
    this._d;
        var 
    n._d;
        var 
    al a.length;
        var 
    bl b.length;
        var 
    sum = new Array(Math.max(albl) + 1);
        var 
    size Math.min(albl);
        var 
    carry 0;
        var 
    digit;

        for (var 
    0sizei++) {
            
    digit a[i] + b[i] + carry;
            
    sum[i] = digit BigInteger.base;
            
    carry = (digit BigInteger.base) | 0;
        }
        if (
    bl al) {
            
    b;
            
    al bl;
        }
        for (
    sizecarry && ali++) {
            
    digit a[i] + carry;
            
    sum[i] = digit BigInteger.base;
            
    carry = (digit BigInteger.base) | 0;
        }
        if (
    carry) {
            
    sum[i] = carry;
        }

        for (; 
    ali++) {
            
    sum[i] = a[i];
        }

        return new 
    BigInteger(sumthis._s);
    };

    /*
        Function: negate
        Get the additive inverse of a <BigInteger>.

        Returns:

            A <BigInteger> with the same magnatude, but with the opposite sign.

        See Also:

            <abs>
    */
    BigInteger.prototype.negate = function () {
        return new 
    BigInteger(this._d, -this._s);
    };

    /*
        Function: abs
        Get the absolute value of a <BigInteger>.

        Returns:

            A <BigInteger> with the same magnatude, but always positive (or zero).

        See Also:

            <negate>
    */
    BigInteger.prototype.abs = function () {
        return (
    this._s 0) ? this.negate() : this;
    };

    /*
        Function: subtract
        Subtract two <BigIntegers>.

        Parameters:

            n - The number to subtract from *this*. Will be converted to a <BigInteger>.

        Returns:

            The *n* subtracted from *this*.

        See Also:

            <add>, <multiply>, <quotient>, <prev>
    */
    BigInteger.prototype.subtract = function (n) {
        if (
    this._s === 0) {
            return 
    BigInteger(n).negate();
        }

        
    BigInteger(n);
        if (
    n._s === 0) {
            return 
    this;
        }
        if (
    this._s !== n._s) {
            
    n.negate();
            return 
    this.add(n);
        }

        var 
    this;
        var 
    t;
        
    // negative - negative => -|a| - -|b| => -|a| + |b| => |b| - |a|
        
    if (this._s 0) {
            
    m;
            
    = new BigInteger(n._d1);
            
    = new BigInteger(t._d1);
        }

        
    // Both are positive => a - b
        
    var sign m.compareAbs(n);
        if (
    sign === 0) {
            return 
    BigInteger.ZERO;
        } else if (
    sign 0) {
            
    // swap m and n
            
    n;
            
    m;
            
    t;
        }

        
    // a > b
        
    var m._d;
        var 
    n._d;
        var 
    al a.length;
        var 
    bl b.length;
        var 
    diff = new Array(al); // al >= bl since a > b
        
    var borrow 0;
        var 
    i;
        var 
    digit;

        for (
    0bli++) {
            
    digit a[i] - borrow b[i];
            if (
    digit 0) {
                
    digit += BigInteger.base;
                
    borrow 1;
            } else {
                
    borrow 0;
            }
            
    diff[i] = digit;
        }
        for (
    blali++) {
            
    digit a[i] - borrow;
            if (
    digit 0) {
                
    digit += BigInteger.base;
            } else {
                
    diff[i++] = digit;
                break;
            }
            
    diff[i] = digit;
        }
        for (; 
    ali++) {
            
    diff[i] = a[i];
        }

        return new 
    BigInteger(diffsign);
    };

    (function () {
        function 
    addOne(nsign) {
            var 
    n._d;
            var 
    sum a.slice();
            var 
    carry true;
            var 
    0;

            while (
    true) {
                var 
    digit = (a[i] || 0) + 1;
                
    sum[i] = digit BigInteger.base;
                if (
    digit <= BigInteger.base 1) {
                    break;
                }++
    i;
            }

            return new 
    BigInteger(sumsign);
        }

        function 
    subtractOne(nsign) {
            var 
    n._d;
            var 
    sum a.slice();
            var 
    borrow true;
            var 
    0;

            while (
    true) {
                var 
    digit = (a[i] || 0) - 1;
                if (
    digit 0) {
                    
    sum[i] = digit BigInteger.base;
                } else {
                    
    sum[i] = digit;
                    break;
                }++
    i;
            }

            return new 
    BigInteger(sumsign);
        }

        
    /*
            Function: next
            Get the next <BigInteger> (add one).

            Returns:

                *this* + 1.

            See Also:

                <add>, <prev>
        */
        
    BigInteger.prototype.next = function () {
            switch (
    this._s) {
            case 
    0:
                return 
    BigInteger.ONE;
            case -
    1:
                return 
    subtractOne(this, -1);
                
    // case 1:
            
    default:
                return 
    addOne(this1);
            }
        };

        
    /*
            Function: prev
            Get the previous <BigInteger> (subtract one).

            Returns:

                *this* - 1.

            See Also:

                <next>, <subtract>
        */
        
    BigInteger.prototype.prev = function () {
            switch (
    this._s) {
            case 
    0:
                return 
    BigInteger.M_ONE;
            case -
    1:
                return 
    addOne(this, -1);
                
    // case 1:
            
    default:
                return 
    subtractOne(this1);
            }
        };
    })();

    /*
        Function: compareAbs
        Compare the absolute value of two <BigIntegers>.

        Calling <compareAbs> is faster than calling <abs> twice, then <compare>.

        Parameters:

            n - The number to compare to *this*. Will be converted to a <BigInteger>.

        Returns:

            -1, 0, or +1 if *|this|* is less than, equal to, or greater than *|n|*.

        See Also:

            <compare>, <abs>
    */
    BigInteger.prototype.compareAbs = function (n) {
        if (
    this === n) {
            return 
    0;
        }

        if (!(
    instanceof BigInteger)) {
            if (!
    isFinite(n)) {
                return (
    isNaN(n) ? : -1);
            }
            
    BigInteger(n);
        }

        if (
    this._s === 0) {
            return (
    n._s !== 0) ? -0;
        }
        if (
    n._s === 0) {
            return 
    1;
        }

        var 
    this._d.length;
        var 
    nl n._d.length;
        if (
    nl) {
            return -
    1;
        } else if (
    nl) {
            return 
    1;
        }

        var 
    this._d;
        var 
    n._d;
        for (var 
    1>= 0i--) {
            if (
    a[i] !== b[i]) {
                return 
    a[i] < b[i] ? -1;
            }
        }

        return 
    0;
    };

    /*
        Function: compare
        Compare two <BigIntegers>.

        Parameters:

            n - The number to compare to *this*. Will be converted to a <BigInteger>.

        Returns:

            -1, 0, or +1 if *this* is less than, equal to, or greater than *n*.

        See Also:

            <compareAbs>, <isPositive>, <isNegative>, <isUnit>
    */
    BigInteger.prototype.compare = function (n) {
        if (
    this === n) {
            return 
    0;
        }

        
    BigInteger(n);

        if (
    this._s === 0) {
            return -
    n._s;
        }

        if (
    this._s === n._s) { // both positive or both negative
            
    var cmp this.compareAbs(n);
            return 
    cmp this._s;
        } else {
            return 
    this._s;
        }
    };

    /*
        Function: isUnit
        Return true iff *this* is either 1 or -1.

        Returns:

            true if *this* compares equal to <BigInteger.ONE> or <BigInteger.M_ONE>.

        See Also:

            <isZero>, <isNegative>, <isPositive>, <compareAbs>, <compare>,
            <BigInteger.ONE>, <BigInteger.M_ONE>
    */
    BigInteger.prototype.isUnit = function () {
        return 
    this === BigInteger.ONE || this === BigInteger.M_ONE || (this._d.length === && this._d[0] === 1);
    };

    /*
        Function: multiply
        Multiply two <BigIntegers>.

        Parameters:

            n - The number to multiply *this* by. Will be converted to a
            <BigInteger>.

        Returns:

            The numbers multiplied together.

        See Also:

            <add>, <subtract>, <quotient>, <square>
    */
    BigInteger.prototype.multiply = function (n) {
        
    // TODO: Consider adding Karatsuba multiplication for large numbers
        
    if (this._s === 0) {
            return 
    BigInteger.ZERO;
        }

        
    BigInteger(n);
        if (
    n._s === 0) {
            return 
    BigInteger.ZERO;
        }
        if (
    this.isUnit()) {
            if (
    this._s 0) {
                return 
    n.negate();
            }
            return 
    n;
        }
        if (
    n.isUnit()) {
            if (
    n._s 0) {
                return 
    this.negate();
            }
            return 
    this;
        }
        if (
    this === n) {
            return 
    this.square();
        }

        var 
    = (this._d.length >= n._d.length);
        var 
    = (this n)._d// a will be longer than b
        
    var = (this)._d;
        var 
    al a.length;
        var 
    bl b.length;

        var 
    pl al bl;
        var 
    partial = new Array(pl);
        var 
    i;
        for (
    0pli++) {
            
    partial[i] = 0;
        }

        for (
    0bli++) {
            var 
    carry 0;
            var 
    bi b[i];
            var 
    jlimit al i;
            var 
    digit;
            for (var 
    ijlimitj++) {
                
    digit partial[j] + bi a[i] + carry;
                
    carry = (digit BigInteger.base) | 0;
                
    partial[j] = (digit BigInteger.base) | 0;
            }
            if (
    carry) {
                
    digit partial[j] + carry;
                
    carry = (digit BigInteger.base) | 0;
                
    partial[j] = digit BigInteger.base;
            }
        }
        return new 
    BigInteger(partialthis._s n._s);
    };

    // Multiply a BigInteger by a single-digit native number
    // Assumes that this and n are >= 0
    // This is not really intended to be used outside the library itself
    BigInteger.prototype.multiplySingleDigit = function (n) {
        if (
    === || this._s === 0) {
            return 
    BigInteger.ZERO;
        }
        if (
    === 1) {
            return 
    this;
        }

        var 
    digit;
        if (
    this._d.length === 1) {
            
    digit this._d[0] * n;
            if (
    digit >= BigInteger.base) {
                return new 
    BigInteger([(digit BigInteger.base) | 0, (digit BigInteger.base) | 0], 1);
            }
            return new 
    BigInteger([digit], 1);
        }

        if (
    === 2) {
            return 
    this.add(this);
        }
        if (
    this.isUnit()) {
            return new 
    BigInteger([n], 1);
        }

        var 
    this._d;
        var 
    al a.length;

        var 
    pl al 1;
        var 
    partial = new Array(pl);
        for (var 
    0pli++) {
            
    partial[i] = 0;
        }

        var 
    carry 0;
        for (var 
    0alj++) {
            
    digit a[j] + carry;
            
    carry = (digit BigInteger.base) | 0;
            
    partial[j] = (digit BigInteger.base) | 0;
        }
        if (
    carry) {
            
    digit carry;
            
    carry = (digit BigInteger.base) | 0;
            
    partial[j] = digit BigInteger.base;
        }

        return new 
    BigInteger(partial1);
    };

    /*
        Function: square
        Multiply a <BigInteger> by itself.

        This is slightly faster than regular multiplication, since it removes the
        duplicated multiplcations.

        Returns:

            > this.multiply(this)

        See Also:
            <multiply>
    */
    BigInteger.prototype.square = function () {
        
    // Normally, squaring a 10-digit number would take 100 multiplications.
        // Of these 10 are unique diagonals, of the remaining 90 (100-10), 45 are repeated.
        // This procedure saves (N*(N-1))/2 multiplications, (e.g., 45 of 100 multiplies).
        // Based on code by Gary Darby, Intellitech Systems Inc., www.DelphiForFun.org
        
    if (this._s === 0) {
            return 
    BigInteger.ZERO;
        }
        if (
    this.isUnit()) {
            return 
    BigInteger.ONE;
        }

        var 
    digits this._d;
        var 
    length digits.length;
        var 
    imult1 = new Array(length length 1);
        var 
    productcarryk;
        var 
    i;

        
    // Calculate diagonal
        
    for (0lengthi++) {
            
    2;
            
    product digits[i] * digits[i];
            
    carry = (product BigInteger.base) | 0;
            
    imult1[k] = product BigInteger.base;
            
    imult1[1] = carry;
        }

        
    // Calculate repeating part
        
    for (0lengthi++) {
            
    carry 0;
            
    1;
            for (var 
    1lengthj++, k++) {
                
    product digits[j] * digits[i] * imult1[k] + carry;
                
    carry = (product BigInteger.base) | 0;
                
    imult1[k] = product BigInteger.base;
            }
            
    length i;
            var 
    digit carry imult1[k];
            
    carry = (digit BigInteger.base) | 0;
            
    imult1[k] = digit BigInteger.base;
            
    imult1[1] += carry;
        }

        return new 
    BigInteger(imult11);
    };

    /*
        Function: quotient
        Divide two <BigIntegers> and truncate towards zero.

        <quotient> throws an exception if *n* is zero.

        Parameters:

            n - The number to divide *this* by. Will be converted to a <BigInteger>.

        Returns:

            The *this* / *n*, truncated to an integer.

        See Also:

            <add>, <subtract>, <multiply>, <divRem>, <remainder>
    */
    BigInteger.prototype.quotient = function (n) {
        return 
    this.divRem(n)[0];
    };

    /*
        Function: divide
        Deprecated synonym for <quotient>.
    */
    BigInteger.prototype.divide BigInteger.prototype.quotient;

    /*
        Function: remainder
        Calculate the remainder of two <BigIntegers>.

        <remainder> throws an exception if *n* is zero.

        Parameters:

            n - The remainder after *this* is divided *this* by *n*. Will be
                converted to a <BigInteger>.

        Returns:

            *this* % *n*.

        See Also:

            <divRem>, <quotient>
    */
    BigInteger.prototype.remainder = function (n) {
        return 
    this.divRem(n)[1];
    };

    /*
        Function: divRem
        Calculate the integer quotient and remainder of two <BigIntegers>.

        <divRem> throws an exception if *n* is zero.

        Parameters:

            n - The number to divide *this* by. Will be converted to a <BigInteger>.

        Returns:

            A two-element array containing the quotient and the remainder.

            > a.divRem(b)

            is exactly equivalent to

            > [a.quotient(b), a.remainder(b)]

            except it is faster, because they are calculated at the same time.

        See Also:

            <quotient>, <remainder>
    */
    BigInteger.prototype.divRem = function (n) {
        
    BigInteger(n);
        if (
    n._s === 0) {
            throw new 
    Error("Divide by zero");
        }
        if (
    this._s === 0) {
            return [
    BigInteger.ZEROBigInteger.ZERO];
        }
        if (
    n._d.length === 1) {
            return 
    this.divRemSmall(n._s n._d[0]);
        }

        
    // Test for easy cases -- |n1| <= |n2|
        
    switch (this.compareAbs(n)) {
        case 
    0:
            
    // n1 == n2
            
    return [this._s === n._s BigInteger.ONE BigInteger.M_ONEBigInteger.ZERO];
        case -
    1:
            
    // |n1| < |n2|
            
    return [BigInteger.ZEROthis];
        }

        var 
    sign this._s n._s;
        var 
    n.abs();
        var 
    b_digits this._d.slice();
        var 
    digits n._d.length;
        var 
    max b_digits.length;
        var 
    quot = [];
        var 
    guess;

        var 
    part = new BigInteger([], 1);
        
    part._s 1;

        while (
    b_digits.length) {
            
    part._d.unshift(b_digits.pop());
            
    part = new BigInteger(part._d1);

            if (
    part.compareAbs(n) < 0) {
                
    quot.push(0);
                continue;
            }
            if (
    part._s === 0) {
                
    guess 0;
            } else {
                var 
    xlen part._d.length,
                    
    ylen a._d.length;
                var 
    highx part._d[xlen 1] * BigInteger.base part._d[xlen 2];
                var 
    highy a._d[ylen 1] * BigInteger.base a._d[ylen 2];
                if (
    part._d.length a._d.length) {
                    
    // The length of part._d can either match a._d length,
                    // or exceed it by one.
                    
    highx = (highx 1) * BigInteger.base;
                }
                
    guess Math.ceil(highx highy);
            }
            do {
                var 
    check a.multiplySingleDigit(guess);
                if (
    check.compareAbs(part) <= 0) {
                    break;
                }
                
    guess--;
            } while (
    guess);

            
    quot.push(guess);
            if (!
    guess) {
                continue;
            }
            var 
    diff part.subtract(check);
            
    part._d diff._d.slice();
        }

        return [new 
    BigInteger(quot.reverse(), sign), new BigInteger(part._dthis._s)];
    };

    // Throws an exception if n is outside of (-BigInteger.base, -1] or
    // [1, BigInteger.base).  It's not necessary to call this, since the
    // other division functions will call it if they are able to.
    BigInteger.prototype.divRemSmall = function (n) {
        var 
    r;
        
    = +n;
        if (
    === 0) {
            throw new 
    Error("Divide by zero");
        }

        var 
    n_s ? -1;
        var 
    sign this._s n_s;
        
    Math.abs(n);

        if (
    || >= BigInteger.base) {
            throw new 
    Error("Argument out of range");
        }

        if (
    this._s === 0) {
            return [
    BigInteger.ZEROBigInteger.ZERO];
        }

        if (
    === || === -1) {
            return [(
    sign === 1) ? this.abs() : new BigInteger(this._dsign), BigInteger.ZERO];
        }

        
    // 2 <= n < BigInteger.base
        // divide a single digit by a single digit
        
    if (this._d.length === 1) {
            var 
    = new BigInteger([(this._d[0] / n) | 0], 1);
            
    = new BigInteger([(this._d[0] % n) | 0], 1);
            if (
    sign 0) {
                
    q.negate();
            }
            if (
    this._s 0) {
                
    r.negate();
            }
            return [
    qr];
        }

        var 
    digits this._d.slice();
        var 
    quot = new Array(digits.length);
        var 
    part 0;
        var 
    diff 0;
        var 
    0;
        var 
    guess;

        while (
    digits.length) {
            
    part part BigInteger.base digits[digits.length 1];
            if (
    part n) {
                
    quot[i++] = 0;
                
    digits.pop();
                
    diff BigInteger.base diff part;
                continue;
            }
            if (
    part === 0) {
                
    guess 0;
            } else {
                
    guess = (part n) | 0;
            }

            var 
    check guess;
            
    diff part check;
            
    quot[i++] = guess;
            if (!
    guess) {
                
    digits.pop();
                continue;
            }

            
    digits.pop();
            
    part diff;
        }

        
    = new BigInteger([diff], 1);
        if (
    this._s 0) {
            
    r.negate();
        }
        return [new 
    BigInteger(quot.reverse(), sign), r];
    };

    /*
        Function: isEven
        Return true iff *this* is divisible by two.

        Note that <BigInteger.ZERO> is even.

        Returns:

            true if *this* is even, false otherwise.

        See Also:

            <isOdd>
    */
    BigInteger.prototype.isEven = function () {
        var 
    digits this._d;
        return 
    this._s === || digits.length === || (digits[0] % 2) === 0;
    };

    /*
        Function: isOdd
        Return true iff *this* is not divisible by two.

        Returns:

            true if *this* is odd, false otherwise.

        See Also:

            <isEven>
    */
    BigInteger.prototype.isOdd = function () {
        return !
    this.isEven();
    };

    /*
        Function: sign
        Get the sign of a <BigInteger>.

        Returns:

            * -1 if *this* < 0
            * 0 if *this* == 0
            * +1 if *this* > 0

        See Also:

            <isZero>, <isPositive>, <isNegative>, <compare>, <BigInteger.ZERO>
    */
    BigInteger.prototype.sign = function () {
        return 
    this._s;
    };

    /*
        Function: isPositive
        Return true iff *this* > 0.

        Returns:

            true if *this*.compare(<BigInteger.ZERO>) == 1.

        See Also:

            <sign>, <isZero>, <isNegative>, <isUnit>, <compare>, <BigInteger.ZERO>
    */
    BigInteger.prototype.isPositive = function () {
        return 
    this._s 0;
    };

    /*
        Function: isNegative
        Return true iff *this* < 0.

        Returns:

            true if *this*.compare(<BigInteger.ZERO>) == -1.

        See Also:

            <sign>, <isPositive>, <isZero>, <isUnit>, <compare>, <BigInteger.ZERO>
    */
    BigInteger.prototype.isNegative = function () {
        return 
    this._s 0;
    };

    /*
        Function: isZero
        Return true iff *this* == 0.

        Returns:

            true if *this*.compare(<BigInteger.ZERO>) == 0.

        See Also:

            <sign>, <isPositive>, <isNegative>, <isUnit>, <BigInteger.ZERO>
    */
    BigInteger.prototype.isZero = function () {
        return 
    this._s === 0;
    };

    /*
        Function: exp10
        Multiply a <BigInteger> by a power of 10.

        This is equivalent to, but faster than

        > if (n >= 0) {
        >     return this.multiply(BigInteger("1e" + n));
        > }
        > else { // n <= 0
        >     return this.quotient(BigInteger("1e" + -n));
        > }

        Parameters:

            n - The power of 10 to multiply *this* by. *n* is converted to a
            javascipt number and must be no greater than <BigInteger.MAX_EXP>
            (0x7FFFFFFF), or an exception will be thrown.

        Returns:

            *this* * (10 ** *n*), truncated to an integer if necessary.

        See Also:

            <pow>, <multiply>
    */
    BigInteger.prototype.exp10 = function (n) {
        
    = +n;
        if (
    === 0) {
            return 
    this;
        }
        if (
    Math.abs(n) > Number(BigInteger.MAX_EXP)) {
            throw new 
    Error("exponent too large in BigInteger.exp10");
        }
        if (
    0) {
            var 
    = new BigInteger(this._d.slice(), this._s);

            for (; 
    >= BigInteger.base_log10-= BigInteger.base_log10) {
                
    k._d.unshift(0);
            }
            if (
    == 0) return k;
            
    k._s 1;
            
    k.multiplySingleDigit(Math.pow(10n));
            return (
    this._s k.negate() : k);
        } else if (-
    >= this._d.length BigInteger.base_log10) {
            return 
    BigInteger.ZERO;
        } else {
            var 
    = new BigInteger(this._d.slice(), this._s);

            for (
    = -n>= BigInteger.base_log10-= BigInteger.base_log10) {
                
    k._d.shift();
            }
            return (
    == 0) ? k.divRemSmall(Math.pow(10n))[0];
        }
    };

    /*
        Function: pow
        Raise a <BigInteger> to a power.

        In this implementation, 0**0 is 1.

        Parameters:

            n - The exponent to raise *this* by. *n* must be no greater than
            <BigInteger.MAX_EXP> (0x7FFFFFFF), or an exception will be thrown.

        Returns:

            *this* raised to the *nth* power.

        See Also:

            <modPow>
    */
    BigInteger.prototype.pow = function (n) {
        if (
    this.isUnit()) {
            if (
    this._s 0) {
                return 
    this;
            } else {
                return 
    BigInteger(n).isOdd() ? this this.negate();
            }
        }

        
    BigInteger(n);
        if (
    n._s === 0) {
            return 
    BigInteger.ONE;
        } else if (
    n._s 0) {
            if (
    this._s === 0) {
                throw new 
    Error("Divide by zero");
            } else {
                return 
    BigInteger.ZERO;
            }
        }
        if (
    this._s === 0) {
            return 
    BigInteger.ZERO;
        }
        if (
    n.isUnit()) {
            return 
    this;
        }

        if (
    n.compareAbs(BigInteger.MAX_EXP) > 0) {
            throw new 
    Error("exponent too large in BigInteger.pow");
        }
        var 
    this;
        var 
    aux BigInteger.ONE;
        var 
    two BigInteger.small[2];

        while (
    n.isPositive()) {
            if (
    n.isOdd()) {
                
    aux aux.multiply(x);
                if (
    n.isUnit()) {
                    return 
    aux;
                }
            }
            
    x.square();
            
    n.quotient(two);
        }

        return 
    aux;
    };

    /*
        Function: modPow
        Raise a <BigInteger> to a power (mod m).

        Because it is reduced by a modulus, <modPow> is not limited by
        <BigInteger.MAX_EXP> like <pow>.

        Parameters:

            exponent - The exponent to raise *this* by. Must be positive.
            modulus - The modulus.

        Returns:

            *this* ^ *exponent* (mod *modulus*).

        See Also:

            <pow>, <mod>
    */
    BigInteger.prototype.modPow = function (exponentmodulus) {
        var 
    result BigInteger.ONE;
        var 
    base this;

        while (
    exponent.isPositive()) {
            if (
    exponent.isOdd()) {
                
    result result.multiply(base).remainder(modulus);
            }

            
    exponent exponent.quotient(BigInteger.small[2]);
            if (
    exponent.isPositive()) {
                
    base base.square().remainder(modulus);
            }
        }

        return 
    result;
    };

    /*
        Function: log
        Get the natural logarithm of a <BigInteger> as a native JavaScript number.

        This is equivalent to

        > Math.log(this.toJSValue())

        but handles values outside of the native number range.

        Returns:

            log( *this* )

        See Also:

            <toJSValue>
    */
    BigInteger.prototype.log = function () {
        switch (
    this._s) {
        case 
    0:
            return -
    Infinity;
        case -
    1:
            return 
    NaN;
        default:
            
    // Fall through.
        
    }

        var 
    this._d.length;

        if (
    BigInteger.base_log10 30) {
            return 
    Math.log(this.valueOf());
        }

        var 
    Math.ceil(30 BigInteger.base_log10);
        var 
    firstNdigits this._d.slice(N);
        return 
    Math.log((new BigInteger(firstNdigits1)).valueOf()) + (N) * Math.log(BigInteger.base);
    };

    /*
        Function: valueOf
        Convert a <BigInteger> to a native JavaScript integer.

        This is called automatically by JavaScipt to convert a <BigInteger> to a
        native value.

        Returns:

            > parseInt(this.toString(), 10)

        See Also:

            <toString>, <toJSValue>
    */
    BigInteger.prototype.valueOf = function () {
        return 
    parseInt(this.toString(), 10);
    };

    /*
        Function: toJSValue
        Convert a <BigInteger> to a native JavaScript integer.

        This is the same as valueOf, but more explicitly named.

        Returns:

            > parseInt(this.toString(), 10)

        See Also:

            <toString>, <valueOf>
    */
    BigInteger.prototype.toJSValue = function () {
        return 
    parseInt(this.toString(), 10);
    };

    // Constant: MAX_EXP
    // The largest exponent allowed in <pow> and <exp10> (0x7FFFFFFF or 2147483647).
    BigInteger.MAX_EXP BigInteger(0x7FFFFFFF);

    (function () {
        function 
    makeUnary(fn) {
            return function (
    a) {
                return 
    fn.call(BigInteger(a));
            };
        }

        function 
    makeBinary(fn) {
            return function (
    ab) {
                return 
    fn.call(BigInteger(a), BigInteger(b));
            };
        }

        function 
    makeTrinary(fn) {
            return function (
    abc) {
                return 
    fn.call(BigInteger(a), BigInteger(b), BigInteger(c));
            };
        }

        (function () {
            var 
    ifn;
            var 
    unary "toJSValue,isEven,isOdd,sign,isZero,isNegative,abs,isUnit,square,negate,isPositive,toString,next,prev,log".split(",");
            var 
    binary "compare,remainder,divRem,subtract,add,quotient,divide,multiply,pow,compareAbs".split(",");
            var 
    trinary = ["modPow"];

            for (
    0unary.lengthi++) {
                
    fn unary[i];
                
    BigInteger[fn] = makeUnary(BigInteger.prototype[fn]);
            }

            for (
    0binary.lengthi++) {
                
    fn binary[i];
                
    BigInteger[fn] = makeBinary(BigInteger.prototype[fn]);
            }

            for (
    0trinary.lengthi++) {
                
    fn trinary[i];
                
    BigInteger[fn] = makeTrinary(BigInteger.prototype[fn]);
            }

            
    BigInteger.exp10 = function (xn) {
                return 
    BigInteger(x).exp10(n);
            };
        })();
    })();

    if (
    typeof exports !== 'undefined') {
        
    exports.BigInteger BigInteger;

    Perfection as a goal is a nice idea that can point one in a specific direction. However, since "perfection" is an ever changing (evolving?) and moving target, one must admit that perfection can never be obtained...

    When in doubt, check the d4mn source code!
    ================================================
    And here are my terms...
    1. I don't care if you use my source code. (Known as "Code.")
    2. I don't care if I get any monetary compensation.
    3. I do care to receive credit for Code provided. So, please keep my name in the comments for Code provided.
    4. Code is provided without warranty "AS-IS" and I claim absolutely no warranty nor liability to the quality, security, and run-ability on any platform.
    5. By using Code, you accept all risk inherit with Code regardless if Code has known and yet to be discovered bugs.
    6. You are welcome to change and improve the Code to best meet your needs.
    7. I don't care if you use the Code in a commercial or open-source project.
    8. You are not required to contact me prior to using the Code.
    ================================================
    Simple. Enjoy.

  2. #2
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,085
    Vote Rating
    467
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    I have provided the suggestion to development. Since this is specialty item, I am not sure it will pass .. but you never know

    Regards,
    Scott.

Thread Participants: 1

Tags for this Thread