diff --git a/js-assembler/runtime-src/js-numbers.js b/js-assembler/runtime-src/js-numbers.js index db8df45..0192b47 100644 --- a/js-assembler/runtime-src/js-numbers.js +++ b/js-assembler/runtime-src/js-numbers.js @@ -1,90 +1,4092 @@ -var __PLTNUMBERS_TOP__;typeof exports!=="undefined"?__PLTNUMBERS_TOP__=exports:(this.jsnums||(this.jsnums={}),__PLTNUMBERS_TOP__=this.jsnums); -(function(){function f(a,b,c){a!=null&&("number"==typeof a?this.fromNumber(a,b,c):b==null&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function p(){return new f(null)}function hb(a,b,c,e,j,d){for(;--d>=0;){var f=b*this[a++]+c[e]+j,j=Math.floor(f/67108864);c[e++]=f&67108863}return j}function ib(a,b,c,e,j,d){var f=b&32767;for(b>>=15;--d>=0;){var g=this[a]&32767,h=this[a++]>>15,i=b*g+h*f,g=f*g+((i&32767)<<15)+c[e]+(j&1073741823),j=(g>>>30)+(i>>>15)+b*h+(j>>>30);c[e++]=g&1073741823}return j} -function jb(a,b,c,e,j,d){var f=b&16383;for(b>>=14;--d>=0;){var g=this[a]&16383,h=this[a++]>>14,i=b*g+h*f,g=f*g+((i&16383)<<14)+c[e]+j,j=(g>>28)+(i>>14)+b*h;c[e++]=g&268435455}return j}function xa(a,b){var c=ja[a.charCodeAt(b)];return c==null?-1:c}function N(a){var b=p();b.fromInt(a);return b}function Y(a){var b=this.s-a.s;if(b!=0)return b;var c=this.t,b=this.s<0?a.t-c:c-a.t;if(b!=0)return b;for(;--c>=0;)if((b=this[c]-a[c])!=0)return b;return 0}function ka(a){var b=1,c;if((c=a>>>16)!=0)a=c,b+=16;if((c= -a>>8)!=0)a=c,b+=8;if((c=a>>4)!=0)a=c,b+=4;if((c=a>>2)!=0)a=c,b+=2;a>>1!=0&&(b+=1);return b}function ya(a){var b=p();this.abs().divRemTo(a,null,b);this.s<0&&b.compareTo(f.ZERO)>0&&a.subTo(b,b);return b}function P(a){this.m=a}function Q(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<0&&(b.rShiftTo(e,b),a.rShiftTo(e,a));for(;b.signum()>0;)(c=b.getLowestSetBit())>0&&b.rShiftTo(c,b),(c=a.getLowestSetBit())>0&&a.rShiftTo(c,a),b.compareTo(a)>=0?(b.subTo(a,b),b.rShiftTo(1,b)):(a.subTo(b,a),a.rShiftTo(1,a));e>0&&a.lShiftTo(e,a);return a}var h=__PLTNUMBERS_TOP__,H=function(a,b,c){c= -c||{};return function(e,j){if(c.isXSpecialCase&&c.isXSpecialCase(e))return c.onXSpecialCase(e,j);if(c.isYSpecialCase&&c.isYSpecialCase(j))return c.onYSpecialCase(e,j);if(typeof e==="number"&&typeof j==="number")return a(e,j);typeof e==="number"&&(e=Ka(e,j));typeof j==="number"&&(j=Ka(j,e));e.level=a[2].length- -1?a[1]+a[2].substring(1)+Ma(b-(a[2].length-1)):a[1]+a[2].substring(1,1+b)):a},Ma=function(a){var b=[];b.length=a;for(var c=0;c=b},function(a,b){(!E(a)||!E(b))&&l(">=: couldn't be applied to complex number",a,b);return a.greaterThanOrEqual(b)}),da=H(function(a,b){return a<=b},function(a,b){(!E(a)||!E(b))&&l("<=: couldn't be applied to complex number",a,b);return a.lessThanOrEqual(b)}),U=H(function(a,b){return a>b},function(a,b){(!E(a)|| -!E(b))&&l(">: couldn't be applied to complex number",a,b);return a.greaterThan(b)}),J=H(function(a,b){return a=0?(a=Math.sqrt(a),Math.floor(a)===a?a:d.makeInstance(a)): -g.makeInstance(0,D(-a)):a.sqrt()},A=function(a){return typeof a==="number"?Math.abs(a):a.abs()},z=function(a){return typeof a==="number"?a:a.floor()},Ra=function(a){return typeof a==="number"?a:a.ceiling()},Sa=function(a){return typeof a==="number"?a:a.conjugate()},na=function(a){return q(a,1)?0:typeof a==="number"?d.makeInstance(Math.log(a)):a.log()},Ta=function(a){return typeof a==="number"?a>0?0:d.pi:a.angle()},Ua=function(a){return q(a,0)?0:typeof a==="number"?d.makeInstance(Math.tan(a)):a.tan()}, -wa=function(a){return q(a,0)?0:typeof a==="number"?d.makeInstance(Math.atan(a)):a.atan()},oa=function(a){return q(a,0)?1:typeof a==="number"?d.makeInstance(Math.cos(a)):a.cos()},pa=function(a){return q(a,0)?0:typeof a==="number"?d.makeInstance(Math.sin(a)):a.sin()},Va=function(a){return q(a,1)?0:typeof a==="number"?d.makeInstance(Math.acos(a)):a.acos()},Wa=function(a){return q(a,0)?0:typeof a==="number"?d.makeInstance(Math.asin(a)):a.asin()},ca=function(a){return typeof a==="number"?0:a.imaginaryPart()}, -M=function(a){return typeof a==="number"?a:a.realPart()},Xa=function(a){return typeof a==="number"?a:a.round()},X=function(a){return k(a,a)},Ya=function(a){t(a)||l("integer-sqrt: the argument "+a.toString()+" is not an integer.",a);return typeof a==="number"?a<0?g.makeInstance(0,Math.floor(Math.sqrt(-a))):Math.floor(Math.sqrt(a)):a.integerSqrt()},qa=function(a,b){t(a)||l("quotient: the first argument "+a.toString()+" is not an integer.",a);t(b)||l("quotient: the second argument "+b.toString()+" is not an integer.", -b);return fa(a,b)},ra=function(a,b){t(a)||l("remainder: the first argument "+a.toString()+" is not an integer.",a);t(b)||l("remainder: the second argument "+b.toString()+" is not an integer.",b);return mb(a,b)},K=function(a){return a<-9E15||9E15 -b},function(a,b){return Y.call(a,b)>0},{doNotCoerseToFloating:!0}),ta=n(function(a,b){return a=b},function(a,b){return Y.call(a,b)>=0},{doNotCoerseToFloating:!0}),pb=n(function(a,b){return a<=b},function(a,b){return Y.call(a,b)<=0},{doNotCoerseToFloating:!0}),i=function(a,b){this.n=a;this.d=b};i.prototype.toString=function(){return T(this.d)?this.n.toString()+"":this.n.toString()+"/"+this.d.toString()}; -i.prototype.level=1;i.prototype.liftTo=function(a){return a.level===2?new d(B(this.n,this.d)):a.level===3?new g(this,0):l("invalid level of Number",this,a)};i.prototype.isFinite=function(){return!0};i.prototype.equals=function(a){return a instanceof i&&$a(this.n,a.n)&&$a(this.d,a.d)};i.prototype.isInteger=function(){return T(this.d)};i.prototype.isRational=function(){return!0};i.prototype.isReal=function(){return!0};i.prototype.add=function(a){return i.makeInstance(nb(u(this.n,a.d),u(this.d,a.n)), -u(this.d,a.d))};i.prototype.subtract=function(a){return i.makeInstance(ob(u(this.n,a.d),u(this.d,a.n)),u(this.d,a.d))};i.prototype.negate=function(){return i.makeInstance(-this.n,this.d)};i.prototype.multiply=function(a){return i.makeInstance(u(this.n,a.n),u(this.d,a.d))};i.prototype.divide=function(a){(r(this.d)||r(a.n))&&l("/: division by zero",this,a);return i.makeInstance(u(this.n,a.d),u(this.d,a.n))};i.prototype.toExact=function(){return this};i.prototype.toInexact=function(){return d.makeInstance(this.toFixnum())}; -i.prototype.isExact=function(){return!0};i.prototype.isInexact=function(){return!1};i.prototype.toFixnum=function(){return B(this.n,this.d)};i.prototype.numerator=function(){return this.n};i.prototype.denominator=function(){return this.d};i.prototype.greaterThan=function(a){return ab(u(this.n,a.d),u(this.d,a.n))};i.prototype.greaterThanOrEqual=function(a){return bb(u(this.n,a.d),u(this.d,a.n))};i.prototype.lessThan=function(a){return ta(u(this.n,a.d),u(this.d,a.n))};i.prototype.lessThanOrEqual=function(a){return pb(u(this.n, -a.d),u(this.d,a.n))};i.prototype.integerSqrt=function(){var a=D(this);return va(a)?S(z(a)):E(a)?S(z(a)):g.makeInstance(S(z(M(a))),S(z(ca(a))))};i.prototype.sqrt=function(){if(bb(this.n,0)){var a=D(this.n),b=D(this.d);return s(z(a),a)&&s(z(b),b)?i.makeInstance(a,b):d.makeInstance(B(a,b))}else return a=D(x(this.n)),b=D(this.d),s(z(a),a)&&s(z(b),b)?g.makeInstance(0,i.makeInstance(a,b)):g.makeInstance(0,d.makeInstance(B(a,b)))};i.prototype.abs=function(){return i.makeInstance(A(this.n),this.d)};i.prototype.floor= -function(){var a=fa(this.n,this.d);return ta(this.n,0)?w(a,1):a};i.prototype.ceiling=function(){var a=fa(this.n,this.d);return ta(this.n,0)?a:m(a,1)};i.prototype.conjugate=function(){return this};i.prototype.magnitude=i.prototype.abs;i.prototype.log=function(){return d.makeInstance(Math.log(this.n/this.d))};i.prototype.angle=function(){return r(this.n)?0:ab(this.n,0)?0:d.pi};i.prototype.tan=function(){return d.makeInstance(Math.tan(B(this.n,this.d)))};i.prototype.atan=function(){return d.makeInstance(Math.atan(B(this.n, -this.d)))};i.prototype.cos=function(){return d.makeInstance(Math.cos(B(this.n,this.d)))};i.prototype.sin=function(){return d.makeInstance(Math.sin(B(this.n,this.d)))};i.prototype.expt=function(a){return O(a)&&ma(a,0)?Za(this,a):d.makeInstance(Math.pow(B(this.n,this.d),B(a.n,a.d)))};i.prototype.exp=function(){return d.makeInstance(Math.exp(B(this.n,this.d)))};i.prototype.acos=function(){return d.makeInstance(Math.acos(B(this.n,this.d)))};i.prototype.asin=function(){return d.makeInstance(Math.asin(B(this.n, -this.d)))};i.prototype.imaginaryPart=function(){return 0};i.prototype.realPart=function(){return this};i.prototype.round=function(){if(s(this.d,2)){var a=B(this.n,this.d),b=Math.floor(a),a=Math.ceil(a);return r(b%2)?b:a}else return Math.round(this.n/this.d)};i.makeInstance=function(a,b){a===void 0&&l("n undefined",a,b);b===void 0&&(b=1);ta(b,0)&&(a=x(a),b=x(b));var c=sa(A(a),A(b)),a=fa(a,c),b=fa(b,c);return T(b)||r(a)?a:new i(a,b)};var d=function(a){this.n=a},ga=new d(Number.NaN),n=new d(Number.POSITIVE_INFINITY), -cb=new d(Number.NEGATIVE_INFINITY),db=new d(Number.POSITIVE_INFINITY),eb=new d(Number.NEGATIVE_INFINITY),L=new d(0),fb=new d(0);d.pi=new d(Math.PI);d.e=new d(Math.E);d.nan=ga;d.inf=n;d.neginf=cb;d.makeInstance=function(a){if(isNaN(a))return d.nan;else if(a===Number.POSITIVE_INFINITY)return d.inf;else if(a===Number.NEGATIVE_INFINITY)return d.neginf;else if(a===0)return 1/a===-Infinity?L:fb;return new d(a)};d.prototype.isExact=function(){return!1};d.prototype.isInexact=function(){return!0};d.prototype.isFinite= -function(){return isFinite(this.n)||this===db||this===eb};d.prototype.toExact=function(){(!isFinite(this.n)||isNaN(this.n))&&l("toExact: no exact representation for "+this,this);var a=this.n.toString().match(/^(.*)\.(.*)$/);return a?(parseInt(a[1]),parseInt(a[2]),a=Math.pow(10,a[2].length),i.makeInstance(Math.round(this.n*a),a)):this.n};d.prototype.toInexact=function(){return this};d.prototype.isInexact=function(){return!0};d.prototype.level=2;d.prototype.liftTo=function(a){return a.level===3?new g(this, -0):l("invalid level of Number",this,a)};d.prototype.toString=function(){if(isNaN(this.n))return"+nan.0";if(this.n===Number.POSITIVE_INFINITY)return"+inf.0";if(this.n===Number.NEGATIVE_INFINITY)return"-inf.0";if(this===L)return"-0.0";var a=this.n.toString();return a.match("\\.")?a:a+".0"};d.prototype.equals=function(a){return a instanceof d&&this.n===a.n};d.prototype.isRational=function(){return this.isFinite()};d.prototype.isInteger=function(){return this.isFinite()&&this.n===Math.floor(this.n)}; -d.prototype.isReal=function(){return!0};var ha=function(a){return J(a,0)?-1:U(a,0)?1:a===L?-1:0};d.prototype.add=function(a){return this.isFinite()&&a.isFinite()?d.makeInstance(this.n+a.n):isNaN(this.n)||isNaN(a.n)?ga:this.isFinite()&&!a.isFinite()?a:!this.isFinite()&&a.isFinite()?this:ha(this)*ha(a)===1?this:ga};d.prototype.subtract=function(a){return this.isFinite()&&a.isFinite()?d.makeInstance(this.n-a.n):isNaN(this.n)||isNaN(a.n)?ga:!this.isFinite()&&!a.isFinite()?ha(this)===ha(a)?ga:this:this.isFinite()? -k(a,-1):this};d.prototype.negate=function(){return d.makeInstance(-this.n)};d.prototype.multiply=function(a){return d.makeInstance(this.n*a.n)};d.prototype.divide=function(a){return d.makeInstance(this.n/a.n)};d.prototype.toFixnum=function(){return this.n};d.prototype.numerator=function(){var a=this.n.toString().match(/^(.*)\.(.*)$/);if(a){var b=parseInt(a[2]),a=Math.pow(10,a[2].length),b=sa(a,b);return d.makeInstance(Math.round(this.n*(a/b)))}else return this};d.prototype.denominator=function(){var a= -this.n.toString().match(/^(.*)\.(.*)$/);if(a){var b=parseInt(a[2]),a=Math.pow(10,a[2].length),b=sa(a,b);return d.makeInstance(Math.round(a/b))}else return d.makeInstance(1)};d.prototype.floor=function(){return d.makeInstance(Math.floor(this.n))};d.prototype.ceiling=function(){return d.makeInstance(Math.ceil(this.n))};d.prototype.greaterThan=function(a){return this.n>a.n};d.prototype.greaterThanOrEqual=function(a){return this.n>=a.n};d.prototype.lessThan=function(a){return this.n=0?d.makeInstance(Math.floor(Math.sqrt(this.n))):g.makeInstance(fb,d.makeInstance(Math.floor(Math.sqrt(-this.n))));else l("integerSqrt: can only be applied to an integer",this)};d.prototype.sqrt=function(){return this.n<0?g.makeInstance(0,d.makeInstance(Math.sqrt(-this.n))):d.makeInstance(Math.sqrt(this.n))};d.prototype.abs=function(){return d.makeInstance(Math.abs(this.n))};d.prototype.log= -function(){return this.n<0?(new g(this,0)).log():d.makeInstance(Math.log(this.n))};d.prototype.angle=function(){return 0===this.n?0:this.n>0?0:d.pi};d.prototype.tan=function(){return d.makeInstance(Math.tan(this.n))};d.prototype.atan=function(){return d.makeInstance(Math.atan(this.n))};d.prototype.cos=function(){return d.makeInstance(Math.cos(this.n))};d.prototype.sin=function(){return d.makeInstance(Math.sin(this.n))};d.prototype.expt=function(a){return this.n===1?(a.isFinite()||isNaN(a.n),this): -d.makeInstance(Math.pow(this.n,a.n))};d.prototype.exp=function(){return d.makeInstance(Math.exp(this.n))};d.prototype.acos=function(){return d.makeInstance(Math.acos(this.n))};d.prototype.asin=function(){return d.makeInstance(Math.asin(this.n))};d.prototype.imaginaryPart=function(){return 0};d.prototype.realPart=function(){return this};d.prototype.round=function(){return isFinite(this.n)?this===L?this:Math.abs(Math.floor(this.n)-this.n)===0.5?Math.floor(this.n)%2===0?d.makeInstance(Math.floor(this.n)): -d.makeInstance(Math.ceil(this.n)):d.makeInstance(Math.round(this.n)):this};d.prototype.conjugate=function(){return this};d.prototype.magnitude=d.prototype.abs;var g=function(a,b){this.r=a;this.i=b};g.makeInstance=function(a,b){b===void 0&&(b=0);if(W(b)&&t(b)&&r(b))return a;if(aa(a)||aa(b))a=ba(a),b=ba(b);return new g(a,b)};g.prototype.toString=function(){var a=this.r.toString(),b=this.i.toString();return b[0]==="-"||b[0]==="+"?a+b+"i":a+"+"+b+"i"};g.prototype.isFinite=function(){return(typeof this.r=== -"number"?isFinite(this.r):this.r.isFinite())&&(typeof this.i==="number"?isFinite(this.i):this.i.isFinite())};g.prototype.isRational=function(){return va(this.r)&&q(this.i,0)};g.prototype.isInteger=function(){return t(this.r)&&q(this.i,0)};g.prototype.toExact=function(){return g.makeInstance(S(this.r),S(this.i))};g.prototype.toInexact=function(){return g.makeInstance(ba(this.r),ba(this.i))};g.prototype.isExact=function(){return W(this.r)&&W(this.i)};g.prototype.isInexact=function(){return aa(this.r)|| -aa(this.i)};g.prototype.level=3;g.prototype.liftTo=function(a){l("Don't know how to lift Complex number",this,a)};g.prototype.equals=function(a){return a instanceof g&&s(this.r,a.r)&&s(this.i,a.i)};g.prototype.greaterThan=function(a){(!this.isReal()||!a.isReal())&&l(">: expects argument of type real number",this,a);return U(this.r,a.r)};g.prototype.greaterThanOrEqual=function(a){(!this.isReal()||!a.isReal())&&l(">=: expects argument of type real number",this,a);return ma(this.r,a.r)};g.prototype.lessThan= -function(a){(!this.isReal()||!a.isReal())&&l("<: expects argument of type real number",this,a);return J(this.r,a.r)};g.prototype.lessThanOrEqual=function(a){(!this.isReal()||!a.isReal())&&l("<=: expects argument of type real number",this,a);return da(this.r,a.r)};g.prototype.abs=function(){s(this.i,0).valueOf()||l("abs: expects argument of type real number",this);return A(this.r)};g.prototype.toFixnum=function(){s(this.i,0).valueOf()||l("toFixnum: expects argument of type real number",this);return I(this.r)}; -g.prototype.numerator=function(){this.isReal()||l("numerator: can only be applied to real number",this);return ea(this.n)};g.prototype.denominator=function(){this.isReal()||l("floor: can only be applied to real number",this);return Qa(this.n)};g.prototype.add=function(a){return g.makeInstance(m(this.r,a.r),m(this.i,a.i))};g.prototype.subtract=function(a){return g.makeInstance(w(this.r,a.r),w(this.i,a.i))};g.prototype.negate=function(){return g.makeInstance(x(this.r),x(this.i))};g.prototype.multiply= -function(a){if(a.isReal())return g.makeInstance(k(this.r,a.r),k(this.i,a.r));var b=w(k(this.r,a.r),k(this.i,a.i)),a=m(k(this.r,a.i),k(this.i,a.r));return g.makeInstance(b,a)};g.prototype.divide=function(a){var b,c,e,j,d;return a.isReal()?g.makeInstance(o(this.r,a.r),o(this.i,a.r)):this.isInexact()||a.isInexact()?(b=this.r,c=this.i,e=a.r,j=a.i,da(A(j),A(e))?(d=o(j,e),a=o(m(b,k(c,d)),m(e,k(j,d))),b=o(w(c,k(b,d)),m(e,k(j,d)))):(d=o(e,j),a=o(m(k(b,d),c),m(k(e,d),j)),b=o(w(k(c,d),b),m(k(e,d),j))),g.makeInstance(a, -b)):(c=Sa(a),b=k(this,c),c=M(k(a,c)),g.makeInstance(o(M(b),c),o(ca(b),c)))};g.prototype.conjugate=function(){return g.makeInstance(this.r,w(0,this.i))};g.prototype.magnitude=function(){var a=m(k(this.r,this.r),k(this.i,this.i));return D(a)};g.prototype.isReal=function(){return q(this.i,0)};g.prototype.integerSqrt=function(){if(t(this))return Ya(this.r);else l("integerSqrt: can only be applied to an integer",this)};g.prototype.sqrt=function(){if(this.isReal())return D(this.r);var a=m(this.magnitude(), -this.r),b=D(o(a,2)),a=o(this.i,D(k(a,2)));return g.makeInstance(b,a)};g.prototype.log=function(){var a=this.magnitude(),b=this.angle();return m(na(a),k(b,G))};g.prototype.angle=function(){if(this.isReal())return Ta(this.r);if(s(0,this.r)){var a=o(d.pi,2);return U(this.i,0)?a:x(a)}else return a=wa(o(A(this.i),A(this.r))),U(this.r,0)?U(this.i,0)?a:x(a):U(this.i,0)?w(d.pi,a):w(a,d.pi)};var G=g.makeInstance(0,1),gb=g.makeInstance(0,-1);g.prototype.tan=function(){return o(this.sin(),this.cos())};g.prototype.atan= -function(){return s(this,G)||s(this,gb)?cb:k(G,k(d.makeInstance(0.5),na(o(m(G,this),m(G,w(0,this))))))};g.prototype.cos=function(){if(this.isReal())return oa(this.r);var a=k(this,G),b=x(a),a=m(F(a),F(b));return o(a,2)};g.prototype.sin=function(){if(this.isReal())return pa(this.r);var a=k(this,G),b=x(a),c=g.makeInstance(0,2),a=w(F(a),F(b));return o(a,c)};g.prototype.expt=function(a){if(O(a)&&ma(a,0))return Za(this,a);a=k(a,this.log());return F(a)};g.prototype.exp=function(){var a=F(this.r),b=oa(this.i), -c=pa(this.i);return k(a,m(b,k(c,G)))};g.prototype.acos=function(){if(this.isReal())return Va(this.r);var a=o(d.pi,2),b=k(this,G),c=D(w(1,X(this))),b=na(m(b,c)),b=k(b,G);return m(a,b)};g.prototype.asin=function(){if(this.isReal())return Wa(this.r);var a=w(1,X(this)),a=D(a);return k(2,wa(o(this,m(1,a))))};g.prototype.ceiling=function(){this.isReal()||l("ceiling: can only be applied to real number",this);return Ra(this.r)};g.prototype.floor=function(){this.isReal()||l("floor: can only be applied to real number", -this);return z(this.r)};g.prototype.imaginaryPart=function(){return this.i};g.prototype.realPart=function(){return this.r};g.prototype.round=function(){this.isReal()||l("round: can only be applied to real number",this);return Xa(this.r)};var qb=/^([+-]?\d+)\/(\d+)$/,rb=/^([+-]?[\d\w/\.]*)([+-])([\d\w/\.]*)i$/,sb=/^[+-]?\d+$/,tb=/^([+-]?\d*)\.(\d*)$/,La=/^([+-]?\d*\.?\d*)[Ee](\+?\d+)$/,ia=function(a){var b=a.match(qb);if(b)return i.makeInstance(ia(b[1]),ia(b[2]));if(b=a.match(rb))return g.makeInstance(ia(b[1]|| -"0"),ia(b[2]+(b[3]||"1")));if(a==="+nan.0"||a==="-nan.0")return d.nan;if(a==="+inf.0")return d.inf;if(a==="-inf.0")return d.neginf;if(a==="-0.0")return L;return a.match(tb)||a.match(La)?d.makeInstance(Number(a)):a.match(sb)?(b=Number(a),K(b)?v(a):b):!1};typeof navigator!=="undefined"&&navigator.appName=="Microsoft Internet Explorer"?(f.prototype.am=ib,n=30):typeof navigator!=="undefined"&&navigator.appName!="Netscape"?(f.prototype.am=hb,n=26):(f.prototype.am=jb,n=28);f.prototype.DB=n;f.prototype.DM= -(1<=0?a.mod(this.m):a};P.prototype.revert=function(a){return a};P.prototype.reduce=function(a){a.divRemTo(this.m,null,a)};P.prototype.mulTo=function(a,b,c){a.multiplyTo(b,c);this.reduce(c)}; -P.prototype.sqrTo=function(a,b){a.squareTo(b);this.reduce(b)};Q.prototype.convert=function(a){var b=p();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);a.s<0&&b.compareTo(f.ZERO)>0&&this.m.subTo(b,b);return b};Q.prototype.revert=function(a){var b=p();a.copyTo(b);this.reduce(b);return b};Q.prototype.reduce=function(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b>15)*this.mpl&this.um)<<15)&a.DM,c=b+this.m.t;for(a[c]+=this.m.am(0, -e,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp();a.drShiftTo(this.m.t,a);a.compareTo(this.m)>=0&&a.subTo(this.m,a)};Q.prototype.mulTo=function(a,b,c){a.multiplyTo(b,c);this.reduce(c)};Q.prototype.sqrTo=function(a,b){a.squareTo(b);this.reduce(b)};f.prototype.copyTo=function(a){for(var b=this.t-1;b>=0;--b)a[b]=this[b];a.t=this.t;a.s=this.s};f.prototype.fromInt=function(a){this.t=1;this.s=a<0?-1:0;a>0?this[0]=a:a<-1?this[0]=a+DV:this.t=0};f.prototype.fromString=function(a,b){var c;if(b==16)c= -4;else if(b==8)c=3;else if(b==256)c=8;else if(b==2)c=1;else if(b==32)c=5;else if(b==4)c=2;else{this.fromRadix(a,b);return}this.s=this.t=0;for(var e=a.length,j=!1,d=0;--e>=0;){var g=c==8?a[e]&255:xa(a,e);g<0?a.charAt(e)=="-"&&(j=!0):(j=!1,d==0?this[this.t++]=g:d+c>this.DB?(this[this.t-1]|=(g&(1<>this.DB-d):this[this.t-1]|=g<=this.DB&&(d-=this.DB))}if(c==8&&(a[0]&128)!=0)this.s=-1,d>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==a;)--this.t};f.prototype.dlShiftTo=function(a,b){var c;for(c=this.t-1;c>=0;--c)b[c+a]=this[c];for(c=a-1;c>=0;--c)b[c]=0;b.t=this.t+a;b.s=this.s};f.prototype.drShiftTo=function(a,b){for(var c=a;c=0;--h)b[h+f+1]=this[h]>> -e|g,g=(this[h]&d)<=0;--h)b[h]=0;b[f]=g;b.t=this.t+f+1;b.s=this.s;b.clamp()};f.prototype.rShiftTo=function(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)b.t=0;else{var e=a%this.DB,d=this.DB-e,f=(1<>e;for(var g=c+1;g>e;e>0&&(b[this.t-c-1]|=(this.s&f)<>=this.DB;if(a.t< -this.t){for(e-=a.s;c>=this.DB;e+=this.s}else{for(e+=this.s;c>=this.DB;e-=a.s}b.s=e<0?-1:0;e<-1?b[c++]=this.DV+e:e>0&&(b[c++]=e);b.t=c;b.clamp()};f.prototype.multiplyTo=function(a,b){var c=this.abs(),e=a.abs(),d=c.t;for(b.t=d+e.t;--d>=0;)b[d]=0;for(d=0;d=0;)a[c]=0;for(c= -0;c=b.DV)a[c+b.t]-=b.DV,a[c+b.t+1]=1}a.t>0&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1));a.s=0;a.clamp()};f.prototype.divRemTo=function(a,b,c){var e=a.abs();if(!(e.t<=0)){var d=this.abs();if(d.t0?(e.lShiftTo(i,g),d.lShiftTo(i,c)):(e.copyTo(g),d.copyTo(c));e=g.t;d=g[e-1];if(d!=0){var l=d*(1<1?g[e-2]>>this.F2:0),k=this.FV/l,l=(1<=0&&(c[c.t++]=1,c.subTo(q,c));f.ONE.dlShiftTo(e,q);for(q.subTo(g,g);g.t=0;){var r=c[--m]==d?this.DM:Math.floor(c[m]*k+(c[m-1]+n)*l);if((c[m]+=g.am(0,r,c,o,0,e))0&&c.rShiftTo(i,c);h<0&&f.ZERO.subTo(c,c)}}}};f.prototype.invDigit= -function(){if(this.t<1)return 0;var a=this[0];if((a&1)==0)return 0;var b=a&3,b=b*(2-(a&15)*b)&15,b=b*(2-(a&255)*b)&255,b=b*(2-((a&65535)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV;return b>0?this.DV-b:-b};f.prototype.isEven=function(){return(this.t>0?this[0]&1:this.s)==0};f.prototype.exp=function(a,b){if(a>4294967295||a<1)return f.ONE;var c=p(),e=p(),d=b.convert(this),g=ka(a)-1;for(d.copyTo(c);--g>=0;)if(b.sqrTo(c,e),(a&1<0)b.mulTo(e,d,c);else var h=c,c=e,e=h;return b.revert(c)};f.prototype.toString= -function(a){if(this.s<0)return"-"+this.negate().toString(a);if(a==16)a=4;else if(a==8)a=3;else if(a==2)a=1;else if(a==32)a=5;else if(a==4)a=2;else return this.toRadix(a);var b=(1<0){if(g>g)>0)e=!0,d.push("0123456789abcdefghijklmnopqrstuvwxyz".charAt(c));for(;f>=0;)g>(g+=this.DB-a)):(c=this[f]>>(g-=a)&b,g<=0&&(g+=this.DB,--f)),c>0&&(e=!0),e&&d.push("0123456789abcdefghijklmnopqrstuvwxyz".charAt(c))}return e? -d.join(""):"0"};f.prototype.negate=function(){var a=p();f.ZERO.subTo(this,a);return a};f.prototype.abs=function(){return this.s<0?this.negate():this};f.prototype.compareTo=Y;f.prototype.bitLength=function(){return this.t<=0?0:this.DB*(this.t-1)+ka(this[this.t-1]^this.s&this.DM)};f.prototype.mod=ya;f.prototype.modPowInt=function(a,b){var c;c=a<256||b.isEven()?new P(b):new Q(b);return this.exp(a,c)};f.ZERO=N(0);f.ONE=N(1);$.prototype.convert=Ha;$.prototype.revert=Ha;$.prototype.mulTo=function(a,b,c){a.multiplyTo(b, -c)};$.prototype.sqrTo=function(a,b){a.squareTo(b)};V.prototype.convert=function(a){if(a.s<0||a.t>2*this.m.t)return a.mod(this.m);else if(a.compareTo(this.m)<0)return a;else{var b=p();a.copyTo(b);this.reduce(b);return b}};V.prototype.revert=function(a){return a};V.prototype.reduce=function(a){a.drShiftTo(this.m.t-1,this.r2);if(a.t>this.m.t+1)a.t=this.m.t+1,a.clamp();this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);for(this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);a.compareTo(this.r2)<0;)a.dAddOffset(1, -this.m.t+1);for(a.subTo(this.r2,a);a.compareTo(this.m)>=0;)a.subTo(this.m,a)};V.prototype.mulTo=function(a,b,c){a.multiplyTo(b,c);this.reduce(c)};V.prototype.sqrTo=function(a,b){a.squareTo(b);this.reduce(b)};var C=[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,503,509],ub=67108864/C[C.length-1];f.prototype.chunkSize=function(a){return Math.floor(Math.LN2*this.DB/Math.log(a))};f.prototype.toRadix=function(a){a==null&&(a=10);if(this.signum()==0||a<2||a>36)return"0";var b=this.chunkSize(a),b=Math.pow(a,b),c=N(b),e=p(),d=p(),f="";for(this.divRemTo(c,e,d);e.signum()>0;)f=(b+d.intValue()).toString(a).substr(1)+f,e.divRemTo(c,e,d);return d.intValue().toString(a)+f};f.prototype.fromRadix=function(a, -b){this.fromInt(0);b==null&&(b=10);for(var c=this.chunkSize(b),e=Math.pow(b,c),d=!1,g=0,h=0,i=0;i=c&&(this.dMultiply(e),this.dAddOffset(h,0),h=g=0))}g>0&&(this.dMultiply(Math.pow(b,g)),this.dAddOffset(h,0));d&&f.ZERO.subTo(this,this)};f.prototype.fromNumber=function(a,b,c){if("number"==typeof b)if(a<2)this.fromInt(1);else{this.fromNumber(a,c);this.testBit(a-1)||this.bitwiseTo(f.ONE.shiftLeft(a-1),ua,this);for(this.isEven()&& -this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(f.ONE.shiftLeft(a-1),this)}else{var c=[],e=a&7;c.length=(a>>3)+1;b.nextBytes(c);e>0?c[0]&=(1<>=this.DB;if(a.t>=this.DB;e+=this.s}else{for(e+=this.s;c>=this.DB;e+=a.s}b.s=e<0?-1:0;e>0?b[c++]=e:e<-1&&(b[c++]=this.DV+e);b.t=c;b.clamp()};f.prototype.dMultiply=function(a){this[this.t]=this.am(0,a-1,this, -0,0,this.t);++this.t;this.clamp()};f.prototype.dAddOffset=function(a,b){if(a!=0){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}};f.prototype.multiplyLowerTo=function(a,b,c){var e=Math.min(this.t+a.t,b);c.s=0;for(c.t=e;e>0;)c[--e]=0;var d;for(d=c.t-this.t;e=0;)c[e]=0;for(e=Math.max(b-this.t,0);e0)if(b==0)c=this[0]%a;else for(var e=this.t-1;e>=0;--e)c=(b*c+this[e])%a;return c};f.prototype.millerRabin=function(a){var b=this.subtract(f.ONE),c=b.getLowestSetBit();if(c<=0)return!1;var e=b.shiftRight(c),a=a+1>>1;if(a>C.length)a=C.length;for(var d=p(), -g=0;g>24};f.prototype.shortValue=function(){return this.t==0?this.s:this[0]<<16>>16};f.prototype.signum=function(){return this.s<0?-1:this.t<=0||this.t==1&&this[0]<=0?0:1};f.prototype.toByteArray=function(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,e,d=0;if(a-- >0){if(c>c)!=(this.s&this.DM)>>c)b[d++]=e|this.s<=0;)if(c<8?(e=(this[a]&(1<>(c+=this.DB- -8)):(e=this[a]>>(c-=8)&255,c<=0&&(c+=this.DB,--a)),(e&128)!=0&&(e|=-256),d==0&&(this.s&128)!=(e&128)&&++d,d>0||e!=this.s)b[d++]=e}return b};f.prototype.equals=Z;f.prototype.min=function(a){return this.compareTo(a)<0?this:a};f.prototype.max=function(a){return this.compareTo(a)>0?this:a};f.prototype.and=function(a){var b=p();this.bitwiseTo(a,kb,b);return b};f.prototype.or=function(a){var b=p();this.bitwiseTo(a,ua,b);return b};f.prototype.xor=function(a){var b=p();this.bitwiseTo(a,za,b);return b};f.prototype.andNot= -function(a){var b=p();this.bitwiseTo(a,Aa,b);return b};f.prototype.not=function(){for(var a=p(),b=0;b>=16,c+=16);(a&255)==0&&(a>>=8,c+=8);(a&15)==0&&(a>>=4,c+=4);(a&3)==0&&(a>>=2,c+=2);(a&1)==0&&++c;a=c}return b+a}return this.s<0?this.t*this.DB:-1};f.prototype.bitCount=function(){for(var a=0,b=this.s&this.DM,c=0;c=this.t?this.s!=0:(this[b]&1<1){c=p();for(f.sqrTo(g[1],c);h<=l;)g[h]=p(),f.mulTo(c,g[h-2],g[h]), -h+=2}for(var k=a.t-1,m,o=!0,n=p(),c=ka(a[k])-1;k>=0;){c>=i?m=a[k]>>c-i&l:(m=(a[k]&(1<0&&(m|=a[k-1]>>this.DB+c-i));for(h=e;(m&1)==0;)m>>=1,--h;if((c-=h)<0)c+=this.DB,--k;if(o)g[m].copyTo(d),o=!1;else{for(;h>1;)f.sqrTo(d,n),f.sqrTo(n,d),h-=2;h>0?f.sqrTo(d,n):(h=d,d=n,n=h);f.mulTo(n,g[m],d)}for(;k>=0&&(a[k]&1<=0?(c.subTo(e,c),b&&d.subTo(h,d),g.subTo(i,g)):(e.subTo(c,e),b&&h.subTo(d,h),i.subTo(g,i))}if(e.compareTo(f.ONE)!= -0)return f.ZERO;if(i.compareTo(a)>=0)return i.subtract(a);if(i.signum()<0)i.addTo(a,i);else return i;return i.signum()<0?i.add(a):i};f.prototype.pow=Ia;f.prototype.gcd=Ja;f.prototype.isProbablePrime=function(a){var b,c=this.abs();if(c.t==1&&c[0]<=C[C.length-1]){for(b=0;b0};f.prototype.greaterThanOrEqual=function(a){return this.compareTo(a)>= -0};f.prototype.lessThan=function(a){return this.compareTo(a)<0};f.prototype.lessThanOrEqual=function(a){return this.compareTo(a)<=0};f.prototype.divide=function(a){var b=Ga.call(this,a);return b[1].compareTo(f.ZERO)===0?b[0]:m(b[0],i.makeInstance(b[1],a))};f.prototype.numerator=function(){return this};f.prototype.denominator=function(){return 1};(function(){var a=function(a,c){for(;!da(X(c),a)||!J(a,X(m(c,1)));)c=z(o(m(c,z(o(a,c))),2));return c};f.prototype.integerSqrt=function(){var b;return ha(this)>= -0?a(this,this):(b=this.negate(),g.makeInstance(0,a(b,b)))}})();(function(){f.prototype.sqrt=function(){var a=this.integerSqrt(),b;if(q(X(a),this))return a;b=I(this);return isFinite(b)?b>=0?d.makeInstance(Math.sqrt(b)):g.makeInstance(0,d.makeInstance(Math.sqrt(-b))):a}})();f.prototype.floor=function(){return this};f.prototype.ceiling=function(){return this};f.prototype.expt=function(a){return Ia.call(this,a)};f.prototype.imaginaryPart=function(){return 0};f.prototype.realPart=function(){return this}; -n=function(){return function(a,b,c){var e=512;if(c&&typeof c.limit!=="undefined")e=c.limit;t(a)||l("toRepeatingDecimal: n "+a.toString()+" is not an integer.");t(b)||l("toRepeatingDecimal: d "+b.toString()+" is not an integer.");s(b,0)&&l("toRepeatingDecimal: d equals 0");J(b,0)&&l("toRepeatingDecimal: d < 0");c=J(a,0)?"-":"";a=A(a);c+=qa(a,b);a:{var a=ra(a,b),d=e,e=[],f={};for(f[a]=!0;;){if(d--<=0){b=[e.join(""),"..."];break a}var g=qa(k(a,10),b),a=ra(k(a,10),b);e.push(g.toString());if(f[a])break; -else f[a]=!0}f=a;for(d=[];;)if(g=qa(k(a,10),b),a=ra(k(a,10),b),d.push(g.toString()),s(a,f))break;b=e.join("");for(a=d.join("");b.length>=a.length&&b.substring(b.length-a.length)===a;)b=b.substring(0,b.length-a.length);b=[b,a]}return[c].concat(b)}}();h.fromFixnum=function(a){if(isNaN(a)||!isFinite(a))return d.makeInstance(a);var b=Math.floor(a);return b===a?K(b)?v(Na(a+"")):b:d.makeInstance(a)};h.fromString=ia;h.makeBignum=v;h.makeRational=i.makeInstance;h.makeFloat=d.makeInstance;h.makeComplex=g.makeInstance; -h.makeComplexPolar=function(a,b){return q(b,0)?a:g.makeInstance(k(a,oa(b)),k(a,pa(b)))};h.pi=d.pi;h.e=d.e;h.nan=d.nan;h.negative_inf=d.neginf;h.inf=d.inf;h.negative_one=-1;h.zero=0;h.one=1;h.i=G;h.negative_i=gb;h.negative_zero=L;h.onThrowRuntimeError=function(a){throw Error(a);};h.isSchemeNumber=R;h.isRational=va;h.isReal=E;h.isExact=W;h.isInexact=aa;h.isInteger=t;h.toFixnum=I;h.toExact=S;h.toInexact=ba;h.add=m;h.subtract=w;h.multiply=k;h.divide=o;h.equals=s;h.eqv=q;h.approxEquals=function(a,b,c){return J(A(w(a, -b)),c)};h.greaterThanOrEqual=ma;h.lessThanOrEqual=da;h.greaterThan=U;h.lessThan=J;h.expt=lb;h.exp=F;h.modulo=Pa;h.numerator=ea;h.denominator=Qa;h.integerSqrt=Ya;h.sqrt=D;h.abs=A;h.quotient=qa;h.remainder=ra;h.floor=z;h.ceiling=Ra;h.conjugate=Sa;h.magnitude=function(a){return typeof a==="number"?Math.abs(a):a.magnitude()};h.log=na;h.angle=Ta;h.tan=Ua;h.atan=wa;h.cos=oa;h.sin=pa;h.tan=Ua;h.acos=Va;h.asin=Wa;h.cosh=function(a){return q(a,0)?d.makeInstance(1):o(m(F(a),F(x(a))),2)};h.sinh=function(a){return o(w(F(a), -F(x(a))),2)};h.imaginaryPart=ca;h.realPart=M;h.round=Xa;h.sqr=X;h.gcd=function(a,b){t(a)||l("gcd: the argument "+a.toString()+" is not an integer.",a);for(var c=A(a),e,d,f=0;f any) (scheme-number scheme-number -> any) -> (scheme-number scheme-number) X + // Creates a binary function that works either on fixnums or boxnums. + // Applies the appropriate binary function, ensuring that both scheme numbers are + // lifted to the same level. + var makeNumericBinop = function(onFixnums, onBoxednums, options) { + options = options || {}; + return function(x, y) { + if (options.isXSpecialCase && options.isXSpecialCase(x)) + return options.onXSpecialCase(x, y); + if (options.isYSpecialCase && options.isYSpecialCase(y)) + return options.onYSpecialCase(x, y); + + if (typeof(x) === 'number' && + typeof(y) === 'number') { + return onFixnums(x, y); + } + if (typeof(x) === 'number') { + x = liftFixnumInteger(x, y); + } + if (typeof(y) === 'number') { + y = liftFixnumInteger(y, x); + } + + if (x.level < y.level) x = x.liftTo(y); + if (y.level < x.level) y = y.liftTo(x); + return onBoxednums(x, y); + }; + } + + + // fromFixnum: fixnum -> scheme-number + var fromFixnum = function(x) { + if (isNaN(x) || (! isFinite(x))) { + return FloatPoint.makeInstance(x); + } + var nf = Math.floor(x); + if (nf === x) { + if (isOverflow(nf)) { + return makeBignum(expandExponent(x+'')); + } else { + return nf; + } + } else { + return FloatPoint.makeInstance(x); + } + }; + + var expandExponent = function(s) { + var match = s.match(scientificPattern), mantissaChunks, exponent; + if (match) { + mantissaChunks = match[1].match(/^([^.]*)(.*)$/); + exponent = Number(match[2]); + + if (mantissaChunks[2].length === 0) { + return mantissaChunks[1] + zfill(exponent); + } + + if (exponent >= mantissaChunks[2].length - 1) { + return (mantissaChunks[1] + + mantissaChunks[2].substring(1) + + zfill(exponent - (mantissaChunks[2].length - 1))); + } else { + return (mantissaChunks[1] + + mantissaChunks[2].substring(1, 1+exponent)); + } + } else { + return s; + } + }; + + // zfill: integer -> string + // builds a string of "0"'s of length n. + var zfill = function(n) { + var buffer = []; + buffer.length = n; + for (var i = 0; i < n; i++) { + buffer[i] = '0'; + } + return buffer.join(''); + }; + + + + // liftFixnumInteger: fixnum-integer boxed-scheme-number -> boxed-scheme-number + // Lifts up fixnum integers to a boxed type. + var liftFixnumInteger = function(x, other) { + switch(other.level) { + case 0: // BigInteger + return makeBignum(x); + case 1: // Rational + return new Rational(x, 1); + case 2: // FloatPoint + return new FloatPoint(x); + case 3: // Complex + return new Complex(x, 0); + default: + throwRuntimeError("IMPOSSIBLE: cannot lift fixnum integer to " + other.toString(), x, other); + } + }; + + + // throwRuntimeError: string (scheme-number | undefined) (scheme-number | undefined) -> void + // Throws a runtime error with the given message string. + var throwRuntimeError = function(msg, x, y) { + Numbers['onThrowRuntimeError'](msg, x, y); + }; + + + + // onThrowRuntimeError: string (scheme-number | undefined) (scheme-number | undefined) -> void + // By default, will throw a new Error with the given message. + // Override Numbers['onThrowRuntimeError'] if you need to do something special. + var onThrowRuntimeError = function(msg, x, y) { + throw new Error(msg); + }; + + + // isSchemeNumber: any -> boolean + // Returns true if the thing is a scheme number. + var isSchemeNumber = function(thing) { + return (typeof(thing) === 'number' + || (thing instanceof Rational || + thing instanceof FloatPoint || + thing instanceof Complex || + thing instanceof BigInteger)); + }; + + + // isRational: scheme-number -> boolean + var isRational = function(n) { + return (typeof(n) === 'number' || + (isSchemeNumber(n) && n.isRational())); + }; + + // isReal: scheme-number -> boolean + var isReal = function(n) { + return (typeof(n) === 'number' || + (isSchemeNumber(n) && n.isReal())); + }; + + // isExact: scheme-number -> boolean + var isExact = function(n) { + return (typeof(n) === 'number' || + (isSchemeNumber(n) && n.isExact())); + }; + + // isExact: scheme-number -> boolean + var isInexact = function(n) { + if (typeof(n) === 'number') { + return false; + } else { + return (isSchemeNumber(n) && n.isInexact()); + } + }; + + // isInteger: scheme-number -> boolean + var isInteger = function(n) { + return (typeof(n) === 'number' || + (isSchemeNumber(n) && n.isInteger())); + }; + + // isExactInteger: scheme-number -> boolean + var isExactInteger = function(n) { + return (typeof(n) === 'number' || + (isSchemeNumber(n) && + n.isInteger() && + n.isExact())); + } + + + + // toFixnum: scheme-number -> javascript-number + var toFixnum = function(n) { + if (typeof(n) === 'number') + return n; + return n.toFixnum(); + }; + + // toExact: scheme-number -> scheme-number + var toExact = function(n) { + if (typeof(n) === 'number') + return n; + return n.toExact(); + }; + + + // toExact: scheme-number -> scheme-number + var toInexact = function(n) { + if (typeof(n) === 'number') + return FloatPoint.makeInstance(n); + return n.toInexact(); + }; + + + + ////////////////////////////////////////////////////////////////////// + + + // add: scheme-number scheme-number -> scheme-number + var add = makeNumericBinop( + function(x, y) { + var sum = x + y; + if (isOverflow(sum)) { + return (makeBignum(x)).add(makeBignum(y)); + } else { + return sum; + } + }, + function(x, y) { + return x.add(y); + }, + {isXSpecialCase: function(x) { + return isExactInteger(x) && _integerIsZero(x) }, + onXSpecialCase: function(x, y) { return y; }, + isYSpecialCase: function(y) { + return isExactInteger(y) && _integerIsZero(y) }, + onYSpecialCase: function(x, y) { return x; } + }); + + + // subtract: scheme-number scheme-number -> scheme-number + var subtract = makeNumericBinop( + function(x, y) { + var diff = x - y; + if (isOverflow(diff)) { + return (makeBignum(x)).subtract(makeBignum(y)); + } else { + return diff; + } + }, + function(x, y) { + return x.subtract(y); + }, + {isXSpecialCase: function(x) { + return isExactInteger(x) && _integerIsZero(x) }, + onXSpecialCase: function(x, y) { return negate(y); }, + isYSpecialCase: function(y) { + return isExactInteger(y) && _integerIsZero(y) }, + onYSpecialCase: function(x, y) { return x; } + }); + + + // mulitply: scheme-number scheme-number -> scheme-number + var multiply = makeNumericBinop( + function(x, y) { + var prod = x * y; + if (isOverflow(prod)) { + return (makeBignum(x)).multiply(makeBignum(y)); + } else { + return prod; + } + }, + function(x, y) { + return x.multiply(y); + }, + {isXSpecialCase: function(x) { + return (isExactInteger(x) && + (_integerIsZero(x) || _integerIsOne(x) || _integerIsNegativeOne(x))) }, + onXSpecialCase: function(x, y) { + if (_integerIsZero(x)) + return 0; + if (_integerIsOne(x)) + return y; + if (_integerIsNegativeOne(x)) + return negate(y); + }, + isYSpecialCase: function(y) { + return (isExactInteger(y) && + (_integerIsZero(y) || _integerIsOne(y) || _integerIsNegativeOne(y)))}, + onYSpecialCase: function(x, y) { + if (_integerIsZero(y)) + return 0; + if (_integerIsOne(y)) + return x; + if (_integerIsNegativeOne(y)) + return negate(x); + } + }); + + + // divide: scheme-number scheme-number -> scheme-number + var divide = makeNumericBinop( + function(x, y) { + if (_integerIsZero(y)) + throwRuntimeError("/: division by zero", x, y); + var div = x / y; + if (isOverflow(div)) { + return (makeBignum(x)).divide(makeBignum(y)); + } else if (Math.floor(div) !== div) { + return Rational.makeInstance(x, y); + } else { + return div; + } + }, + function(x, y) { + return x.divide(y); + }, + { isXSpecialCase: function(x) { + return (eqv(x, 0)); + }, + onXSpecialCase: function(x, y) { + if (eqv(y, 0)) { + throwRuntimeError("/: division by zero", x, y); + } + return 0; + }, + isYSpecialCase: function(y) { + return (eqv(y, 0)); }, + onYSpecialCase: function(x, y) { + throwRuntimeError("/: division by zero", x, y); + } + }); + + + // equals: scheme-number scheme-number -> boolean + var equals = makeNumericBinop( + function(x, y) { + return x === y; + }, + function(x, y) { + return x.equals(y); + }); + + + // eqv: scheme-number scheme-number -> boolean + var eqv = function(x, y) { + if (x === y) + return true; + if (typeof(x) === 'number' && typeof(y) === 'number') + return x === y; + if (x === NEGATIVE_ZERO || y === NEGATIVE_ZERO) + return x === y; + if (x instanceof Complex || y instanceof Complex) { + return (eqv(realPart(x), realPart(y)) && + eqv(imaginaryPart(x), imaginaryPart(y))); + } + var ex = isExact(x), ey = isExact(y); + return (((ex && ey) || (!ex && !ey)) && equals(x, y)); + }; + + // approxEqual: scheme-number scheme-number scheme-number -> boolean + var approxEquals = function(x, y, delta) { + return lessThan(abs(subtract(x, y)), + delta); + }; + + // greaterThanOrEqual: scheme-number scheme-number -> boolean + var greaterThanOrEqual = makeNumericBinop( + function(x, y) { + return x >= y; + }, + function(x, y) { + if (!(isReal(x) && isReal(y))) + throwRuntimeError( + ">=: couldn't be applied to complex number", x, y); + return x.greaterThanOrEqual(y); + }); + + + // lessThanOrEqual: scheme-number scheme-number -> boolean + var lessThanOrEqual = makeNumericBinop( + function(x, y){ + + return x <= y; + }, + function(x, y) { + if (!(isReal(x) && isReal(y))) + throwRuntimeError("<=: couldn't be applied to complex number", x, y); + return x.lessThanOrEqual(y); + }); + + + // greaterThan: scheme-number scheme-number -> boolean + var greaterThan = makeNumericBinop( + function(x, y){ + return x > y; + }, + function(x, y) { + if (!(isReal(x) && isReal(y))) + throwRuntimeError(">: couldn't be applied to complex number", x, y); + return x.greaterThan(y); + }); + + + // lessThan: scheme-number scheme-number -> boolean + var lessThan = makeNumericBinop( + function(x, y){ + + return x < y; + }, + function(x, y) { + if (!(isReal(x) && isReal(y))) + throwRuntimeError("<: couldn't be applied to complex number", x, y); + return x.lessThan(y); + }); + + + + // expt: scheme-number scheme-number -> scheme-number + var expt = (function() { + var _expt = makeNumericBinop( + function(x, y){ + var pow = Math.pow(x, y); + if (isOverflow(pow)) { + return (makeBignum(x)).expt(makeBignum(y)); + } else { + return pow; + } + }, + function(x, y) { + if (equals(y, 0)) { + return add(y, 1); + } else { + return x.expt(y); + } + }); + return function(x, y) { + if (equals(y, 0)) + return add(y, 1); + if (isReal(y) && lessThan(y, 0)) { + return _expt(divide(1, x), negate(y)); + } + return _expt(x, y); + }; + })(); + + + // exp: scheme-number -> scheme-number + var exp = function(n) { + if ( eqv(n, 0) ) { + return 1; + } + if (typeof(n) === 'number') { + return FloatPoint.makeInstance(Math.exp(n)); + } + return n.exp(); + }; + + + // modulo: scheme-number scheme-number -> scheme-number + var modulo = function(m, n) { + if (! isInteger(m)) { + throwRuntimeError('modulo: the first argument ' + + m + " is not an integer.", m, n); + } + if (! isInteger(n)) { + throwRuntimeError('modulo: the second argument ' + + n + " is not an integer.", m, n); + } + var result; + if (typeof(m) === 'number') { + result = m % n; + if (n < 0) { + if (result <= 0) + return result; + else + return result + n; + } else { + if (result < 0) + return result + n; + else + return result; + } + } + result = _integerModulo(floor(m), floor(n)); + // The sign of the result should match the sign of n. + if (lessThan(n, 0)) { + if (lessThanOrEqual(result, 0)) { + return result; + } + return add(result, n); + + } else { + if (lessThan(result, 0)) { + return add(result, n); + } + return result; + } + }; + + + + // numerator: scheme-number -> scheme-number + var numerator = function(n) { + if (typeof(n) === 'number') + return n; + return n.numerator(); + }; + + + // denominator: scheme-number -> scheme-number + var denominator = function(n) { + if (typeof(n) === 'number') + return 1; + return n.denominator(); + }; + + // sqrt: scheme-number -> scheme-number + var sqrt = function(n) { + if (typeof(n) === 'number') { + if (n >= 0) { + var result = Math.sqrt(n); + if (Math.floor(result) === result) { + return result; + } else { + return FloatPoint.makeInstance(result); + } + } else { + return (Complex.makeInstance(0, sqrt(-n))); + } + } + return n.sqrt(); + }; + + // abs: scheme-number -> scheme-number + var abs = function(n) { + if (typeof(n) === 'number') { + return Math.abs(n); + } + return n.abs(); + }; + + // floor: scheme-number -> scheme-number + var floor = function(n) { + if (typeof(n) === 'number') + return n; + return n.floor(); + }; + + // ceiling: scheme-number -> scheme-number + var ceiling = function(n) { + if (typeof(n) === 'number') + return n; + return n.ceiling(); + }; + + // conjugate: scheme-number -> scheme-number + var conjugate = function(n) { + if (typeof(n) === 'number') + return n; + return n.conjugate(); + }; + + // magnitude: scheme-number -> scheme-number + var magnitude = function(n) { + if (typeof(n) === 'number') + return Math.abs(n); + return n.magnitude(); + }; + + + // log: scheme-number -> scheme-number + var log = function(n) { + if ( eqv(n, 1) ) { + return 0; + } + if (typeof(n) === 'number') { + return FloatPoint.makeInstance(Math.log(n)); + } + return n.log(); + }; + + // angle: scheme-number -> scheme-number + var angle = function(n) { + if (typeof(n) === 'number') { + if (n > 0) + return 0; + else + return FloatPoint.pi; + } + return n.angle(); + }; + + // tan: scheme-number -> scheme-number + var tan = function(n) { + if (eqv(n, 0)) { return 0; } + if (typeof(n) === 'number') { + return FloatPoint.makeInstance(Math.tan(n)); + } + return n.tan(); + }; + + // atan: scheme-number -> scheme-number + var atan = function(n) { + if (eqv(n, 0)) { return 0; } + if (typeof(n) === 'number') { + return FloatPoint.makeInstance(Math.atan(n)); + } + return n.atan(); + }; + + // cos: scheme-number -> scheme-number + var cos = function(n) { + if (eqv(n, 0)) { return 1; } + if (typeof(n) === 'number') { + return FloatPoint.makeInstance(Math.cos(n)); + } + return n.cos(); + }; + + // sin: scheme-number -> scheme-number + var sin = function(n) { + if (eqv(n, 0)) { return 0; } + if (typeof(n) === 'number') { + return FloatPoint.makeInstance(Math.sin(n)); + } + return n.sin(); + }; + + // acos: scheme-number -> scheme-number + var acos = function(n) { + if (eqv(n, 1)) { return 0; } + if (typeof(n) === 'number') { + return FloatPoint.makeInstance(Math.acos(n)); + } + return n.acos(); + }; + + // asin: scheme-number -> scheme-number + var asin = function(n) { + if (eqv(n, 0)) { return 0; } + if (typeof(n) === 'number') { + return FloatPoint.makeInstance(Math.asin(n)); + } + return n.asin(); + }; + + // imaginaryPart: scheme-number -> scheme-number + var imaginaryPart = function(n) { + if (typeof(n) === 'number') { + return 0; + } + return n.imaginaryPart(); + }; + + // realPart: scheme-number -> scheme-number + var realPart = function(n) { + if (typeof(n) === 'number') { + return n; + } + return n.realPart(); + }; + + // round: scheme-number -> scheme-number + var round = function(n) { + if (typeof(n) === 'number') { + return n; + } + return n.round(); + }; + + + + // sqr: scheme-number -> scheme-number + var sqr = function(x) { + return multiply(x, x); + }; + + + // integerSqrt: scheme-number -> scheme-number + var integerSqrt = function(x) { + if (! isInteger(x)) { + throwRuntimeError('integer-sqrt: the argument ' + x.toString() + + " is not an integer.", x); + } + if (typeof (x) === 'number') { + if(x < 0) { + return Complex.makeInstance(0, + Math.floor(Math.sqrt(-x))) + } else { + return Math.floor(Math.sqrt(x)); + } + } + return x.integerSqrt(); + }; + + + // gcd: scheme-number [scheme-number ...] -> scheme-number + var gcd = function(first, rest) { + if (! isInteger(first)) { + throwRuntimeError('gcd: the argument ' + first.toString() + + " is not an integer.", first); + } + var a = abs(first), t, b; + for(var i = 0; i < rest.length; i++) { + b = abs(rest[i]); + if (! isInteger(b)) { + throwRuntimeError('gcd: the argument ' + b.toString() + + " is not an integer.", b); + } + while (! _integerIsZero(b)) { + t = a; + a = b; + b = _integerModulo(t, b); + } + } + return a; + }; + + // lcm: scheme-number [scheme-number ...] -> scheme-number + var lcm = function(first, rest) { + if (! isInteger(first)) { + throwRuntimeError('lcm: the argument ' + first.toString() + + " is not an integer.", first); + } + var result = abs(first); + if (_integerIsZero(result)) { return 0; } + for (var i = 0; i < rest.length; i++) { + if (! isInteger(rest[i])) { + throwRuntimeError('lcm: the argument ' + rest[i].toString() + + " is not an integer.", rest[i]); + } + var divisor = _integerGcd(result, rest[i]); + if (_integerIsZero(divisor)) { + return 0; + } + result = divide(multiply(result, rest[i]), divisor); + } + return result; + }; + + + var quotient = function(x, y) { + if (! isInteger(x)) { + throwRuntimeError('quotient: the first argument ' + x.toString() + + " is not an integer.", x); + } + if (! isInteger(y)) { + throwRuntimeError('quotient: the second argument ' + y.toString() + + " is not an integer.", y); + } + return _integerQuotient(x, y); + }; + + + var remainder = function(x, y) { + if (! isInteger(x)) { + throwRuntimeError('remainder: the first argument ' + x.toString() + + " is not an integer.", x); + } + if (! isInteger(y)) { + throwRuntimeError('remainder: the second argument ' + y.toString() + + " is not an integer.", y); + } + return _integerRemainder(x, y); + }; + + + // Implementation of the hyperbolic functions + // http://en.wikipedia.org/wiki/Hyperbolic_cosine + var cosh = function(x) { + if (eqv(x, 0)) { + return FloatPoint.makeInstance(1.0); + } + return divide(add(exp(x), exp(negate(x))), + 2); + }; + + var sinh = function(x) { + return divide(subtract(exp(x), exp(negate(x))), + 2); + }; + + + + var makeComplexPolar = function(r, theta) { + // special case: if theta is zero, just return + // the scalar. + if (eqv(theta, 0)) { + return r; + } + return Complex.makeInstance(multiply(r, cos(theta)), + multiply(r, sin(theta))); + }; + + + + ////////////////////////////////////////////////////////////////////// + + // Helpers + + + // IsFinite: scheme-number -> boolean + // Returns true if the scheme number is finite or not. + var isSchemeNumberFinite = function(n) { + if (typeof(n) === 'number') { + return isFinite(n); + } else { + return n.isFinite(); + } + }; + + // isOverflow: javascript-number -> boolean + // Returns true if we consider the number an overflow. + var MIN_FIXNUM = -(9e15); + var MAX_FIXNUM = (9e15); + var isOverflow = function(n) { + return (n < MIN_FIXNUM || MAX_FIXNUM < n); + }; + + + // negate: scheme-number -> scheme-number + // multiplies a number times -1. + var negate = function(n) { + if (typeof(n) === 'number') { + return -n; + } + return n.negate(); + }; + + + // halve: scheme-number -> scheme-number + // Divide a number by 2. + var halve = function(n) { + return divide(n, 2); + }; + + + // timesI: scheme-number scheme-number + // multiplies a number times i. + var timesI = function(x) { + return multiply(x, plusI); + }; + + + // fastExpt: computes n^k by squaring. + // n^k = (n^2)^(k/2) + // Assumes k is non-negative integer. + var fastExpt = function(n, k) { + var acc = 1; + while (true) { + if (_integerIsZero(k)) { + return acc; + } + if (equals(modulo(k, 2), 0)) { + n = multiply(n, n); + k = divide(k, 2); + } else { + acc = multiply(acc, n); + k = subtract(k, 1); + } + } + }; + + + + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + + + // Integer operations + // Integers are either represented as fixnums or as BigIntegers. + + // makeIntegerBinop: (fixnum fixnum -> X) (BigInteger BigInteger -> X) -> X + // Helper to collect the common logic for coersing integer fixnums or bignums to a + // common type before doing an operation. + var makeIntegerBinop = function(onFixnums, onBignums, options) { + options = options || {}; + return (function(m, n) { + if (m instanceof Rational) { + m = numerator(m); + } else if (m instanceof Complex) { + m = realPart(m); + } + + if (n instanceof Rational) { + n = numerator(n); + }else if (n instanceof Complex) { + n = realPart(n); + } + + if (typeof(m) === 'number' && typeof(n) === 'number') { + var result = onFixnums(m, n); + if (! isOverflow(result) || + (options.ignoreOverflow)) { + return result; + } + } + if (m instanceof FloatPoint || n instanceof FloatPoint) { + if (options.doNotCoerseToFloating) { + return onFixnums(toFixnum(m), toFixnum(n)); + } + else { + return FloatPoint.makeInstance( + onFixnums(toFixnum(m), toFixnum(n))); + } + } + if (typeof(m) === 'number') { + m = makeBignum(m); + } + if (typeof(n) === 'number') { + n = makeBignum(n); + } + return onBignums(m, n); + }); + }; + + + var makeIntegerUnOp = function(onFixnums, onBignums, options) { + options = options || {}; + return (function(m) { + if (m instanceof Rational) { + m = numerator(m); + } else if (m instanceof Complex) { + m = realPart(m); + } + + if (typeof(m) === 'number') { + var result = onFixnums(m); + if (! isOverflow(result) || + (options.ignoreOverflow)) { + return result; + } + } + if (m instanceof FloatPoint) { + return onFixnums(toFixnum(m)); + } + if (typeof(m) === 'number') { + m = makeBignum(m); + } + return onBignums(m); + }); + }; + + + + // _integerModulo: integer-scheme-number integer-scheme-number -> integer-scheme-number + var _integerModulo = makeIntegerBinop( + function(m, n) { + return m % n; + }, + function(m, n) { + return bnMod.call(m, n); + }); + + + // _integerGcd: integer-scheme-number integer-scheme-number -> integer-scheme-number + var _integerGcd = makeIntegerBinop( + function(a, b) { + var t; + while (b !== 0) { + t = a; + a = b; + b = t % b; + } + return a; + }, + function(m, n) { + return bnGCD.call(m, n); + }); + + + // _integerIsZero: integer-scheme-number -> boolean + // Returns true if the number is zero. + var _integerIsZero = makeIntegerUnOp( + function(n){ + return n === 0; + }, + function(n) { + return bnEquals.call(n, BigInteger.ZERO); + } + ); + + + // _integerIsOne: integer-scheme-number -> boolean + var _integerIsOne = makeIntegerUnOp( + function(n) { + return n === 1; + }, + function(n) { + return bnEquals.call(n, BigInteger.ONE); + }); + + + + // _integerIsNegativeOne: integer-scheme-number -> boolean + var _integerIsNegativeOne = makeIntegerUnOp( + function(n) { + return n === -1; + }, + function(n) { + return bnEquals.call(n, BigInteger.NEGATIVE_ONE); + }); + + + + // _integerAdd: integer-scheme-number integer-scheme-number -> integer-scheme-number + var _integerAdd = makeIntegerBinop( + function(m, n) { + return m + n; + }, + function(m, n) { + return bnAdd.call(m, n); + }); + + // _integerSubtract: integer-scheme-number integer-scheme-number -> integer-scheme-number + var _integerSubtract = makeIntegerBinop( + function(m, n) { + return m - n; + }, + function(m, n) { + return bnSubtract.call(m, n); + }); + + // _integerMultiply: integer-scheme-number integer-scheme-number -> integer-scheme-number + var _integerMultiply = makeIntegerBinop( + function(m, n) { + return m * n; + }, + function(m, n) { + return bnMultiply.call(m, n); + }); + + //_integerQuotient: integer-scheme-number integer-scheme-number -> integer-scheme-number + var _integerQuotient = makeIntegerBinop( + function(m, n) { + return ((m - (m % n))/ n); + }, + function(m, n) { + return bnDivide.call(m, n); + }); + + var _integerRemainder = makeIntegerBinop( + function(m, n) { + return m % n; + }, + function(m, n) { + return bnRemainder.call(m, n); + }); + + + // _integerDivideToFixnum: integer-scheme-number integer-scheme-number -> fixnum + var _integerDivideToFixnum = makeIntegerBinop( + function(m, n) { + return m / n; + }, + function(m, n) { + return toFixnum(m) / toFixnum(n); + }, + {ignoreOverflow: true, + doNotCoerseToFloating: true}); + + + // _integerEquals: integer-scheme-number integer-scheme-number -> boolean + var _integerEquals = makeIntegerBinop( + function(m, n) { + return m === n; + }, + function(m, n) { + return bnEquals.call(m, n); + }, + {doNotCoerseToFloating: true}); + + // _integerGreaterThan: integer-scheme-number integer-scheme-number -> boolean + var _integerGreaterThan = makeIntegerBinop( + function(m, n) { + return m > n; + }, + function(m, n) { + return bnCompareTo.call(m, n) > 0; + }, + {doNotCoerseToFloating: true}); + + // _integerLessThan: integer-scheme-number integer-scheme-number -> boolean + var _integerLessThan = makeIntegerBinop( + function(m, n) { + return m < n; + }, + function(m, n) { + return bnCompareTo.call(m, n) < 0; + }, + {doNotCoerseToFloating: true}); + + // _integerGreaterThanOrEqual: integer-scheme-number integer-scheme-number -> boolean + var _integerGreaterThanOrEqual = makeIntegerBinop( + function(m, n) { + return m >= n; + }, + function(m, n) { + return bnCompareTo.call(m, n) >= 0; + }, + {doNotCoerseToFloating: true}); + + // _integerLessThanOrEqual: integer-scheme-number integer-scheme-number -> boolean + var _integerLessThanOrEqual = makeIntegerBinop( + function(m, n) { + return m <= n; + }, + function(m, n) { + return bnCompareTo.call(m, n) <= 0; + }, + {doNotCoerseToFloating: true}); + + + + ////////////////////////////////////////////////////////////////////// + // The boxed number types are expected to implement the following + // interface. + // + // toString: -> string + + // level: number + + // liftTo: scheme-number -> scheme-number + + // isFinite: -> boolean + + // isInteger: -> boolean + // Produce true if this number can be coersed into an integer. + + // isRational: -> boolean + // Produce true if the number is rational. + + // isReal: -> boolean + // Produce true if the number is real. + + // isExact: -> boolean + // Produce true if the number is exact + + // toExact: -> scheme-number + // Produce an exact number. + + // toFixnum: -> javascript-number + // Produce a javascript number. + + // greaterThan: scheme-number -> boolean + // Compare against instance of the same type. + + // greaterThanOrEqual: scheme-number -> boolean + // Compare against instance of the same type. + + // lessThan: scheme-number -> boolean + // Compare against instance of the same type. + + // lessThanOrEqual: scheme-number -> boolean + // Compare against instance of the same type. + + // add: scheme-number -> scheme-number + // Add with an instance of the same type. + + // subtract: scheme-number -> scheme-number + // Subtract with an instance of the same type. + + // multiply: scheme-number -> scheme-number + // Multiply with an instance of the same type. + + // divide: scheme-number -> scheme-number + // Divide with an instance of the same type. + + // numerator: -> scheme-number + // Return the numerator. + + // denominator: -> scheme-number + // Return the denominator. + + // integerSqrt: -> scheme-number + // Produce the integer square root. + + // sqrt: -> scheme-number + // Produce the square root. + + // abs: -> scheme-number + // Produce the absolute value. + + // floor: -> scheme-number + // Produce the floor. + + // ceiling: -> scheme-number + // Produce the ceiling. + + // conjugate: -> scheme-number + // Produce the conjugate. + + // magnitude: -> scheme-number + // Produce the magnitude. + + // log: -> scheme-number + // Produce the log. + + // angle: -> scheme-number + // Produce the angle. + + // atan: -> scheme-number + // Produce the arc tangent. + + // cos: -> scheme-number + // Produce the cosine. + + // sin: -> scheme-number + // Produce the sine. + + // expt: scheme-number -> scheme-number + // Produce the power to the input. + + // exp: -> scheme-number + // Produce e raised to the given power. + + // acos: -> scheme-number + // Produce the arc cosine. + + // asin: -> scheme-number + // Produce the arc sine. + + // imaginaryPart: -> scheme-number + // Produce the imaginary part + + // realPart: -> scheme-number + // Produce the real part. + + // round: -> scheme-number + // Round to the nearest integer. + + // equals: scheme-number -> boolean + // Produce true if the given number of the same type is equal. + + + + ////////////////////////////////////////////////////////////////////// + + // Rationals + + + var Rational = function(n, d) { + this.n = n; + this.d = d; + }; + + + Rational.prototype.toString = function() { + if (_integerIsOne(this.d)) { + return this.n.toString() + ""; + } else { + return this.n.toString() + "/" + this.d.toString(); + } + }; + + + Rational.prototype.level = 1; + + + Rational.prototype.liftTo = function(target) { + if (target.level === 2) + return new FloatPoint( + _integerDivideToFixnum(this.n, this.d)); + if (target.level === 3) + return new Complex(this, 0); + return throwRuntimeError("invalid level of Number", this, target); + }; + + Rational.prototype.isFinite = function() { + return true; + }; + + Rational.prototype.equals = function(other) { + return (other instanceof Rational && + _integerEquals(this.n, other.n) && + _integerEquals(this.d, other.d)); + }; + + + + Rational.prototype.isInteger = function() { + return _integerIsOne(this.d); + }; + + Rational.prototype.isRational = function() { + return true; + }; + + Rational.prototype.isReal = function() { + return true; + }; + + + Rational.prototype.add = function(other) { + return Rational.makeInstance(_integerAdd(_integerMultiply(this.n, other.d), + _integerMultiply(this.d, other.n)), + _integerMultiply(this.d, other.d)); + }; + + Rational.prototype.subtract = function(other) { + return Rational.makeInstance(_integerSubtract(_integerMultiply(this.n, other.d), + _integerMultiply(this.d, other.n)), + _integerMultiply(this.d, other.d)); + }; + + Rational.prototype.negate = function() { + return Rational.makeInstance(-this.n, this.d) + }; + + Rational.prototype.multiply = function(other) { + return Rational.makeInstance(_integerMultiply(this.n, other.n), + _integerMultiply(this.d, other.d)); + }; + + Rational.prototype.divide = function(other) { + if (_integerIsZero(this.d) || _integerIsZero(other.n)) { + throwRuntimeError("/: division by zero", this, other); + } + return Rational.makeInstance(_integerMultiply(this.n, other.d), + _integerMultiply(this.d, other.n)); + }; + + + Rational.prototype.toExact = function() { + return this; + }; + + Rational.prototype.toInexact = function() { + return FloatPoint.makeInstance(this.toFixnum()); + }; + + + Rational.prototype.isExact = function() { + return true; + }; + + Rational.prototype.isInexact = function() { + return false; + }; + + + Rational.prototype.toFixnum = function() { + return _integerDivideToFixnum(this.n, this.d); + }; + + Rational.prototype.numerator = function() { + return this.n; + }; + + Rational.prototype.denominator = function() { + return this.d; + }; + + Rational.prototype.greaterThan = function(other) { + return _integerGreaterThan(_integerMultiply(this.n, other.d), + _integerMultiply(this.d, other.n)); + }; + + Rational.prototype.greaterThanOrEqual = function(other) { + return _integerGreaterThanOrEqual(_integerMultiply(this.n, other.d), + _integerMultiply(this.d, other.n)); + }; + + Rational.prototype.lessThan = function(other) { + return _integerLessThan(_integerMultiply(this.n, other.d), + _integerMultiply(this.d, other.n)); + }; + + Rational.prototype.lessThanOrEqual = function(other) { + return _integerLessThanOrEqual(_integerMultiply(this.n, other.d), + _integerMultiply(this.d, other.n)); + }; + + Rational.prototype.integerSqrt = function() { + var result = sqrt(this); + if (isRational(result)) { + return toExact(floor(result)); + } else if (isReal(result)) { + return toExact(floor(result)); + } else { + return Complex.makeInstance(toExact(floor(realPart(result))), + toExact(floor(imaginaryPart(result)))); + } + }; + + + Rational.prototype.sqrt = function() { + if (_integerGreaterThanOrEqual(this.n, 0)) { + var newN = sqrt(this.n); + var newD = sqrt(this.d); + if (equals(floor(newN), newN) && + equals(floor(newD), newD)) { + return Rational.makeInstance(newN, newD); + } else { + return FloatPoint.makeInstance(_integerDivideToFixnum(newN, newD)); + } + } else { + var newN = sqrt(negate(this.n)); + var newD = sqrt(this.d); + if (equals(floor(newN), newN) && + equals(floor(newD), newD)) { + return Complex.makeInstance( + 0, + Rational.makeInstance(newN, newD)); + } else { + return Complex.makeInstance( + 0, + FloatPoint.makeInstance(_integerDivideToFixnum(newN, newD))); + } + } + }; + + Rational.prototype.abs = function() { + return Rational.makeInstance(abs(this.n), + this.d); + }; + + + Rational.prototype.floor = function() { + var quotient = _integerQuotient(this.n, this.d); + if (_integerLessThan(this.n, 0)) { + return subtract(quotient, 1); + } else { + return quotient; + } + }; + + + Rational.prototype.ceiling = function() { + var quotient = _integerQuotient(this.n, this.d); + if (_integerLessThan(this.n, 0)) { + return quotient; + } else { + return add(quotient, 1); + } + }; + + Rational.prototype.conjugate = function() { + return this; + }; + + Rational.prototype.magnitude = Rational.prototype.abs; + + Rational.prototype.log = function(){ + return FloatPoint.makeInstance(Math.log(this.n / this.d)); + }; + + Rational.prototype.angle = function(){ + if (_integerIsZero(this.n)) + return 0; + if (_integerGreaterThan(this.n, 0)) + return 0; + else + return FloatPoint.pi; + }; + + Rational.prototype.tan = function(){ + return FloatPoint.makeInstance(Math.tan(_integerDivideToFixnum(this.n, this.d))); + }; + + Rational.prototype.atan = function(){ + return FloatPoint.makeInstance(Math.atan(_integerDivideToFixnum(this.n, this.d))); + }; + + Rational.prototype.cos = function(){ + return FloatPoint.makeInstance(Math.cos(_integerDivideToFixnum(this.n, this.d))); + }; + + Rational.prototype.sin = function(){ + return FloatPoint.makeInstance(Math.sin(_integerDivideToFixnum(this.n, this.d))); + }; + + Rational.prototype.expt = function(a){ + if (isExactInteger(a) && greaterThanOrEqual(a, 0)) { + return fastExpt(this, a); + } + return FloatPoint.makeInstance(Math.pow(_integerDivideToFixnum(this.n, this.d), + _integerDivideToFixnum(a.n, a.d))); + }; + + Rational.prototype.exp = function(){ + return FloatPoint.makeInstance(Math.exp(_integerDivideToFixnum(this.n, this.d))); + }; + + Rational.prototype.acos = function(){ + return FloatPoint.makeInstance(Math.acos(_integerDivideToFixnum(this.n, this.d))); + }; + + Rational.prototype.asin = function(){ + return FloatPoint.makeInstance(Math.asin(_integerDivideToFixnum(this.n, this.d))); + }; + + Rational.prototype.imaginaryPart = function(){ + return 0; + }; + + Rational.prototype.realPart = function(){ + return this; + }; + + + Rational.prototype.round = function() { + // FIXME: not correct when values are bignums + if (equals(this.d, 2)) { + // Round to even if it's a n/2 + var v = _integerDivideToFixnum(this.n, this.d); + var fl = Math.floor(v); + var ce = Math.ceil(v); + if (_integerIsZero(fl % 2)) { + return fl; + } + else { + return ce; + } + } else { + return Math.round(this.n / this.d); + } + }; + + + Rational.makeInstance = function(n, d) { + if (n === undefined) + throwRuntimeError("n undefined", n, d); + + if (d === undefined) { d = 1; } + + if (_integerLessThan(d, 0)) { + n = negate(n); + d = negate(d); + } + + var divisor = _integerGcd(abs(n), abs(d)); + n = _integerQuotient(n, divisor); + d = _integerQuotient(d, divisor); + + // Optimization: if we can get around construction the rational + // in favor of just returning n, do it: + if (_integerIsOne(d) || _integerIsZero(n)) { + return n; + } + + return new Rational(n, d); + }; + + + + // Floating Point numbers + var FloatPoint = function(n) { + this.n = n; + }; + FloatPoint = FloatPoint; + + + var NaN = new FloatPoint(Number.NaN); + var inf = new FloatPoint(Number.POSITIVE_INFINITY); + var neginf = new FloatPoint(Number.NEGATIVE_INFINITY); + + // We use these two constants to represent the floating-point coersion + // of bignums that can't be represented with fidelity. + var TOO_POSITIVE_TO_REPRESENT = new FloatPoint(Number.POSITIVE_INFINITY); + var TOO_NEGATIVE_TO_REPRESENT = new FloatPoint(Number.NEGATIVE_INFINITY); + + // Negative zero is a distinguished value representing -0.0. + // There should only be one instance for -0.0. + var NEGATIVE_ZERO = new FloatPoint(-0.0); + var INEXACT_ZERO = new FloatPoint(0.0); + + FloatPoint.pi = new FloatPoint(Math.PI); + FloatPoint.e = new FloatPoint(Math.E); + FloatPoint.nan = NaN; + FloatPoint.inf = inf; + FloatPoint.neginf = neginf; + + FloatPoint.makeInstance = function(n) { + if (isNaN(n)) { + return FloatPoint.nan; + } else if (n === Number.POSITIVE_INFINITY) { + return FloatPoint.inf; + } else if (n === Number.NEGATIVE_INFINITY) { + return FloatPoint.neginf; + } else if (n === 0) { + if ((1/n) === -Infinity) { + return NEGATIVE_ZERO; + } else { + return INEXACT_ZERO; + } + } + return new FloatPoint(n); + }; + + + FloatPoint.prototype.isExact = function() { + return false; + }; + + FloatPoint.prototype.isInexact = function() { + return true; + }; + + + FloatPoint.prototype.isFinite = function() { + return (isFinite(this.n) || + this === TOO_POSITIVE_TO_REPRESENT || + this === TOO_NEGATIVE_TO_REPRESENT); + }; + + + FloatPoint.prototype.toExact = function() { + // The precision of ieee is about 16 decimal digits, which we use here. + if (! isFinite(this.n) || isNaN(this.n)) { + throwRuntimeError("toExact: no exact representation for " + this, this); + } + + var stringRep = this.n.toString(); + var match = stringRep.match(/^(.*)\.(.*)$/); + if (match) { + var intPart = parseInt(match[1]); + var fracPart = parseInt(match[2]); + var tenToDecimalPlaces = Math.pow(10, match[2].length); + return Rational.makeInstance(Math.round(this.n * tenToDecimalPlaces), + tenToDecimalPlaces); + } + else { + return this.n; + } + }; + + FloatPoint.prototype.toInexact = function() { + return this; + }; + + FloatPoint.prototype.isInexact = function() { + return true; + }; + + + FloatPoint.prototype.level = 2; + + + FloatPoint.prototype.liftTo = function(target) { + if (target.level === 3) + return new Complex(this, 0); + return throwRuntimeError("invalid level of Number", this, target); + }; + + FloatPoint.prototype.toString = function() { + if (isNaN(this.n)) + return "+nan.0"; + if (this.n === Number.POSITIVE_INFINITY) + return "+inf.0"; + if (this.n === Number.NEGATIVE_INFINITY) + return "-inf.0"; + if (this === NEGATIVE_ZERO) + return "-0.0"; + var partialResult = this.n.toString(); + if (! partialResult.match('\\.')) { + return partialResult + ".0"; + } else { + return partialResult; + } + }; + + + FloatPoint.prototype.equals = function(other, aUnionFind) { + return ((other instanceof FloatPoint) && + ((this.n === other.n))); + }; + + + + FloatPoint.prototype.isRational = function() { + return this.isFinite(); + }; + + FloatPoint.prototype.isInteger = function() { + return this.isFinite() && this.n === Math.floor(this.n); + }; + + FloatPoint.prototype.isReal = function() { + return true; + }; + + + // sign: Number -> {-1, 0, 1} + var sign = function(n) { + if (lessThan(n, 0)) { + return -1; + } else if (greaterThan(n, 0)) { + return 1; + } else if (n === NEGATIVE_ZERO) { + return -1; + } else { + return 0; + } + }; + + + FloatPoint.prototype.add = function(other) { + if (this.isFinite() && other.isFinite()) { + return FloatPoint.makeInstance(this.n + other.n); + } else { + if (isNaN(this.n) || isNaN(other.n)) { + return NaN; + } else if (this.isFinite() && ! other.isFinite()) { + return other; + } else if (!this.isFinite() && other.isFinite()) { + return this; + } else { + return ((sign(this) * sign(other) === 1) ? + this : NaN); + }; + } + }; + + FloatPoint.prototype.subtract = function(other) { + if (this.isFinite() && other.isFinite()) { + return FloatPoint.makeInstance(this.n - other.n); + } else if (isNaN(this.n) || isNaN(other.n)) { + return NaN; + } else if (! this.isFinite() && ! other.isFinite()) { + if (sign(this) === sign(other)) { + return NaN; + } else { + return this; + } + } else if (this.isFinite()) { + return multiply(other, -1); + } else { // other.isFinite() + return this; + } + }; + + + FloatPoint.prototype.negate = function() { + return FloatPoint.makeInstance(-this.n); + }; + + FloatPoint.prototype.multiply = function(other) { + return FloatPoint.makeInstance(this.n * other.n); + }; + + FloatPoint.prototype.divide = function(other) { + return FloatPoint.makeInstance(this.n / other.n); + }; + + + FloatPoint.prototype.toFixnum = function() { + return this.n; + }; + + FloatPoint.prototype.numerator = function() { + var stringRep = this.n.toString(); + var match = stringRep.match(/^(.*)\.(.*)$/); + if (match) { + var afterDecimal = parseInt(match[2]); + var factorToInt = Math.pow(10, match[2].length); + var extraFactor = _integerGcd(factorToInt, afterDecimal); + var multFactor = factorToInt / extraFactor; + return FloatPoint.makeInstance( Math.round(this.n * multFactor) ); + } else { + return this; + } + }; + + FloatPoint.prototype.denominator = function() { + var stringRep = this.n.toString(); + var match = stringRep.match(/^(.*)\.(.*)$/); + if (match) { + var afterDecimal = parseInt(match[2]); + var factorToInt = Math.pow(10, match[2].length); + var extraFactor = _integerGcd(factorToInt, afterDecimal); + return FloatPoint.makeInstance( Math.round(factorToInt/extraFactor) ); + } else { + return FloatPoint.makeInstance(1); + } + }; + + + FloatPoint.prototype.floor = function() { + return FloatPoint.makeInstance(Math.floor(this.n)); + }; + + FloatPoint.prototype.ceiling = function() { + return FloatPoint.makeInstance(Math.ceil(this.n)); + }; + + + FloatPoint.prototype.greaterThan = function(other) { + return this.n > other.n; + }; + + FloatPoint.prototype.greaterThanOrEqual = function(other) { + return this.n >= other.n; + }; + + FloatPoint.prototype.lessThan = function(other) { + return this.n < other.n; + }; + + FloatPoint.prototype.lessThanOrEqual = function(other) { + return this.n <= other.n; + }; + + + FloatPoint.prototype.integerSqrt = function() { + if (this === NEGATIVE_ZERO) { return this; } + if (isInteger(this)) { + if(this.n >= 0) { + return FloatPoint.makeInstance(Math.floor(Math.sqrt(this.n))); + } else { + return Complex.makeInstance( + INEXACT_ZERO, + FloatPoint.makeInstance(Math.floor(Math.sqrt(-this.n)))); + } + } else { + throwRuntimeError("integerSqrt: can only be applied to an integer", this); + } + }; + + FloatPoint.prototype.sqrt = function() { + if (this.n < 0) { + var result = Complex.makeInstance( + 0, + FloatPoint.makeInstance(Math.sqrt(-this.n))); + return result; + } else { + return FloatPoint.makeInstance(Math.sqrt(this.n)); + } + }; + + FloatPoint.prototype.abs = function() { + return FloatPoint.makeInstance(Math.abs(this.n)); + }; + + + + FloatPoint.prototype.log = function(){ + if (this.n < 0) + return (new Complex(this, 0)).log(); + else + return FloatPoint.makeInstance(Math.log(this.n)); + }; + + FloatPoint.prototype.angle = function(){ + if (0 === this.n) + return 0; + if (this.n > 0) + return 0; + else + return FloatPoint.pi; + }; + + FloatPoint.prototype.tan = function(){ + return FloatPoint.makeInstance(Math.tan(this.n)); + }; + + FloatPoint.prototype.atan = function(){ + return FloatPoint.makeInstance(Math.atan(this.n)); + }; + + FloatPoint.prototype.cos = function(){ + return FloatPoint.makeInstance(Math.cos(this.n)); + }; + + FloatPoint.prototype.sin = function(){ + return FloatPoint.makeInstance(Math.sin(this.n)); + }; + + FloatPoint.prototype.expt = function(a){ + if (this.n === 1) { + if (a.isFinite()) { + return this; + } else if (isNaN(a.n)){ + return this; + } else { + return this; + } + } else { + return FloatPoint.makeInstance(Math.pow(this.n, a.n)); + } + }; + + FloatPoint.prototype.exp = function(){ + return FloatPoint.makeInstance(Math.exp(this.n)); + }; + + FloatPoint.prototype.acos = function(){ + return FloatPoint.makeInstance(Math.acos(this.n)); + }; + + FloatPoint.prototype.asin = function(){ + return FloatPoint.makeInstance(Math.asin(this.n)); + }; + + FloatPoint.prototype.imaginaryPart = function(){ + return 0; + }; + + FloatPoint.prototype.realPart = function(){ + return this; + }; + + + FloatPoint.prototype.round = function(){ + if (isFinite(this.n)) { + if (this === NEGATIVE_ZERO) { + return this; + } + if (Math.abs(Math.floor(this.n) - this.n) === 0.5) { + if (Math.floor(this.n) % 2 === 0) + return FloatPoint.makeInstance(Math.floor(this.n)); + return FloatPoint.makeInstance(Math.ceil(this.n)); + } else { + return FloatPoint.makeInstance(Math.round(this.n)); + } + } else { + return this; + } + }; + + + FloatPoint.prototype.conjugate = function() { + return this; + }; + + FloatPoint.prototype.magnitude = FloatPoint.prototype.abs; + + + + ////////////////////////////////////////////////////////////////////// + // Complex numbers + ////////////////////////////////////////////////////////////////////// + + var Complex = function(r, i){ + this.r = r; + this.i = i; + }; + + // Constructs a complex number from two basic number r and i. r and i can + // either be plt.type.Rational or plt.type.FloatPoint. + Complex.makeInstance = function(r, i){ + if (i === undefined) { i = 0; } + if (isExact(i) && isInteger(i) && _integerIsZero(i)) { + return r; + } + if (isInexact(r) || isInexact(i)) { + r = toInexact(r); + i = toInexact(i); + } + return new Complex(r, i); + }; + + Complex.prototype.toString = function() { + var realPart = this.r.toString(), imagPart = this.i.toString(); + if (imagPart[0] === '-' || imagPart[0] === '+') { + return realPart + imagPart + 'i'; + } else { + return realPart + "+" + imagPart + 'i'; + } + }; + + + Complex.prototype.isFinite = function() { + return isSchemeNumberFinite(this.r) && isSchemeNumberFinite(this.i); + }; + + + Complex.prototype.isRational = function() { + return isRational(this.r) && eqv(this.i, 0); + }; + + Complex.prototype.isInteger = function() { + return (isInteger(this.r) && + eqv(this.i, 0)); + }; + + Complex.prototype.toExact = function() { + return Complex.makeInstance( toExact(this.r), toExact(this.i) ); + }; + + Complex.prototype.toInexact = function() { + return Complex.makeInstance(toInexact(this.r), + toInexact(this.i)); + }; + + + Complex.prototype.isExact = function() { + return isExact(this.r) && isExact(this.i); + }; + + + Complex.prototype.isInexact = function() { + return isInexact(this.r) || isInexact(this.i); + }; + + + Complex.prototype.level = 3; + + + Complex.prototype.liftTo = function(target){ + throwRuntimeError("Don't know how to lift Complex number", this, target); + }; + + Complex.prototype.equals = function(other) { + var result = ((other instanceof Complex) && + (equals(this.r, other.r)) && + (equals(this.i, other.i))); + return result; + }; + + + + Complex.prototype.greaterThan = function(other) { + if (! this.isReal() || ! other.isReal()) { + throwRuntimeError(">: expects argument of type real number", this, other); + } + return greaterThan(this.r, other.r); + }; + + Complex.prototype.greaterThanOrEqual = function(other) { + if (! this.isReal() || ! other.isReal()) { + throwRuntimeError(">=: expects argument of type real number", this, other); + } + return greaterThanOrEqual(this.r, other.r); + }; + + Complex.prototype.lessThan = function(other) { + if (! this.isReal() || ! other.isReal()) { + throwRuntimeError("<: expects argument of type real number", this, other); + } + return lessThan(this.r, other.r); + }; + + Complex.prototype.lessThanOrEqual = function(other) { + if (! this.isReal() || ! other.isReal()) { + throwRuntimeError("<=: expects argument of type real number", this, other); + } + return lessThanOrEqual(this.r, other.r); + }; + + + Complex.prototype.abs = function(){ + if (!equals(this.i, 0).valueOf()) + throwRuntimeError("abs: expects argument of type real number", this); + return abs(this.r); + }; + + Complex.prototype.toFixnum = function(){ + if (!equals(this.i, 0).valueOf()) + throwRuntimeError("toFixnum: expects argument of type real number", this); + return toFixnum(this.r); + }; + + Complex.prototype.numerator = function() { + if (!this.isReal()) + throwRuntimeError("numerator: can only be applied to real number", this); + return numerator(this.n); + }; + + + Complex.prototype.denominator = function() { + if (!this.isReal()) + throwRuntimeError("floor: can only be applied to real number", this); + return denominator(this.n); + }; + + Complex.prototype.add = function(other){ + return Complex.makeInstance( + add(this.r, other.r), + add(this.i, other.i)); + }; + + Complex.prototype.subtract = function(other){ + return Complex.makeInstance( + subtract(this.r, other.r), + subtract(this.i, other.i)); + }; + + Complex.prototype.negate = function() { + return Complex.makeInstance(negate(this.r), + negate(this.i)); + }; + + + Complex.prototype.multiply = function(other){ + // If the other value is real, just do primitive division + if (other.isReal()) { + return Complex.makeInstance( + multiply(this.r, other.r), + multiply(this.i, other.r)); + } + var r = subtract( + multiply(this.r, other.r), + multiply(this.i, other.i)); + var i = add( + multiply(this.r, other.i), + multiply(this.i, other.r)); + return Complex.makeInstance(r, i); + }; + + + + + + Complex.prototype.divide = function(other){ + var a, b, c, d, r, x, y; + // If the other value is real, just do primitive division + if (other.isReal()) { + return Complex.makeInstance( + divide(this.r, other.r), + divide(this.i, other.r)); + } + + if (this.isInexact() || other.isInexact()) { + // http://portal.acm.org/citation.cfm?id=1039814 + // We currently use Smith's method, though we should + // probably switch over to Priest's method. + a = this.r; + b = this.i; + c = other.r; + d = other.i; + if (lessThanOrEqual(abs(d), abs(c))) { + r = divide(d, c); + x = divide(add(a, multiply(b, r)), + add(c, multiply(d, r))); + y = divide(subtract(b, multiply(a, r)), + add(c, multiply(d, r))); + } else { + r = divide(c, d); + x = divide(add(multiply(a, r), b), + add(multiply(c, r), d)); + y = divide(subtract(multiply(b, r), a), + add(multiply(c, r), d)); + } + return Complex.makeInstance(x, y); + } else { + var con = conjugate(other); + var up = multiply(this, con); + + // Down is guaranteed to be real by this point. + var down = realPart(multiply(other, con)); + + var result = Complex.makeInstance( + divide(realPart(up), down), + divide(imaginaryPart(up), down)); + return result; + } + }; + + Complex.prototype.conjugate = function(){ + var result = Complex.makeInstance( + this.r, + subtract(0, this.i)); + + return result; + }; + + Complex.prototype.magnitude = function(){ + var sum = add( + multiply(this.r, this.r), + multiply(this.i, this.i)); + return sqrt(sum); + }; + + Complex.prototype.isReal = function(){ + return eqv(this.i, 0); + }; + + Complex.prototype.integerSqrt = function() { + if (isInteger(this)) { + return integerSqrt(this.r); + } else { + throwRuntimeError("integerSqrt: can only be applied to an integer", this); + } + }; + + Complex.prototype.sqrt = function(){ + if (this.isReal()) + return sqrt(this.r); + // http://en.wikipedia.org/wiki/Square_root#Square_roots_of_negative_and_complex_numbers + var r_plus_x = add(this.magnitude(), this.r); + + var r = sqrt(halve(r_plus_x)); + + var i = divide(this.i, sqrt(multiply(r_plus_x, 2))); + + + return Complex.makeInstance(r, i); + }; + + Complex.prototype.log = function(){ + var m = this.magnitude(); + var theta = this.angle(); + var result = add( + log(m), + timesI(theta)); + return result; + }; + + Complex.prototype.angle = function(){ + if (this.isReal()) { + return angle(this.r); + } + if (equals(0, this.r)) { + var tmp = halve(FloatPoint.pi); + return greaterThan(this.i, 0) ? + tmp : negate(tmp); + } else { + var tmp = atan(divide(abs(this.i), abs(this.r))); + if (greaterThan(this.r, 0)) { + return greaterThan(this.i, 0) ? + tmp : negate(tmp); + } else { + return greaterThan(this.i, 0) ? + subtract(FloatPoint.pi, tmp) : subtract(tmp, FloatPoint.pi); + } + } + }; + + var plusI = Complex.makeInstance(0, 1); + var minusI = Complex.makeInstance(0, -1); + + + Complex.prototype.tan = function() { + return divide(this.sin(), this.cos()); + }; + + Complex.prototype.atan = function(){ + if (equals(this, plusI) || + equals(this, minusI)) { + return neginf; + } + return multiply( + plusI, + multiply( + FloatPoint.makeInstance(0.5), + log(divide( + add(plusI, this), + add( + plusI, + subtract(0, this)))))); + }; + + Complex.prototype.cos = function(){ + if (this.isReal()) + return cos(this.r); + var iz = timesI(this); + var iz_negate = negate(iz); + + return halve(add(exp(iz), exp(iz_negate))); + }; + + Complex.prototype.sin = function(){ + if (this.isReal()) + return sin(this.r); + var iz = timesI(this); + var iz_negate = negate(iz); + var z2 = Complex.makeInstance(0, 2); + var exp_negate = subtract(exp(iz), exp(iz_negate)); + var result = divide(exp_negate, z2); + return result; + }; + + + Complex.prototype.expt = function(y){ + if (isExactInteger(y) && greaterThanOrEqual(y, 0)) { + return fastExpt(this, y); + } + var expo = multiply(y, this.log()); + return exp(expo); + }; + + Complex.prototype.exp = function(){ + var r = exp(this.r); + var cos_a = cos(this.i); + var sin_a = sin(this.i); + + return multiply( + r, + add(cos_a, timesI(sin_a))); + }; + + Complex.prototype.acos = function(){ + if (this.isReal()) + return acos(this.r); + var pi_half = halve(FloatPoint.pi); + var iz = timesI(this); + var root = sqrt(subtract(1, sqr(this))); + var l = timesI(log(add(iz, root))); + return add(pi_half, l); + }; + + Complex.prototype.asin = function(){ + if (this.isReal()) + return asin(this.r); + + var oneNegateThisSq = + subtract(1, sqr(this)); + var sqrtOneNegateThisSq = sqrt(oneNegateThisSq); + return multiply(2, atan(divide(this, + add(1, sqrtOneNegateThisSq)))); + }; + + Complex.prototype.ceiling = function(){ + if (!this.isReal()) + throwRuntimeError("ceiling: can only be applied to real number", this); + return ceiling(this.r); + }; + + Complex.prototype.floor = function(){ + if (!this.isReal()) + throwRuntimeError("floor: can only be applied to real number", this); + return floor(this.r); + }; + + Complex.prototype.imaginaryPart = function(){ + return this.i; + }; + + Complex.prototype.realPart = function(){ + return this.r; + }; + + Complex.prototype.round = function(){ + if (!this.isReal()) + throwRuntimeError("round: can only be applied to real number", this); + return round(this.r); + }; + + + + var rationalRegexp = new RegExp("^([+-]?\\d+)/(\\d+)$"); + var complexRegexp = new RegExp("^([+-]?[\\d\\w/\\.]*)([+-])([\\d\\w/\\.]*)i$"); + var digitRegexp = new RegExp("^[+-]?\\d+$"); + var flonumRegexp = new RegExp("^([+-]?\\d*)\\.(\\d*)$"); + var scientificPattern = new RegExp("^([+-]?\\d*\\.?\\d*)[Ee](\\+?\\d+)$"); + + // fromString: string -> (scheme-number | false) + var fromString = function(x) { + var aMatch = x.match(rationalRegexp); + if (aMatch) { + return Rational.makeInstance(fromString(aMatch[1]), + fromString(aMatch[2])); + } + + var cMatch = x.match(complexRegexp); + if (cMatch) { + return Complex.makeInstance(fromString(cMatch[1] || "0"), + fromString(cMatch[2] + (cMatch[3] || "1"))); + } + + // Floating point tests + if (x === '+nan.0' || x === '-nan.0') + return FloatPoint.nan; + if (x === '+inf.0') + return FloatPoint.inf; + if (x === '-inf.0') + return FloatPoint.neginf; + if (x === "-0.0") { + return NEGATIVE_ZERO; + } + if (x.match(flonumRegexp) || x.match(scientificPattern)) { + return FloatPoint.makeInstance(Number(x)); + } + + // Finally, integer tests. + if (x.match(digitRegexp)) { + var n = Number(x); + if (isOverflow(n)) { + return makeBignum(x); + } else { + return n; + } + } else { + return false; + } + }; + + + + + + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + + // The code below comes from Tom Wu's BigInteger implementation: + + // Copyright (c) 2005 Tom Wu + // All Rights Reserved. + // See "LICENSE" for details. + + // Basic JavaScript BN library - subset useful for RSA encryption. + + // Bits per digit + var dbits; + + // JavaScript engine analysis + var canary = 0xdeadbeefcafe; + var j_lm = ((canary&0xffffff)==0xefcafe); + + // (public) Constructor + function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); + } + + // return new, unset BigInteger + function nbi() { return new BigInteger(null); } + + // am: Compute w_j += (x*this_i), propagate carries, + // c is initial carry, returns final carry. + // c < 3*dvalue, x < 2*dvalue, this_i < dvalue + // We need to select the fastest one that works in this environment. + + // am1: use a single mult and divide to get the high bits, + // max digit bits should be 26 because + // max internal value = 2*dvalue^2-2*dvalue (< 2^53) + function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; + } + // am2 avoids a big mult-and-extract completely. + // Max digit bits should be <= 30 because we do bitwise ops + // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) + function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; + } + // Alternately, set max digit bits to 28 since some + // browsers slow down when dealing with 32-bit numbers. + function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; + } + if(j_lm && (typeof(navigator) !== 'undefined' && navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; + } + else if(j_lm && (typeof(navigator) !== 'undefined' && navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; + } + else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; + } + + BigInteger.prototype.DB = dbits; + BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; + } + + // (protected) set from integer value x, -DV <= x < DV + function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+DV; + else this.t = 0; + } + + // return bigint initialized to value + function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + + // (protected) set from string and radix + function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); + } + else + this[this.t-1] |= x<= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; + } + + // (public) return string representation in given radix + function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1< 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r.push(int2char(d)); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r.push(int2char(d)); + } + } + return m?r.join(""):"0"; + } + + // (public) -this + function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + + // (public) |this| + function bnAbs() { return (this.s<0)?this.negate():this; } + + // (public) return + if this > a, - if this < a, 0 if equal + function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + if ( this.s < 0 ) { + r = a.t - i; + } + else { + r = i - a.t; + } + if(r != 0) return r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; + } + + // returns bit length of the integer x + function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; + } + + // (public) return the number of bits in "this" + function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); + } + + // (protected) r = this << n*DB + function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; + } + + // (protected) r = this >> n*DB + function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; + } + + // (protected) r = this << n + function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); + } + + // (protected) r = this >> n + function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); + } + + // (protected) r = this * a, r != this,a (HAC 14.12) + // "this" should be the larger one if appropriate. + function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); + } + + // (protected) r = this^2, r != this (HAC 14.16) + function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); + } + + + // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) + // r != q, this != m. q or r may be null. + function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); + } + + // (public) this mod a + function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; + } + + // Modular reduction using "classic" algorithm + function Classic(m) { this.m = m; } + function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; + } + function cRevert(x) { return x; } + function cReduce(x) { x.divRemTo(this.m,null,x); } + function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + Classic.prototype.convert = cConvert; + Classic.prototype.revert = cRevert; + Classic.prototype.reduce = cReduce; + Classic.prototype.mulTo = cMulTo; + Classic.prototype.sqrTo = cSqrTo; + + // (protected) return "-1/this % 2^DB"; useful for Mont. reduction + // justification: + // xy == 1 (mod m) + // xy = 1+km + // xy(2-xy) = (1+km)(1-km) + // x[y(2-xy)] = 1-k^2m^2 + // x[y(2-xy)] == 1 (mod m^2) + // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 + // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. + // JS multiply "overflows" differently from C/C++, so care is needed here. + function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; + } + + // Montgomery reduction + function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; + } + + // xR mod m + function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; + } + + // x/R mod m + function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; + } + + // x = x/R mod m (HAC 14.32) + function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = "x^2/R mod m"; x != r + function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = "xy/R mod m"; x,y != r + function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Montgomery.prototype.convert = montConvert; + Montgomery.prototype.revert = montRevert; + Montgomery.prototype.reduce = montReduce; + Montgomery.prototype.mulTo = montMulTo; + Montgomery.prototype.sqrTo = montSqrTo; + + // (protected) true iff this is even + function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + + // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) + function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1< 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); + } + + // (public) this^e % m, 0 <= e < 2^32 + function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); + } + + // protected + BigInteger.prototype.copyTo = bnpCopyTo; + BigInteger.prototype.fromInt = bnpFromInt; + BigInteger.prototype.fromString = bnpFromString; + BigInteger.prototype.clamp = bnpClamp; + BigInteger.prototype.dlShiftTo = bnpDLShiftTo; + BigInteger.prototype.drShiftTo = bnpDRShiftTo; + BigInteger.prototype.lShiftTo = bnpLShiftTo; + BigInteger.prototype.rShiftTo = bnpRShiftTo; + BigInteger.prototype.subTo = bnpSubTo; + BigInteger.prototype.multiplyTo = bnpMultiplyTo; + BigInteger.prototype.squareTo = bnpSquareTo; + BigInteger.prototype.divRemTo = bnpDivRemTo; + BigInteger.prototype.invDigit = bnpInvDigit; + BigInteger.prototype.isEven = bnpIsEven; + BigInteger.prototype.exp = bnpExp; + + // public + BigInteger.prototype.toString = bnToString; + BigInteger.prototype.negate = bnNegate; + BigInteger.prototype.abs = bnAbs; + BigInteger.prototype.compareTo = bnCompareTo; + BigInteger.prototype.bitLength = bnBitLength; + BigInteger.prototype.mod = bnMod; + BigInteger.prototype.modPowInt = bnModPowInt; + + // "constants" + BigInteger.ZERO = nbv(0); + BigInteger.ONE = nbv(1); + + // Copyright (c) 2005-2009 Tom Wu + // All Rights Reserved. + // See "LICENSE" for details. + + // Extended JavaScript BN functions, required for RSA private ops. + + // Version 1.1: new BigInteger("0", 10) returns "proper" zero + + // (public) + function bnClone() { var r = nbi(); this.copyTo(r); return r; } + + // (public) return value as integer + function bnIntValue() { + if(this.s < 0) { + if(this.t == 1) return this[0]-this.DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this[1]&((1<<(32-this.DB))-1))<>24; } + + // (public) return value as short (assumes DB>=16) + function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } + + // (protected) return x s.t. r^x < DV + function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } + + // (public) 0 if this == 0, 1 if this > 0 + function bnSigNum() { + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; + } + + // (protected) convert to radix string + function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; + } + + // (protected) convert from radix string + function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); + } + + // (protected) alternate constructor + function bnpFromNumber(a,b,c) { + if("number" == typeof b) { + // new BigInteger(int,int,RNG) + if(a < 2) this.fromInt(1); + else { + this.fromNumber(a,c); + if(!this.testBit(a-1)) // force MSB set + this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); + if(this.isEven()) this.dAddOffset(1,0); // force odd + while(!this.isProbablePrime(b)) { + this.dAddOffset(2,0); + if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); + } + } + } + else { + // new BigInteger(int,RNG) + var x = [], t = a&7; + x.length = (a>>3)+1; + b.nextBytes(x); + if(t > 0) x[0] &= ((1< 0) { + if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) + r[k++] = d|(this.s<<(this.DB-p)); + while(i >= 0) { + if(p < 8) { + d = (this[i]&((1<>(p+=this.DB-8); + } + else { + d = (this[i]>>(p-=8))&0xff; + if(p <= 0) { p += this.DB; --i; } + } + if((d&0x80) != 0) d |= -256; + if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; + if(k > 0 || d != this.s) r[k++] = d; + } + } + return r; + } + + function bnEquals(a) { return(this.compareTo(a)==0); } + function bnMin(a) { return(this.compareTo(a)<0)?this:a; } + function bnMax(a) { return(this.compareTo(a)>0)?this:a; } + + // (protected) r = this op a (bitwise) + function bnpBitwiseTo(a,op,r) { + var i, f, m = Math.min(a.t,this.t); + for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); + if(a.t < this.t) { + f = a.s&this.DM; + for(i = m; i < this.t; ++i) r[i] = op(this[i],f); + r.t = this.t; + } + else { + f = this.s&this.DM; + for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); + r.t = a.t; + } + r.s = op(this.s,a.s); + r.clamp(); + } + + // (public) this & a + function op_and(x,y) { return x&y; } + function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } + + // (public) this | a + function op_or(x,y) { return x|y; } + function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } + + // (public) this ^ a + function op_xor(x,y) { return x^y; } + function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } + + // (public) this & ~a + function op_andnot(x,y) { return x&~y; } + function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } + + // (public) ~this + function bnNot() { + var r = nbi(); + for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; + r.t = this.t; + r.s = ~this.s; + return r; + } + + // (public) this << n + function bnShiftLeft(n) { + var r = nbi(); + if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); + return r; + } + + // (public) this >> n + function bnShiftRight(n) { + var r = nbi(); + if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); + return r; + } + + // return index of lowest 1-bit in x, x < 2^31 + function lbit(x) { + if(x == 0) return -1; + var r = 0; + if((x&0xffff) == 0) { x >>= 16; r += 16; } + if((x&0xff) == 0) { x >>= 8; r += 8; } + if((x&0xf) == 0) { x >>= 4; r += 4; } + if((x&3) == 0) { x >>= 2; r += 2; } + if((x&1) == 0) ++r; + return r; + } + + // (public) returns index of lowest 1-bit (or -1 if none) + function bnGetLowestSetBit() { + for(var i = 0; i < this.t; ++i) + if(this[i] != 0) return i*this.DB+lbit(this[i]); + if(this.s < 0) return this.t*this.DB; + return -1; + } + + // return number of 1 bits in x + function cbit(x) { + var r = 0; + while(x != 0) { x &= x-1; ++r; } + return r; + } + + // (public) return number of set bits + function bnBitCount() { + var r = 0, x = this.s&this.DM; + for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); + return r; + } + + // (public) true iff nth bit is set + function bnTestBit(n) { + var j = Math.floor(n/this.DB); + if(j >= this.t) return(this.s!=0); + return((this[j]&(1<<(n%this.DB)))!=0); + } + + // (protected) this op (1<>= this.DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r[i++] = c; + else if(c < -1) r[i++] = this.DV+c; + r.t = i; + r.clamp(); + } + + // (public) this + a + function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } + + // (public) this - a + function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } + + // (public) this * a + function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } + + // (public) this / a + function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } + + // (public) this % a + function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } + + // (public) [this/a,this%a] + function bnDivideAndRemainder(a) { + var q = nbi(), r = nbi(); + this.divRemTo(a,q,r); + return [q,r]; + } + + // (protected) this *= n, this >= 0, 1 < n < DV + function bnpDMultiply(n) { + this[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); + } + + // (protected) this += n << w words, this >= 0 + function bnpDAddOffset(n,w) { + if(n == 0) return; + while(this.t <= w) this[this.t++] = 0; + this[w] += n; + while(this[w] >= this.DV) { + this[w] -= this.DV; + if(++w >= this.t) this[this.t++] = 0; + ++this[w]; + } + } + + // A "null" reducer + function NullExp() {} + function nNop(x) { return x; } + function nMulTo(x,y,r) { x.multiplyTo(y,r); } + function nSqrTo(x,r) { x.squareTo(r); } + + NullExp.prototype.convert = nNop; + NullExp.prototype.revert = nNop; + NullExp.prototype.mulTo = nMulTo; + NullExp.prototype.sqrTo = nSqrTo; + + // (public) this^e + function bnPow(e) { return this.exp(e,new NullExp()); } + + // (protected) r = lower n words of "this * a", a.t <= n + // "this" should be the larger one if appropriate. + function bnpMultiplyLowerTo(a,n,r) { + var i = Math.min(this.t+a.t,n); + r.s = 0; // assumes a,this >= 0 + r.t = i; + while(i > 0) r[--i] = 0; + var j; + for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); + for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); + r.clamp(); + } + + // (protected) r = "this * a" without lower n words, n > 0 + // "this" should be the larger one if appropriate. + function bnpMultiplyUpperTo(a,n,r) { + --n; + var i = r.t = this.t+a.t-n; + r.s = 0; // assumes a,this >= 0 + while(--i >= 0) r[i] = 0; + for(i = Math.max(n-this.t,0); i < a.t; ++i) + r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); + r.clamp(); + r.drShiftTo(1,r); + } + + // Barrett modular reduction + function Barrett(m) { + // setup Barrett + this.r2 = nbi(); + this.q3 = nbi(); + BigInteger.ONE.dlShiftTo(2*m.t,this.r2); + this.mu = this.r2.divide(m); + this.m = m; + } + + function barrettConvert(x) { + if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); + else if(x.compareTo(this.m) < 0) return x; + else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } + } + + function barrettRevert(x) { return x; } + + // x = x mod m (HAC 14.42) + function barrettReduce(x) { + x.drShiftTo(this.m.t-1,this.r2); + if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } + this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); + this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); + while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); + x.subTo(this.r2,x); + while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + } + + // r = x^2 mod m; x != r + function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + + // r = x*y mod m; x,y != r + function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + + Barrett.prototype.convert = barrettConvert; + Barrett.prototype.revert = barrettRevert; + Barrett.prototype.reduce = barrettReduce; + Barrett.prototype.mulTo = barrettMulTo; + Barrett.prototype.sqrTo = barrettSqrTo; + + // (public) this^e % m (HAC 14.85) + function bnModPow(e,m) { + var i = e.bitLength(), k, r = nbv(1), z; + if(i <= 0) return r; + else if(i < 18) k = 1; + else if(i < 48) k = 3; + else if(i < 144) k = 4; + else if(i < 768) k = 5; + else k = 6; + if(i < 8) + z = new Classic(m); + else if(m.isEven()) + z = new Barrett(m); + else + z = new Montgomery(m); + + // precomputation + var g = [], n = 3, k1 = k-1, km = (1< 1) { + var g2 = nbi(); + z.sqrTo(g[1],g2); + while(n <= km) { + g[n] = nbi(); + z.mulTo(g2,g[n-2],g[n]); + n += 2; + } + } + + var j = e.t-1, w, is1 = true, r2 = nbi(), t; + i = nbits(e[j])-1; + while(j >= 0) { + if(i >= k1) w = (e[j]>>(i-k1))&km; + else { + w = (e[j]&((1<<(i+1))-1))<<(k1-i); + if(j > 0) w |= e[j-1]>>(this.DB+i-k1); + } + + n = k; + while((w&1) == 0) { w >>= 1; --n; } + if((i -= n) < 0) { i += this.DB; --j; } + if(is1) { // ret == 1, don't bother squaring or multiplying it + g[w].copyTo(r); + is1 = false; + } + else { + while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } + if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } + z.mulTo(r2,g[w],r); + } + + while(j >= 0 && (e[j]&(1< 0) { + x.rShiftTo(g,x); + y.rShiftTo(g,y); + } + while(x.signum() > 0) { + if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); + if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); + if(x.compareTo(y) >= 0) { + x.subTo(y,x); + x.rShiftTo(1,x); + } + else { + y.subTo(x,y); + y.rShiftTo(1,y); + } + } + if(g > 0) y.lShiftTo(g,y); + return y; + } + + // (protected) this % n, n < 2^26 + function bnpModInt(n) { + if(n <= 0) return 0; + var d = this.DV%n, r = (this.s<0)?n-1:0; + if(this.t > 0) + if(d == 0) r = this[0]%n; + else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; + return r; + } + + // (public) 1/this % m (HAC 14.61) + function bnModInverse(m) { + var ac = m.isEven(); + if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; + var u = m.clone(), v = this.clone(); + var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); + while(u.signum() != 0) { + while(u.isEven()) { + u.rShiftTo(1,u); + if(ac) { + if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } + a.rShiftTo(1,a); + } + else if(!b.isEven()) b.subTo(m,b); + b.rShiftTo(1,b); + } + while(v.isEven()) { + v.rShiftTo(1,v); + if(ac) { + if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } + c.rShiftTo(1,c); + } + else if(!d.isEven()) d.subTo(m,d); + d.rShiftTo(1,d); + } + if(u.compareTo(v) >= 0) { + u.subTo(v,u); + if(ac) a.subTo(c,a); + b.subTo(d,b); + } + else { + v.subTo(u,v); + if(ac) c.subTo(a,c); + d.subTo(b,d); + } + } + if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; + if(d.compareTo(m) >= 0) return d.subtract(m); + if(d.signum() < 0) d.addTo(m,d); else return d; + if(d.signum() < 0) return d.add(m); else return d; + } + + var lowprimes = [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,503,509]; + var lplim = (1<<26)/lowprimes[lowprimes.length-1]; + + // (public) test primality with certainty >= 1-.5^t + function bnIsProbablePrime(t) { + var i, x = this.abs(); + if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { + for(i = 0; i < lowprimes.length; ++i) + if(x[0] == lowprimes[i]) return true; + return false; + } + if(x.isEven()) return false; + i = 1; + while(i < lowprimes.length) { + var m = lowprimes[i], j = i+1; + while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; + m = x.modInt(m); + while(i < j) if(m%lowprimes[i++] == 0) return false; + } + return x.millerRabin(t); + } + + // (protected) true if probably prime (HAC 4.24, Miller-Rabin) + function bnpMillerRabin(t) { + var n1 = this.subtract(BigInteger.ONE); + var k = n1.getLowestSetBit(); + if(k <= 0) return false; + var r = n1.shiftRight(k); + t = (t+1)>>1; + if(t > lowprimes.length) t = lowprimes.length; + var a = nbi(); + for(var i = 0; i < t; ++i) { + a.fromInt(lowprimes[i]); + var y = a.modPow(r,this); + if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { + var j = 1; + while(j++ < k && y.compareTo(n1) != 0) { + y = y.modPowInt(2,this); + if(y.compareTo(BigInteger.ONE) == 0) return false; + } + if(y.compareTo(n1) != 0) return false; + } + } + return true; + } + + + + // protected + BigInteger.prototype.chunkSize = bnpChunkSize; + BigInteger.prototype.toRadix = bnpToRadix; + BigInteger.prototype.fromRadix = bnpFromRadix; + BigInteger.prototype.fromNumber = bnpFromNumber; + BigInteger.prototype.bitwiseTo = bnpBitwiseTo; + BigInteger.prototype.changeBit = bnpChangeBit; + BigInteger.prototype.addTo = bnpAddTo; + BigInteger.prototype.dMultiply = bnpDMultiply; + BigInteger.prototype.dAddOffset = bnpDAddOffset; + BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; + BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; + BigInteger.prototype.modInt = bnpModInt; + BigInteger.prototype.millerRabin = bnpMillerRabin; + + // public + BigInteger.prototype.clone = bnClone; + BigInteger.prototype.intValue = bnIntValue; + BigInteger.prototype.byteValue = bnByteValue; + BigInteger.prototype.shortValue = bnShortValue; + BigInteger.prototype.signum = bnSigNum; + BigInteger.prototype.toByteArray = bnToByteArray; + BigInteger.prototype.equals = bnEquals; + BigInteger.prototype.min = bnMin; + BigInteger.prototype.max = bnMax; + BigInteger.prototype.and = bnAnd; + BigInteger.prototype.or = bnOr; + BigInteger.prototype.xor = bnXor; + BigInteger.prototype.andNot = bnAndNot; + BigInteger.prototype.not = bnNot; + BigInteger.prototype.shiftLeft = bnShiftLeft; + BigInteger.prototype.shiftRight = bnShiftRight; + BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; + BigInteger.prototype.bitCount = bnBitCount; + BigInteger.prototype.testBit = bnTestBit; + BigInteger.prototype.setBit = bnSetBit; + BigInteger.prototype.clearBit = bnClearBit; + BigInteger.prototype.flipBit = bnFlipBit; + BigInteger.prototype.add = bnAdd; + BigInteger.prototype.subtract = bnSubtract; + BigInteger.prototype.multiply = bnMultiply; + BigInteger.prototype.divide = bnDivide; + BigInteger.prototype.remainder = bnRemainder; + BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; + BigInteger.prototype.modPow = bnModPow; + BigInteger.prototype.modInverse = bnModInverse; + BigInteger.prototype.pow = bnPow; + BigInteger.prototype.gcd = bnGCD; + BigInteger.prototype.isProbablePrime = bnIsProbablePrime; + + // BigInteger interfaces not implemented in jsbn: + + // BigInteger(int signum, byte[] magnitude) + // double doubleValue() + // float floatValue() + // int hashCode() + // long longValue() + // static BigInteger valueOf(long val) + + + + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + // END OF copy-and-paste of jsbn. + + + + BigInteger.NEGATIVE_ONE = BigInteger.ONE.negate(); + + + // Other methods we need to add for compatibilty with js-numbers numeric tower. + + // add is implemented above. + // subtract is implemented above. + // multiply is implemented above. + // equals is implemented above. + // abs is implemented above. + // negate is defined above. + + // makeBignum: string -> BigInteger + var makeBignum = function(s) { + if (typeof(s) === 'number') { s = s + ''; } + s = expandExponent(s); + return new BigInteger(s, 10); + }; + + var zerostring = function(n) { + var buf = []; + for (var i = 0; i < n; i++) { + buf.push('0'); + } + return buf.join(''); + }; + + + BigInteger.prototype.level = 0; + BigInteger.prototype.liftTo = function(target) { + if (target.level === 1) { + return new Rational(this, 1); + } + if (target.level === 2) { + var fixrep = this.toFixnum(); + if (fixrep === Number.POSITIVE_INFINITY) + return TOO_POSITIVE_TO_REPRESENT; + if (fixrep === Number.NEGATIVE_INFINITY) + return TOO_NEGATIVE_TO_REPRESENT; + return new FloatPoint(fixrep); + } + if (target.level === 3) { + return new Complex(this, 0); + } + return throwRuntimeError("invalid level for BigInteger lift", this, target); + }; + + BigInteger.prototype.isFinite = function() { + return true; + }; + + BigInteger.prototype.isInteger = function() { + return true; + }; + + BigInteger.prototype.isRational = function() { + return true; + }; + + BigInteger.prototype.isReal = function() { + return true; + }; + + BigInteger.prototype.isExact = function() { + return true; + }; + + BigInteger.prototype.isInexact = function() { + return false; + }; + + BigInteger.prototype.toExact = function() { + return this; + }; + + BigInteger.prototype.toInexact = function() { + return FloatPoint.makeInstance(this.toFixnum()); + }; + + BigInteger.prototype.toFixnum = function() { + var result = 0, str = this.toString(), i; + if (str[0] === '-') { + for (i=1; i < str.length; i++) { + result = result * 10 + Number(str[i]); + } + return -result; + } else { + for (i=0; i < str.length; i++) { + result = result * 10 + Number(str[i]); + } + return result; + } + }; + + + BigInteger.prototype.greaterThan = function(other) { + return this.compareTo(other) > 0; + }; + + BigInteger.prototype.greaterThanOrEqual = function(other) { + return this.compareTo(other) >= 0; + }; + + BigInteger.prototype.lessThan = function(other) { + return this.compareTo(other) < 0; + }; + + BigInteger.prototype.lessThanOrEqual = function(other) { + return this.compareTo(other) <= 0; + }; + + // divide: scheme-number -> scheme-number + // WARNING NOTE: we override the old version of divide. + BigInteger.prototype.divide = function(other) { + var quotientAndRemainder = bnDivideAndRemainder.call(this, other); + if (quotientAndRemainder[1].compareTo(BigInteger.ZERO) === 0) { + return quotientAndRemainder[0]; + } else { + var result = add(quotientAndRemainder[0], + Rational.makeInstance(quotientAndRemainder[1], other)); + return result; + } + }; + + BigInteger.prototype.numerator = function() { + return this; + }; + + BigInteger.prototype.denominator = function() { + return 1; + }; + + + (function() { + // Classic implementation of Newton-Ralphson square-root search, + // adapted for integer-sqrt. + // http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number + var searchIter = function(n, guess) { + while(!(lessThanOrEqual(sqr(guess),n) && + lessThan(n,sqr(add(guess, 1))))) { + guess = floor(divide(add(guess, + floor(divide(n, guess))), + 2)); + } + return guess; + }; + + // integerSqrt: -> scheme-number + BigInteger.prototype.integerSqrt = function() { + var n; + if(sign(this) >= 0) { + return searchIter(this, this); + } else { + n = this.negate(); + return Complex.makeInstance(0, searchIter(n, n)); + } + }; + })(); + + + (function() { + // Get an approximation using integerSqrt, and then start another + // Newton-Ralphson search if necessary. + BigInteger.prototype.sqrt = function() { + var approx = this.integerSqrt(), fix; + if (eqv(sqr(approx), this)) { + return approx; + } + fix = toFixnum(this); + if (isFinite(fix)) { + if (fix >= 0) { + return FloatPoint.makeInstance(Math.sqrt(fix)); + } else { + return Complex.makeInstance( + 0, + FloatPoint.makeInstance(Math.sqrt(-fix))); + } + } else { + return approx; + } + }; + })(); + + + + + + // sqrt: -> scheme-number + // http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number + // Produce the square root. + + // floor: -> scheme-number + // Produce the floor. + BigInteger.prototype.floor = function() { + return this; + } + + // ceiling: -> scheme-number + // Produce the ceiling. + BigInteger.prototype.ceiling = function() { + return this; + } + + // conjugate: -> scheme-number + // Produce the conjugate. + + // magnitude: -> scheme-number + // Produce the magnitude. + + // log: -> scheme-number + // Produce the log. + + // angle: -> scheme-number + // Produce the angle. + + // atan: -> scheme-number + // Produce the arc tangent. + + // cos: -> scheme-number + // Produce the cosine. + + // sin: -> scheme-number + // Produce the sine. + + + // expt: scheme-number -> scheme-number + // Produce the power to the input. + BigInteger.prototype.expt = function(n) { + return bnPow.call(this, n); + }; + + + + // exp: -> scheme-number + // Produce e raised to the given power. + + // acos: -> scheme-number + // Produce the arc cosine. + + // asin: -> scheme-number + // Produce the arc sine. + + BigInteger.prototype.imaginaryPart = function() { + return 0; + } + BigInteger.prototype.realPart = function() { + return this; + } + + // round: -> scheme-number + // Round to the nearest integer. + + + + + + ////////////////////////////////////////////////////////////////////// + // toRepeatingDecimal: jsnum jsnum {limit: number}? -> [string, string, string] + // + // Given the numerator and denominator parts of a rational, + // produces the repeating-decimal representation, where the first + // part are the digits before the decimal, the second are the + // non-repeating digits after the decimal, and the third are the + // remaining repeating decimals. + // + // An optional limit on the decimal expansion can be provided, in which + // case the search cuts off if we go past the limit. + // If this happens, the third argument returned becomes '...' to indicate + // that the search was prematurely cut off. + var toRepeatingDecimal = (function() { + var getResidue = function(r, d, limit) { + var digits = []; + var seenRemainders = {}; + seenRemainders[r] = true; + while(true) { + if (limit-- <= 0) { + return [digits.join(''), '...'] + } + + var nextDigit = quotient( + multiply(r, 10), d); + var nextRemainder = remainder( + multiply(r, 10), + d); + digits.push(nextDigit.toString()); + if (seenRemainders[nextRemainder]) { + r = nextRemainder; + break; + } else { + seenRemainders[nextRemainder] = true; + r = nextRemainder; + } + } + + var firstRepeatingRemainder = r; + var repeatingDigits = []; + while (true) { + var nextDigit = quotient(multiply(r, 10), d); + var nextRemainder = remainder( + multiply(r, 10), + d); + repeatingDigits.push(nextDigit.toString()); + if (equals(nextRemainder, firstRepeatingRemainder)) { + break; + } else { + r = nextRemainder; + } + }; + + var digitString = digits.join(''); + var repeatingDigitString = repeatingDigits.join(''); + + while (digitString.length >= repeatingDigitString.length && + (digitString.substring( + digitString.length - repeatingDigitString.length) + === repeatingDigitString)) { + digitString = digitString.substring( + 0, digitString.length - repeatingDigitString.length); + } + + return [digitString, repeatingDigitString]; + + }; + + return function(n, d, options) { + // default limit on decimal expansion; can be overridden + var limit = 512; + if (options && typeof(options.limit) !== 'undefined') { + limit = options.limit; + } + if (! isInteger(n)) { + throwRuntimeError('toRepeatingDecimal: n ' + n.toString() + + " is not an integer."); + } + if (! isInteger(d)) { + throwRuntimeError('toRepeatingDecimal: d ' + d.toString() + + " is not an integer."); + } + if (equals(d, 0)) { + throwRuntimeError('toRepeatingDecimal: d equals 0'); + } + if (lessThan(d, 0)) { + throwRuntimeError('toRepeatingDecimal: d < 0'); + } + var sign = (lessThan(n, 0) ? "-" : ""); + n = abs(n); + var beforeDecimalPoint = sign + quotient(n, d); + var afterDecimals = getResidue(remainder(n, d), d, limit); + return [beforeDecimalPoint].concat(afterDecimals); + }; + })(); + ////////////////////////////////////////////////////////////////////// + + + + + // External interface of js-numbers: + + Numbers['fromFixnum'] = fromFixnum; + Numbers['fromString'] = fromString; + Numbers['makeBignum'] = makeBignum; + Numbers['makeRational'] = Rational.makeInstance; + Numbers['makeFloat'] = FloatPoint.makeInstance; + Numbers['makeComplex'] = Complex.makeInstance; + Numbers['makeComplexPolar'] = makeComplexPolar; + + Numbers['pi'] = FloatPoint.pi; + Numbers['e'] = FloatPoint.e; + Numbers['nan'] = FloatPoint.nan; + Numbers['negative_inf'] = FloatPoint.neginf; + Numbers['inf'] = FloatPoint.inf; + Numbers['negative_one'] = -1; // Rational.NEGATIVE_ONE; + Numbers['zero'] = 0; // Rational.ZERO; + Numbers['one'] = 1; // Rational.ONE; + Numbers['i'] = plusI; + Numbers['negative_i'] = minusI; + Numbers['negative_zero'] = NEGATIVE_ZERO; + + Numbers['onThrowRuntimeError'] = onThrowRuntimeError; + Numbers['isSchemeNumber'] = isSchemeNumber; + Numbers['isRational'] = isRational; + Numbers['isReal'] = isReal; + Numbers['isExact'] = isExact; + Numbers['isInexact'] = isInexact; + Numbers['isInteger'] = isInteger; + + Numbers['toFixnum'] = toFixnum; + Numbers['toExact'] = toExact; + Numbers['toInexact'] = toInexact; + Numbers['add'] = add; + Numbers['subtract'] = subtract; + Numbers['multiply'] = multiply; + Numbers['divide'] = divide; + Numbers['equals'] = equals; + Numbers['eqv'] = eqv; + Numbers['approxEquals'] = approxEquals; + Numbers['greaterThanOrEqual'] = greaterThanOrEqual; + Numbers['lessThanOrEqual'] = lessThanOrEqual; + Numbers['greaterThan'] = greaterThan; + Numbers['lessThan'] = lessThan; + Numbers['expt'] = expt; + Numbers['exp'] = exp; + Numbers['modulo'] = modulo; + Numbers['numerator'] = numerator; + Numbers['denominator'] = denominator; + Numbers['integerSqrt'] = integerSqrt; + Numbers['sqrt'] = sqrt; + Numbers['abs'] = abs; + Numbers['quotient'] = quotient; + Numbers['remainder'] = remainder; + Numbers['floor'] = floor; + Numbers['ceiling'] = ceiling; + Numbers['conjugate'] = conjugate; + Numbers['magnitude'] = magnitude; + Numbers['log'] = log; + Numbers['angle'] = angle; + Numbers['tan'] = tan; + Numbers['atan'] = atan; + Numbers['cos'] = cos; + Numbers['sin'] = sin; + Numbers['tan'] = tan; + Numbers['acos'] = acos; + Numbers['asin'] = asin; + Numbers['cosh'] = cosh; + Numbers['sinh'] = sinh; + Numbers['imaginaryPart'] = imaginaryPart; + Numbers['realPart'] = realPart; + Numbers['round'] = round; + Numbers['sqr'] = sqr; + Numbers['gcd'] = gcd; + Numbers['lcm'] = lcm; + + Numbers['toRepeatingDecimal'] = toRepeatingDecimal; + + + + // The following exposes the class representations for easier + // integration with other projects. + Numbers['BigInteger'] = BigInteger; + Numbers['Rational'] = Rational; + Numbers['FloatPoint'] = FloatPoint; + Numbers['Complex'] = Complex; + + Numbers['MIN_FIXNUM'] = MIN_FIXNUM; + Numbers['MAX_FIXNUM'] = MAX_FIXNUM; + +})(); diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index e7798da..6eee7a6 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -843,6 +843,8 @@ return checkedAddSlowPath(M, Array.prototype.slice.call(arguments, 1)); } return sum; + } else { + return plt.baselib.numbers.add(x, y); } } // Secondary path: if everything is a fixnum... @@ -900,9 +902,12 @@ }; var checkedMulSlowPath = function(M, args) { - var i; - var prod = 1; - for (i = 0; i < args.length; i++) { + var i, prod; + if (! isNumber(args[0])) { + raiseArgumentTypeError(M, '*', 'number', 0, args[0]); + } + var prod = args[0]; + for (i = 1; i < args.length; i++) { if (! isNumber(args[i])) { raiseArgumentTypeError(M, '*', 'number', i, args[i]); }