[macruby-changes] [4202] MacRuby/trunk/ext/bigdecimal/lib/bigdecimal/math.rb

source_changes at macosforge.org source_changes at macosforge.org
Fri Jun 4 11:59:10 PDT 2010


Revision: 4202
          http://trac.macosforge.org/projects/ruby/changeset/4202
Author:   martinlagardette at apple.com
Date:     2010-06-04 11:59:07 -0700 (Fri, 04 Jun 2010)
Log Message:
-----------
Update bigdecimal/math

Modified Paths:
--------------
    MacRuby/trunk/ext/bigdecimal/lib/bigdecimal/math.rb

Modified: MacRuby/trunk/ext/bigdecimal/lib/bigdecimal/math.rb
===================================================================
--- MacRuby/trunk/ext/bigdecimal/lib/bigdecimal/math.rb	2010-06-04 00:15:57 UTC (rev 4201)
+++ MacRuby/trunk/ext/bigdecimal/lib/bigdecimal/math.rb	2010-06-04 18:59:07 UTC (rev 4202)
@@ -1,3 +1,5 @@
+require 'bigdecimal'
+
 #
 #--
 # Contents:
@@ -29,11 +31,12 @@
 #   puts sin(a,100) # -> 0.10000000000000000000......E1
 #
 module BigMath
+  module_function
 
-  # Computes the square root of x to the specified number of digits of 
+  # Computes the square root of x to the specified number of digits of
   # precision.
   #
-  # BigDecimal.new('2').sqrt(16).to_s 
+  # BigDecimal.new('2').sqrt(16).to_s
   #  -> "0.14142135623730950488016887242096975E1"
   #
   def sqrt(x,prec)
@@ -49,6 +52,14 @@
     n    = prec + BigDecimal.double_fig
     one  = BigDecimal("1")
     two  = BigDecimal("2")
+    x = -x if neg = x < 0
+    if x > (twopi = two * BigMath.PI(prec))
+      if x > 30
+        x %= twopi
+      else
+        x -= twopi while x > twopi
+      end
+    end
     x1   = x
     x2   = x.mult(x,n)
     sign = 1
@@ -65,7 +76,7 @@
       d   = sign * x1.div(z,m)
       y  += d
     end
-    y
+    neg ? -y : y
   end
 
   # Computes the cosine of x to the specified number of digits of precision.
@@ -77,6 +88,14 @@
     n    = prec + BigDecimal.double_fig
     one  = BigDecimal("1")
     two  = BigDecimal("2")
+    x = -x if x < 0
+    if x > (twopi = two * BigMath.PI(prec))
+      if x > 30
+        x %= twopi
+      else
+        x -= twopi while x > twopi
+      end
+    end
     x1 = one
     x2 = x.mult(x,n)
     sign = 1
@@ -98,12 +117,16 @@
 
   # Computes the arctangent of x to the specified number of digits of precision.
   #
-  # If x is infinite or NaN, returns NaN.
-  # Raises an argument error if x > 1.
+  # If x is NaN, returns NaN.
   def atan(x, prec)
     raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
-    return BigDecimal("NaN") if x.infinite? || x.nan?
-    raise ArgumentError, "x.abs must be less than 1.0" if x.abs>=1
+    return BigDecimal("NaN") if x.nan?
+    pi = PI(prec)
+    x = -x if neg = x < 0
+    return pi.div(neg ? -2 : 2, prec) if x.infinite?
+    return pi / (neg ? -4 : 4) if x.round(prec) == 1
+    x = BigDecimal("1").div(x, prec) if inv = x > 1
+    x = (-1 + sqrt(1 + x**2, prec))/x if dbl = x > 0.5
     n    = prec + BigDecimal.double_fig
     y = x
     d = y
@@ -117,10 +140,13 @@
       y += d
       r += 2
     end
+    y *= 2 if dbl
+    y = pi / 2 - y if inv
+    y = -y if neg
     y
   end
 
-  # Computes the value of e (the base of natural logarithms) raised to the 
+  # Computes the value of e (the base of natural logarithms) raised to the
   # power of x, to the specified number of digits of precision.
   #
   # If x is infinite or NaN, returns NaN.
@@ -132,6 +158,7 @@
     return BigDecimal("NaN") if x.infinite? || x.nan?
     n    = prec + BigDecimal.double_fig
     one  = BigDecimal("1")
+    x = -x if neg = x < 0
     x1 = one
     y  = one
     d  = y
@@ -145,10 +172,14 @@
       d  = x1.div(z,m)
       y += d
     end
-    y
+    if neg
+      one.div(y, prec)
+    else
+      y.round(prec - y.exponent)
+    end
   end
 
-  # Computes the natural logarithm of x to the specified number of digits 
+  # Computes the natural logarithm of x to the specified number of digits
   # of precision.
   #
   # Returns x if x is infinite or NaN.
@@ -159,6 +190,11 @@
     one = BigDecimal("1")
     two = BigDecimal("2")
     n  = prec + BigDecimal.double_fig
+    if (expo = x.exponent) < 0 || expo >= 3
+      x = x.mult(BigDecimal("1E#{-expo}"), n)
+    else
+      expo = nil
+    end
     x  = (x - one).div(x + one,n)
     x2 = x.mult(x,n)
     y  = x
@@ -171,7 +207,11 @@
       d  = x.div(i,m)
       y += d
     end
-    y*two
+    y *= two
+    if expo
+      y += log(BigDecimal("10"),prec) * BigDecimal(expo.to_s)
+    end
+    y
   end
 
   # Computes the value of pi to the specified number of digits of precision.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100604/135cbc18/attachment.html>


More information about the macruby-changes mailing list