@@ -813,6 +813,8 @@ define("pyret-base/js/js-numbers", function() {
813813 // NB: all of these trig-gy generic functions should now return roughnum rather than float
814814 // (except for an arg of 0, etc)
815815
816+ var ln10 = Math . log ( 10 )
817+
816818 // log: pyretnum -> pyretnum
817819 var log = function ( n , errbacks ) {
818820 if ( eqv ( n , 1 , errbacks ) ) {
@@ -824,7 +826,35 @@ define("pyret-base/js/js-numbers", function() {
824826 if ( typeof ( n ) === 'number' ) {
825827 return Roughnum . makeInstance ( Math . log ( n ) , errbacks ) ;
826828 }
827- return n . log ( errbacks ) ;
829+ var nFix = n . toFixnum ( ) ;
830+ if ( typeof ( nFix ) === 'number' && nFix !== Infinity ) {
831+ return Roughnum . makeInstance ( Math . log ( nFix ) , errbacks ) ;
832+ }
833+ // at this point, n must be a very large positive number;
834+ // n > 1e308, i.e, has at least 308 digits;
835+ // we can safely ignore its fractional part;
836+ var nStr = n . round ( errbacks ) . toString ( ) ;
837+ var nLen = nStr . length ;
838+ // we furthermore need only the integer part's first few digits
839+ // although we must remember the number of digits ignored;
840+ var firstFewLen = 308 ; // has to be <= 308
841+ // say integer N = yyy...yyyxxx...xxx
842+ // where the number of x's is nx;
843+ // So N ~= yyy...yyy * 10^nx
844+ // We'll first find the common (base 10) log of N
845+ // log10(N) ~= log10(yyy...yyy * 10^nx)
846+ // = log10(yyy...yyy) + nx
847+ // Now to convert this to the natural log
848+ // ln(N) = log10(N) / log10(e)
849+ // = log10(N) * ln(10)
850+ // ~= [log10(yyy...yyy) + nx] * ln(10)
851+ // = log10(yyy...yyy) * ln(10) + nx * ln(10)
852+ // = ln(yyy...yyy) + nx * ln(10)
853+ // JS gives us ln(yyy...yyy) and ln(10) so we have a good
854+ // approximation for ln(N)
855+ var nFirstFew = parseInt ( nStr . substring ( 0 , firstFewLen ) ) ;
856+ var nLog = Math . log ( nFirstFew ) + ( nLen - firstFewLen ) * ln10 ;
857+ return Roughnum . makeInstance ( nLog , errbacks ) ;
828858 } ;
829859
830860 // tan: pyretnum -> pyretnum
@@ -2889,8 +2919,13 @@ define("pyret-base/js/js-numbers", function() {
28892919 function bnpIsEven ( ) { return ( ( this . t > 0 ) ?( this [ 0 ] & 1 ) :this . s ) == 0 ; }
28902920
28912921 // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
2892- function bnpExp ( e , z ) {
2893- if ( e > 0xffffffff || e < 1 ) return BigInteger . ONE ;
2922+ function bnpExp ( e , z , errbacks ) {
2923+ if ( greaterThan ( e , 0xffffffff , errbacks ) ) {
2924+ errbacks . throwDomainError ( 'expt: exponent ' + e + ' too large' ) ;
2925+ }
2926+ if ( lessThan ( e , 1 , errbacks ) ) {
2927+ return BigInteger . ONE ;
2928+ }
28942929 var r = nbi ( ) , r2 = nbi ( ) , g = z . convert ( this ) , i = nbits ( e ) - 1 ;
28952930 g . copyTo ( r ) ;
28962931 while ( -- i >= 0 ) {
@@ -2902,10 +2937,10 @@ define("pyret-base/js/js-numbers", function() {
29022937 }
29032938
29042939 // (public) this^e % m, 0 <= e < 2^32
2905- function bnModPowInt ( e , m ) {
2940+ function bnModPowInt ( e , m , errbacks ) {
29062941 var z ;
29072942 if ( e < 256 || m . isEven ( ) ) z = new Classic ( m ) ; else z = new Montgomery ( m ) ;
2908- return this . bnpExp ( e , z ) ;
2943+ return this . bnpExp ( e , z , errbacks ) ;
29092944 }
29102945
29112946 // protected
@@ -3274,7 +3309,9 @@ define("pyret-base/js/js-numbers", function() {
32743309 NullExp . prototype . sqrTo = nSqrTo ;
32753310
32763311 // (public) this^e
3277- function bnPow ( e ) { return this . bnpExp ( e , new NullExp ( ) ) ; }
3312+ function bnPow ( e , errbacks ) {
3313+ return this . bnpExp ( e , new NullExp ( ) , errbacks ) ;
3314+ }
32783315
32793316 // (protected) r = lower n words of "this * a", a.t <= n
32803317 // "this" should be the larger one if appropriate.
@@ -3774,48 +3811,48 @@ define("pyret-base/js/js-numbers", function() {
37743811
37753812 // round: -> pyretnum
37763813 // Round to the nearest integer.
3777- BigInteger . prototype . round = function ( n , errbacks ) {
3814+ BigInteger . prototype . round = function ( errbacks ) {
37783815 return this ;
37793816 } ;
37803817
3781- BigInteger . prototype . roundEven = function ( n , errbacks ) {
3818+ BigInteger . prototype . roundEven = function ( errbacks ) {
37823819 return this ;
37833820 } ;
37843821
37853822 // log: -> pyretnum
37863823 // Produce the log.
3787- BigInteger . prototype . log = function ( n , errbacks ) {
3824+ BigInteger . prototype . log = function ( errbacks ) {
37883825 return log ( this . toFixnum ( ) , errbacks ) ;
37893826 } ;
37903827
37913828 // tan: -> pyretnum
37923829 // Produce the tan.
3793- BigInteger . prototype . tan = function ( n , errbacks ) {
3830+ BigInteger . prototype . tan = function ( errbacks ) {
37943831 return tan ( this . toFixnum ( ) , errbacks ) ;
37953832 } ;
37963833
37973834 // atan: -> pyretnum
37983835 // Produce the arc tangent.
3799- BigInteger . prototype . atan = function ( n , errbacks ) {
3836+ BigInteger . prototype . atan = function ( errbacks ) {
38003837 return atan ( this . toFixnum ( ) , errbacks ) ;
38013838 } ;
38023839
38033840 // cos: -> pyretnum
38043841 // Produce the cosine.
3805- BigInteger . prototype . cos = function ( n , errbacks ) {
3842+ BigInteger . prototype . cos = function ( errbacks ) {
38063843 return cos ( this . toFixnum ( ) , errbacks ) ;
38073844 } ;
38083845
38093846 // sin: -> pyretnum
38103847 // Produce the sine.
3811- BigInteger . prototype . sin = function ( n , errbacks ) {
3848+ BigInteger . prototype . sin = function ( errbacks ) {
38123849 return sin ( this . toFixnum ( ) , errbacks ) ;
38133850 } ;
38143851
38153852 // expt: pyretnum -> pyretnum
38163853 // Produce the power to the input.
38173854 BigInteger . prototype . expt = function ( n , errbacks ) {
3818- return bnPow . call ( this , n ) ;
3855+ return bnPow . call ( this , n , errbacks ) ;
38193856 } ;
38203857
38213858 // exp: -> pyretnum
@@ -3829,13 +3866,13 @@ define("pyret-base/js/js-numbers", function() {
38293866
38303867 // acos: -> pyretnum
38313868 // Produce the arc cosine.
3832- BigInteger . prototype . acos = function ( n , errbacks ) {
3869+ BigInteger . prototype . acos = function ( errbacks ) {
38333870 return acos ( this . toFixnum ( ) , errbacks ) ;
38343871 } ;
38353872
38363873 // asin: -> pyretnum
38373874 // Produce the arc sine.
3838- BigInteger . prototype . asin = function ( n , errbacks ) {
3875+ BigInteger . prototype . asin = function ( errbacks ) {
38393876 return asin ( this . toFixnum ( ) , errbacks ) ;
38403877 } ;
38413878
0 commit comments