source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/math.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 5.9 KB
Line 
1#
2#--
3# Contents:
4# sqrt(x, prec)
5# sin (x, prec)
6# cos (x, prec)
7# atan(x, prec) Note: |x|<1, x=0.9999 may not converge.
8# exp (x, prec)
9# log (x, prec)
10# PI (prec)
11# E (prec) == exp(1.0,prec)
12#
13# where:
14# x ... BigDecimal number to be computed.
15# |x| must be small enough to get convergence.
16# prec ... Number of digits to be obtained.
17#++
18#
19# Provides mathematical functions.
20#
21# Example:
22#
23# require "bigdecimal"
24# require "bigdecimal/math"
25#
26# include BigMath
27#
28# a = BigDecimal((PI(100)/2).to_s)
29# puts sin(a,100) # -> 0.10000000000000000000......E1
30#
31module BigMath
32
33 # Computes the square root of x to the specified number of digits of
34 # precision.
35 #
36 # BigDecimal.new('2').sqrt(16).to_s
37 # -> "0.14142135623730950488016887242096975E1"
38 #
39 def sqrt(x,prec)
40 x.sqrt(prec)
41 end
42
43 # Computes the sine of x to the specified number of digits of precision.
44 #
45 # If x is infinite or NaN, returns NaN.
46 def sin(x, prec)
47 raise ArgumentError, "Zero or negative precision for sin" if prec <= 0
48 return BigDecimal("NaN") if x.infinite? || x.nan?
49 n = prec + BigDecimal.double_fig
50 one = BigDecimal("1")
51 two = BigDecimal("2")
52 x1 = x
53 x2 = x.mult(x,n)
54 sign = 1
55 y = x
56 d = y
57 i = one
58 z = one
59 while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
60 m = BigDecimal.double_fig if m < BigDecimal.double_fig
61 sign = -sign
62 x1 = x2.mult(x1,n)
63 i += two
64 z *= (i-one) * i
65 d = sign * x1.div(z,m)
66 y += d
67 end
68 y
69 end
70
71 # Computes the cosine of x to the specified number of digits of precision.
72 #
73 # If x is infinite or NaN, returns NaN.
74 def cos(x, prec)
75 raise ArgumentError, "Zero or negative precision for cos" if prec <= 0
76 return BigDecimal("NaN") if x.infinite? || x.nan?
77 n = prec + BigDecimal.double_fig
78 one = BigDecimal("1")
79 two = BigDecimal("2")
80 x1 = one
81 x2 = x.mult(x,n)
82 sign = 1
83 y = one
84 d = y
85 i = BigDecimal("0")
86 z = one
87 while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
88 m = BigDecimal.double_fig if m < BigDecimal.double_fig
89 sign = -sign
90 x1 = x2.mult(x1,n)
91 i += two
92 z *= (i-one) * i
93 d = sign * x1.div(z,m)
94 y += d
95 end
96 y
97 end
98
99 # Computes the arctangent of x to the specified number of digits of precision.
100 #
101 # If x is infinite or NaN, returns NaN.
102 # Raises an argument error if x > 1.
103 def atan(x, prec)
104 raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
105 return BigDecimal("NaN") if x.infinite? || x.nan?
106 raise ArgumentError, "x.abs must be less than 1.0" if x.abs>=1
107 n = prec + BigDecimal.double_fig
108 y = x
109 d = y
110 t = x
111 r = BigDecimal("3")
112 x2 = x.mult(x,n)
113 while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
114 m = BigDecimal.double_fig if m < BigDecimal.double_fig
115 t = -t.mult(x2,n)
116 d = t.div(r,m)
117 y += d
118 r += 2
119 end
120 y
121 end
122
123 # Computes the value of e (the base of natural logarithms) raised to the
124 # power of x, to the specified number of digits of precision.
125 #
126 # If x is infinite or NaN, returns NaN.
127 #
128 # BigMath::exp(BigDecimal.new('1'), 10).to_s
129 # -> "0.271828182845904523536028752390026306410273E1"
130 def exp(x, prec)
131 raise ArgumentError, "Zero or negative precision for exp" if prec <= 0
132 return BigDecimal("NaN") if x.infinite? || x.nan?
133 n = prec + BigDecimal.double_fig
134 one = BigDecimal("1")
135 x1 = one
136 y = one
137 d = y
138 z = one
139 i = 0
140 while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
141 m = BigDecimal.double_fig if m < BigDecimal.double_fig
142 x1 = x1.mult(x,n)
143 i += 1
144 z *= i
145 d = x1.div(z,m)
146 y += d
147 end
148 y
149 end
150
151 # Computes the natural logarithm of x to the specified number of digits
152 # of precision.
153 #
154 # Returns x if x is infinite or NaN.
155 #
156 def log(x, prec)
157 raise ArgumentError, "Zero or negative argument for log" if x <= 0 || prec <= 0
158 return x if x.infinite? || x.nan?
159 one = BigDecimal("1")
160 two = BigDecimal("2")
161 n = prec + BigDecimal.double_fig
162 x = (x - one).div(x + one,n)
163 x2 = x.mult(x,n)
164 y = x
165 d = y
166 i = one
167 while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
168 m = BigDecimal.double_fig if m < BigDecimal.double_fig
169 x = x2.mult(x,n)
170 i += two
171 d = x.div(i,m)
172 y += d
173 end
174 y*two
175 end
176
177 # Computes the value of pi to the specified number of digits of precision.
178 def PI(prec)
179 raise ArgumentError, "Zero or negative argument for PI" if prec <= 0
180 n = prec + BigDecimal.double_fig
181 zero = BigDecimal("0")
182 one = BigDecimal("1")
183 two = BigDecimal("2")
184
185 m25 = BigDecimal("-0.04")
186 m57121 = BigDecimal("-57121")
187
188 pi = zero
189
190 d = one
191 k = one
192 w = one
193 t = BigDecimal("-80")
194 while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
195 m = BigDecimal.double_fig if m < BigDecimal.double_fig
196 t = t*m25
197 d = t.div(k,m)
198 k = k+two
199 pi = pi + d
200 end
201
202 d = one
203 k = one
204 w = one
205 t = BigDecimal("956")
206 while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
207 m = BigDecimal.double_fig if m < BigDecimal.double_fig
208 t = t.div(m57121,n)
209 d = t.div(k,m)
210 pi = pi + d
211 k = k+two
212 end
213 pi
214 end
215
216 # Computes e (the base of natural logarithms) to the specified number of
217 # digits of precision.
218 def E(prec)
219 raise ArgumentError, "Zero or negative precision for E" if prec <= 0
220 n = prec + BigDecimal.double_fig
221 one = BigDecimal("1")
222 y = one
223 d = y
224 z = one
225 i = 0
226 while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
227 m = BigDecimal.double_fig if m < BigDecimal.double_fig
228 i += 1
229 z *= i
230 d = one.div(z,m)
231 y += d
232 end
233 y
234 end
235end
Note: See TracBrowser for help on using the repository browser.