2652 lines · 71.2 KB · JavaScript
RawDownload
/* * QuickJS Javascript Calculator *  * Copyright (c) 2017-2020 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */"use strict";"use math"; var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunction, Series, Matrix; (function(global) {    global.Integer = global.BigInt;    global.Float = global.BigFloat;    global.algebraicMode = true;        /* add non enumerable properties */    function add_props(obj, props) {        var i, val, prop, tab, desc;        tab = Reflect.ownKeys(props);        for(i = 0; i < tab.length; i++) {            prop = tab[i];            desc = Object.getOwnPropertyDescriptor(props, prop);            desc.enumerable = false;            if ("value" in desc) {                if (typeof desc.value !== "function") {                    desc.writable = false;                    desc.configurable = false;                }            } else {                /* getter/setter */                desc.configurable = false;            }            Object.defineProperty(obj, prop, desc);        }    }     /* same as proto[Symbol.operatorSet] = Operators.create(..op_list)       but allow shortcuts: left: [], right: [] or both    */    function operators_set(proto, ...op_list)    {        var new_op_list, i, a, j, b, k, obj, tab;        var fields = [ "left", "right" ];        new_op_list = [];        for(i = 0; i < op_list.length; i++) {            a = op_list[i];            if (a.left || a.right) {                tab = [ a.left, a.right ];                delete a.left;                delete a.right;                for(k = 0; k < 2; k++) {                    obj = tab[k];                    if (obj) {                        if (!Array.isArray(obj)) {                            obj = [ obj ];                        }                        for(j = 0; j < obj.length; j++) {                            b = {};                            Object.assign(b, a);                            b[fields[k]] = obj[j];                            new_op_list.push(b);                        }                    }                }            } else {                new_op_list.push(a);            }        }        proto[Symbol.operatorSet] =            Operators.create.call(null, ...new_op_list);     }        /* Integer */     function generic_pow(a, b) {        var r, is_neg, i;        if (!Integer.isInteger(b)) {            return exp(log(a) * b);        }        if (Array.isArray(a) && !(a instanceof Polynomial ||                                  a instanceof Series)) {            r = idn(Matrix.check_square(a));        } else {            r = 1;        }        if (b == 0)            return r;        is_neg = false;        if (b < 0) {            is_neg = true;            b = -b;        }        r = a;        for(i = Integer.floorLog2(b) - 1; i >= 0; i--) {            r *= r;            if ((b >> i) & 1)                r *= a;        }        if (is_neg) {            if (typeof r.inverse != "function")                throw "negative powers are not supported for this type";            r = r.inverse();        }        return r;    }        var small_primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499 ];     function miller_rabin_test(n, t) {        var d, r, s, i, j, a;        d = n - 1;        s = 0;        while ((d & 1) == 0) {            d >>= 1;            s++;        }        if (small_primes.length < t)            t = small_primes.length;        loop: for(j = 0; j < t; j++) {            a = small_primes[j];            r = Integer.pmod(a, d, n);            if (r == 1 || r == (n - 1))                continue;            for(i = 1; i < s; i++) {                r = (r * r) % n;                if (r == 1)                    return false;                if (r == (n - 1))                    continue loop;            }            return false; /* n is composite */        }        return true; /* n is probably prime with probability (1-0.5^t) */    }     function fact_rec(a, b) {  /* assumes a <= b */        var i, r;        if ((b - a) <= 5) {            r = a;            for(i = a + 1; i <= b; i++)                r *= i;            return r;        } else {            /* to avoid a quadratic running time it is better to               multiply numbers of similar size */            i = (a + b) >> 1;            return fact_rec(a, i) * fact_rec(i + 1, b);        }    }     /* math mode specific quirk to overload the integer division and power */    Operators.updateBigIntOperators(        {            "/"(a, b) {                if (algebraicMode) {                    return Fraction.toFraction(a, b);                } else {                    return Float(a) / Float(b);                }            },            "**"(a, b) {                if (algebraicMode) {                    return generic_pow(a, b);                } else {                    return Float(a) ** Float(b);                }            }        });                add_props(Integer, {        isInteger(a) {            /* integers are represented either as bigint or as number */            return typeof a === "bigint" ||                (typeof a === "number" && Number.isSafeInteger(a));        },        gcd(a, b) {            var r;            while (b != 0) {                r = a % b;                a = b;                b = r;            }            return a;        },        fact(n) {            return n <= 0 ? 1 : fact_rec(1, n);        },        /* binomial coefficient */        comb(n, k) {            if (k < 0 || k > n)                return 0;            if (k > n - k)                k = n - k;            if (k == 0)                return 1;            return Integer.tdiv(fact_rec(n - k + 1, n), fact_rec(1, k));        },        /* inverse of x modulo y */        invmod(x, y) {            var q, u, v, a, c, t;            u = x;            v = y;            c = 1;            a = 0;            while (u != 0) {                t = Integer.fdivrem(v, u);                q = t[0];                v = u;                u = t[1];                t = c;                c = a - q * c;                a = t;            }            /* v = gcd(x, y) */            if (v != 1)                throw RangeError("not invertible");            return a % y;        },        /* return a ^ b modulo m */        pmod(a, b, m) {            var r;            if (b == 0)                return 1;            if (b < 0) {                a = Integer.invmod(a, m);                b = -b;            }            r = 1;            for(;;) {                if (b & 1) {                    r = (r * a) % m;                }                b >>= 1;                if (b == 0)                    break;                a = (a * a) % m;            }            return r;        },         /* return true if n is prime (or probably prime with           probability 1-0.5^t) */        isPrime(n, t) {            var i, d, n1;            if (!Integer.isInteger(n))                throw TypeError("invalid type");            if (n <= 1)                return false;            n1 = small_primes.length;            /* XXX: need Integer.sqrt() */            for(i = 0; i < n1; i++) {                d = small_primes[i];                if (d == n)                    return true;                if (d > n)                    return false;                if ((n % d) == 0)                    return false;            }            if (n < d * d)                return true;            if (typeof t == "undefined")                t = 64;            return miller_rabin_test(n, t);        },        nextPrime(n) {            if (!Integer.isInteger(n))                throw TypeError("invalid type");            if (n < 1)                n = 1;            for(;;) {                n++;                if (Integer.isPrime(n))                    return n;            }        },        factor(n) {            var r, d;            if (!Integer.isInteger(n))                throw TypeError("invalid type");            r = [];            if (abs(n) <= 1) {                r.push(n);                return r;            }            if (n < 0) {                r.push(-1);                n = -n;            }                        while ((n % 2) == 0) {                n >>= 1;                r.push(2);            }             d = 3;            while (n != 1) {                if (Integer.isPrime(n)) {                    r.push(n);                    break;                }                /* we are sure there is at least one divisor, so one test */                for(;;) {                    if ((n % d) == 0)                        break;                    d += 2;                }                for(;;) {                    r.push(d);                    n = Integer.tdiv(n, d);                    if ((n % d) != 0)                        break;                }            }            return r;        },    });     add_props(Integer.prototype, {        inverse() {            return 1 / this;        },        norm2() {            return this * this;        },        abs() {            var v = this;            if (v < 0)                v = -v;            return v;        },        conj() {            return this;        },        arg() {            if (this >= 0)                return 0;            else                return Float.PI;        },        exp() {            if (this == 0)                return 1;            else                return Float.exp(this);        },        log() {            if (this == 1)                return 0;            else                return Float(this).log();        },    });     /* Fraction */     Fraction = function Fraction(a, b)    {        var d, r, obj;         if (new.target)            throw TypeError("not a constructor");        if (a instanceof Fraction)            return a;        if (!Integer.isInteger(a))            throw TypeError("integer expected");        if (typeof b === "undefined") {            b = 1;        } else {            if (!Integer.isInteger(b))                throw TypeError("integer expected");            if (b == 0)                throw RangeError("division by zero");            d = Integer.gcd(a, b);            if (d != 1) {                a = Integer.tdiv(a, d);                b = Integer.tdiv(b, d);            }                        /* the fractions are normalized with den > 0 */            if (b < 0) {                a = -a;                b = -b;            }        }        obj = Object.create(Fraction.prototype);        obj.num = a;        obj.den = b;        return obj;    }     function fraction_add(a, b) {        a = Fraction(a);        b = Fraction(b);        return Fraction.toFraction(a.num * b.den + a.den * b.num, a.den * b.den);    }    function fraction_sub(a, b) {        a = Fraction(a);        b = Fraction(b);        return Fraction.toFraction(a.num * b.den - a.den * b.num, a.den * b.den);    }    function fraction_mul(a, b) {        a = Fraction(a);        b = Fraction(b);        return Fraction.toFraction(a.num * b.num, a.den * b.den);    }    function fraction_div(a, b) {        a = Fraction(a);        b = Fraction(b);        return Fraction.toFraction(a.num * b.den, a.den * b.num);    }    function fraction_mod(a, b) {        var a1 = Fraction(a);        var b1 = Fraction(b);        return a - Integer.ediv(a1.num * b1.den, a1.den * b1.num) * b;    }    function fraction_eq(a, b) {        a = Fraction(a);        b = Fraction(b);        /* we assume the fractions are normalized */        return (a.num == b.num && a.den == b.den);    }    function fraction_lt(a, b) {        a = Fraction(a);        b = Fraction(b);        return (a.num * b.den < b.num * a.den);    }     /* operators are needed for fractions */    function float_add(a, b) {        return Float(a) + Float(b);    }    function float_sub(a, b) {        return Float(a) - Float(b);    }    function float_mul(a, b) {        return Float(a) * Float(b);    }    function float_div(a, b) {        return Float(a) / Float(b);    }    function float_mod(a, b) {        return Float(a) % Float(b);    }    function float_pow(a, b) {        return Float(a) ** Float(b);    }    function float_eq(a, b) {        /* XXX: may be better to use infinite precision for the comparison */        return Float(a) === Float(b);    }    function float_lt(a, b) {        a = Float(a);        b = Float(b);        /* XXX: may be better to use infinite precision for the comparison */        if (Float.isNaN(a) || Float.isNaN(b))            return undefined;        else            return a < b;    }        operators_set(Fraction.prototype,        {            "+": fraction_add,            "-": fraction_sub,            "*": fraction_mul,            "/": fraction_div,            "%": fraction_mod,            "**": generic_pow,            "==": fraction_eq,            "<": fraction_lt,            "pos"(a) {                return a;            },            "neg"(a) {                return Fraction(-a.num, a.den);            },        },        {            left: [Number, BigInt],            right: [Number, BigInt],            "+": fraction_add,

Lines 1–500 of 2652.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t