From 1e97118d8faf46ae5db00d69bfe3673de5fcc120 Mon Sep 17 00:00:00 2001 From: shigek Date: Thu, 14 Aug 2003 15:34:17 +0000 Subject: Newly added. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4388 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/bigdecimal/lib/bigdecimal/math.rb | 147 ++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 ext/bigdecimal/lib/bigdecimal/math.rb (limited to 'ext/bigdecimal') diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb new file mode 100644 index 0000000000..7921e7cc50 --- /dev/null +++ b/ext/bigdecimal/lib/bigdecimal/math.rb @@ -0,0 +1,147 @@ +# +# Contents: +# sin(x, prec) +# cos(x, prec) +# exp(x, prec) +# log(x, prec) +# PI (prec) +# +# where: +# x ... BigDecimal number to be computed. +# prec ... Number of digits to be obtained. +# +module BigMath + def sin(x, prec) + raise ArgumentError, "Zero or negative precision for sin" if prec <= 0 + return BigDecimal("NaN") if x.infinite? || x.nan? + n = prec + BigDecimal.double_fig + n2 = n+n + one = BigDecimal("1") + two = BigDecimal("2") + x1 = x + x2 = x * x + sign = 1 + y = x + d = y + i = one + z = one + while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) + m = BigDecimal.double_fig if m < BigDecimal.double_fig + sign = -sign + x1 = x2.mult(x1,n2) + i += two + z *= (i-one) * i + d = sign * x1.div(z,m) + y += d + end + y + end + + def cos(x, prec) + raise ArgumentError, "Zero or negative precision for sin" if prec <= 0 + return BigDecimal("NaN") if x.infinite? || x.nan? + n = prec + BigDecimal.double_fig + n2 = n+n + one = BigDecimal("1") + two = BigDecimal("2") + x1 = one + x2 = x * x + sign = 1 + y = one + d = y + i = BigDecimal("0") + z = one + while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) + m = BigDecimal.double_fig if m < BigDecimal.double_fig + sign = -sign + x1 = x2.mult(x1,n2) + i += two + z *= (i-one) * i + d = sign * x1.div(z,m) + y += d + end + y + end + + def exp(x, prec) + raise ArgumentError, "Zero or negative precision for sin" if prec <= 0 + return BigDecimal("NaN") if x.infinite? || x.nan? + n = prec + BigDecimal.double_fig + n2 = n+n + one = BigDecimal("1") + x1 = one + y = one + d = y + z = one + i = 0 + while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) + m = BigDecimal.double_fig if m < BigDecimal.double_fig + x1 = x1.mult(x,n2) + i += 1 + z *= i + d = x1.div(z,m) + y += d + end + y + end + + def log(x, prec) + raise ArgumentError, "Zero or negative argument for log" if x <= 0 || prec <= 0 + return x if x.infinite? || x.nan? + one = BigDecimal("1") + two = BigDecimal("2") + n = prec + BigDecimal.double_fig + n2 = n + n + x = (x - one).div(x + one,n) + x2 = x * x + y = two * x + d = y + i = one + while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) + m = BigDecimal.double_fig if m < BigDecimal.double_fig + x = x2.mult(x,n2) + i += two + d = (two * x).div(i,m) + y += d + end + y + end + + def PI(prec) + raise ArgumentError, "Zero or negative argument for PI" if prec <= 0 + n = prec + BigDecimal.double_fig + zero = BigDecimal("0") + one = BigDecimal("1") + two = BigDecimal("2") + + m25 = BigDecimal("-0.04") + m57121 = BigDecimal("-57121") + + pi = zero + + d = one + k = one + w = one + t = BigDecimal("-80") + while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) + m = BigDecimal.double_fig if m < BigDecimal.double_fig + t = t*m25 + d = t.div(k,m) + k = k+two + pi = pi + d + end + + d = one + k = one + w = one + t = BigDecimal("956") + while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) + m = BigDecimal.double_fig if m < BigDecimal.double_fig + t = t.div(m57121,m) + d = t.div(k,m) + pi = pi + d + k = k+two + end + pi + end +end -- cgit v1.2.1