flt 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +10 -0
- data/Manifest.txt +5 -0
- data/README.txt +16 -10
- data/lib/flt/bin_num.rb +4 -0
- data/lib/flt/complex.rb +312 -0
- data/lib/flt/dec_num.rb +0 -21
- data/lib/flt/math.rb +47 -567
- data/lib/flt/num.rb +249 -20
- data/lib/flt/trigonometry.rb +746 -0
- data/lib/flt/version.rb +2 -2
- data/test/generate_trig_data.rb +169 -0
- data/test/test_basic.rb +5 -0
- metadata +11 -4
data/lib/flt/math.rb
CHANGED
@@ -1,587 +1,67 @@
|
|
1
1
|
require 'flt/dec_num'
|
2
|
+
require 'flt/bin_num'
|
3
|
+
require 'flt/trigonometry'
|
2
4
|
|
3
5
|
module Flt
|
4
6
|
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
7
|
+
# Base module for Math modules for specific Num classes. Math modules area analogous to
|
8
|
+
# ::Math and provide both a means to access math functions (of the current context for a Num class)
|
9
|
+
# and, more useful here, a means to access the functions unqualified by including the module in some
|
10
|
+
# scope.
|
11
|
+
#
|
12
|
+
# The math functions provided by Math modules are trigonometric (sin, cos, tan, asin, acos, atan, hypot),
|
13
|
+
# exp, log, log2, and log10.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
# DecNum.context(:precision=>5) do
|
17
|
+
# puts DecNum::Math.sqrt(2) # => 1.4142
|
18
|
+
# end
|
19
|
+
# DecNum.context.precision = 10
|
20
|
+
# include DecNum::Math
|
21
|
+
# puts sqrt(2) # => 1.414213562
|
22
|
+
#
|
10
23
|
module MathBase
|
11
24
|
|
12
|
-
|
13
|
-
|
14
|
-
cos_base(num_class.Num(x))
|
25
|
+
def self.included(base)
|
26
|
+
base.extend ClassMethods
|
15
27
|
end
|
16
28
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# Tangent of an angle given in the units specified by DecNum.context.angle.
|
23
|
-
def tan(x)
|
24
|
-
tan_base(num_class.Num(x))
|
25
|
-
end
|
26
|
-
|
27
|
-
# Arc-tangent. The result is in the units specified by DecNum.context.angle.
|
28
|
-
# If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
|
29
|
-
def atan(x)
|
30
|
-
atan_base(num_class.Num(x))
|
31
|
-
end
|
32
|
-
|
33
|
-
# Arc-tangent with two arguments (principal value of the argument of the complex number x+i*y).
|
34
|
-
# The result is in the units specified by DecNum.context.angle.
|
35
|
-
# If the angular units are radians the result is in [-pi, pi]; it is in [-180,180] in degrees.
|
36
|
-
def atan2(y, x)
|
37
|
-
atan2_base(num_class.Num(y), num_class.Num(x))
|
38
|
-
end
|
39
|
-
|
40
|
-
# Arc-sine. The result is in the units specified by DecNum.context.angle.
|
41
|
-
# If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
|
42
|
-
def asin(x)
|
43
|
-
asin_base(num_class.Num(x))
|
44
|
-
end
|
45
|
-
|
46
|
-
# Arc-cosine. The result is in the units specified by DecNum.context.angle.
|
47
|
-
# If the angular units are radians the result is in [-pi/2, pi/2]; it is in [-90,90] in degrees.
|
48
|
-
def acos(x)
|
49
|
-
acos_base(num_class.Num(x))
|
50
|
-
end
|
51
|
-
|
52
|
-
# Length of the hypotenuse of a right-angle triangle (modulus or absolute value of the complex x+i*y).
|
53
|
-
def hypot(x, y)
|
54
|
-
hypot_base(num_class.Num(x), num_class.Num(y))
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def cos_base(x)
|
60
|
-
x = x.abs
|
61
|
-
rev_sign = false
|
62
|
-
s = nil
|
63
|
-
num_class.context do |local_context|
|
64
|
-
local_context.precision += 3 # extra digits for intermediate steps
|
65
|
-
x,k,pi_2 = reduce_angle2(x,2)
|
66
|
-
rev_sign = true if k>1
|
67
|
-
if k % 2 == 0
|
68
|
-
x = pi_2 - x
|
29
|
+
module ClassMethods
|
30
|
+
def num_class(cls, &blk)
|
31
|
+
define_method(:num_class){cls}
|
32
|
+
if blk
|
33
|
+
define_method(:context, &blk)
|
69
34
|
else
|
70
|
-
|
71
|
-
end
|
72
|
-
x = to_rad(x)
|
73
|
-
i, lasts, fact, num = 1, 0, 1, num_class.Num(x)
|
74
|
-
s = num
|
75
|
-
x2 = -x*x
|
76
|
-
while s != lasts
|
77
|
-
lasts = s
|
78
|
-
i += 2
|
79
|
-
fact *= i * (i-1)
|
80
|
-
num *= x2
|
81
|
-
s += num / fact
|
35
|
+
define_method(:context){num_class.context}
|
82
36
|
end
|
37
|
+
module_function :num_class, :context
|
83
38
|
end
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
sign = x.sign
|
89
|
-
s = nil
|
90
|
-
num_class.context do |local_context|
|
91
|
-
local_context.precision += 3 # extra digits for intermediate steps
|
92
|
-
x = x.abs if sign<0
|
93
|
-
x,k,pi_2 = reduce_angle2(x,2)
|
94
|
-
sign = -sign if k>1
|
95
|
-
x = pi_2 - x if k % 2 == 1
|
96
|
-
x = to_rad(x)
|
97
|
-
i, lasts, fact, num = 1, 0, 1, num_class.Num(x)
|
98
|
-
s = num
|
99
|
-
x2 = -x*x
|
100
|
-
while s != lasts
|
101
|
-
lasts = s
|
102
|
-
i += 2
|
103
|
-
fact *= i * (i-1)
|
104
|
-
num *= x2
|
105
|
-
s += num / fact
|
106
|
-
end
|
107
|
-
end
|
108
|
-
return (+s).copy_sign(sign)
|
109
|
-
end
|
110
|
-
|
111
|
-
def tan_base(x)
|
112
|
-
+num_class.context do |local_context|
|
113
|
-
local_context.precision += 2 # extra digits for intermediate steps
|
114
|
-
s,c = sin(x), cos(x)
|
115
|
-
s/c
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def atan_base(x)
|
120
|
-
s = nil
|
121
|
-
conversion = true
|
122
|
-
extra_prec = num_class.radix==2 ? 4 : 2
|
123
|
-
num_class.context do |local_context|
|
124
|
-
local_context.precision += extra_prec
|
125
|
-
if x == 0
|
126
|
-
return DecNum.zero
|
127
|
-
elsif x.abs > 1
|
128
|
-
if x.infinite?
|
129
|
-
s = (quarter_cycle).copy_sign(x)
|
130
|
-
conversion = false
|
131
|
-
break
|
132
|
-
else
|
133
|
-
# c = (quarter_cycle).copy_sign(x)
|
134
|
-
c = (half*pi).copy_sign(x)
|
135
|
-
x = 1 / x
|
39
|
+
def math_function(*fs)
|
40
|
+
fs.each do |f|
|
41
|
+
define_method f do |*args|
|
42
|
+
context.send f, *args
|
136
43
|
end
|
137
|
-
|
138
|
-
local_context.precision += extra_prec
|
139
|
-
x_squared = x ** 2
|
140
|
-
if x_squared.zero? || x_squared.subnormal?
|
141
|
-
s = x
|
142
|
-
s = c - s if c && c!=0
|
143
|
-
break
|
144
|
-
end
|
145
|
-
y = x_squared / (1 + x_squared)
|
146
|
-
y_over_x = y / x
|
147
|
-
i = num_class.zero; lasts = 0; s = y_over_x; coeff = 1; num = y_over_x
|
148
|
-
while s != lasts
|
149
|
-
lasts = s
|
150
|
-
i += 2
|
151
|
-
coeff *= i / (i + 1)
|
152
|
-
num *= y
|
153
|
-
s += coeff * num
|
154
|
-
end
|
155
|
-
if c && c!= 0
|
156
|
-
s = c - s
|
44
|
+
module_function f
|
157
45
|
end
|
158
46
|
end
|
159
|
-
return conversion ? rad_to(s) : +s
|
160
47
|
end
|
161
48
|
|
162
|
-
def atan2_base(y, x)
|
163
|
-
abs_y = y.abs
|
164
|
-
abs_x = x.abs
|
165
|
-
y_is_real = !x.infinite?
|
166
|
-
|
167
|
-
if x != 0
|
168
|
-
if y_is_real
|
169
|
-
a = y!=0 ? atan(y / x) : num_class.zero
|
170
|
-
a += half_cycle.copy_sign(y) if x < 0
|
171
|
-
return a
|
172
|
-
elsif abs_y == abs_x
|
173
|
-
x = num_class.Num(1).copy_sign(x)
|
174
|
-
y = num_class.Num(1).copy_sign(y)
|
175
|
-
return half_cycle * (2 - x) / (4 * y)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
if y != 0
|
180
|
-
return atan(num_class.infinity(y.sign))
|
181
|
-
elsif x < 0
|
182
|
-
return half_cycle.copy_sign(x)
|
183
|
-
else
|
184
|
-
return num_class.zero
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
def asin_base(x)
|
189
|
-
x = +x
|
190
|
-
return num_class.context.exception(Num::InvalidOperation, 'asin needs -1 <= x <= 1') if x.abs > 1
|
191
|
-
|
192
|
-
if x == -1
|
193
|
-
return -quarter_cycle
|
194
|
-
elsif x == 0
|
195
|
-
return num_class.zero
|
196
|
-
elsif x == 1
|
197
|
-
return quarter_cycle
|
198
|
-
end
|
199
|
-
|
200
|
-
num_class.context do |local_context|
|
201
|
-
local_context.precision += 3
|
202
|
-
x = x/(1-x*x).sqrt
|
203
|
-
x = atan(x)
|
204
|
-
end
|
205
|
-
+x
|
206
|
-
end
|
207
|
-
|
208
|
-
def acos_base(x)
|
209
|
-
|
210
|
-
return num_class.context.exception(Num::InvalidOperation, 'acos needs -1 <= x <= 2') if x.abs > 1
|
211
|
-
|
212
|
-
if x == -1
|
213
|
-
return half_cycle
|
214
|
-
elsif x == 0
|
215
|
-
return quarter_cycle
|
216
|
-
elsif x == 1
|
217
|
-
return num_class.zero
|
218
|
-
end
|
219
|
-
|
220
|
-
required_precision = num_class.context.precision
|
221
|
-
|
222
|
-
if x < half
|
223
|
-
num_class.context(:precision=>required_precision+2) do
|
224
|
-
x = x/(1-x*x).sqrt
|
225
|
-
x = quarter_cycle - atan(x)
|
226
|
-
end
|
227
|
-
else
|
228
|
-
# valid for x>=0
|
229
|
-
num_class.context(:precision=>required_precision+3) do
|
230
|
-
|
231
|
-
# x = (1-x*x).sqrt # x*x may require double precision if x*x is near 1
|
232
|
-
x = (1-BinNum.context(:precision=>required_precision*2){x*x}).sqrt
|
233
|
-
|
234
|
-
x = asin(x)
|
235
|
-
end
|
236
|
-
end
|
237
|
-
+x
|
238
|
-
|
239
|
-
end
|
240
|
-
|
241
|
-
def hypot_base(x, y)
|
242
|
-
num_class.context do |local_context|
|
243
|
-
local_context.precision += 3
|
244
|
-
(x*x + y*y).sqrt
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def e(digits=nil)
|
249
|
-
num_class.context do |local_context|
|
250
|
-
local_context.precision = digits if digits
|
251
|
-
num_class.Num(1).exp
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
def pi2(decimals=nil)
|
256
|
-
decimals ||= DecNum.context.precision
|
257
|
-
num_class.context(:precision=>decimals) do
|
258
|
-
pi(decimals)*2
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
def invpi(decimals=nil)
|
263
|
-
decimals ||= DecNum.context.precision
|
264
|
-
num_class.context(:precision=>decimals) do
|
265
|
-
num_class.Num(1)/pi(decimals)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
def inv2pi(decimals=nil)
|
270
|
-
decimals ||= DecNum.context.precision
|
271
|
-
num_class.context(:precision=>decimals) do
|
272
|
-
num_class.Num(1)/pi2(decimals)
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
# class <<self
|
277
|
-
# private
|
278
|
-
|
279
|
-
def iarccot(x, unity)
|
280
|
-
xpow = unity / x
|
281
|
-
n = 1
|
282
|
-
sign = 1
|
283
|
-
sum = 0
|
284
|
-
loop do
|
285
|
-
term = xpow / n
|
286
|
-
break if term == 0
|
287
|
-
sum += sign * (xpow/n)
|
288
|
-
xpow /= x*x
|
289
|
-
n += 2
|
290
|
-
sign = -sign
|
291
|
-
end
|
292
|
-
sum
|
293
|
-
end
|
294
|
-
|
295
|
-
def modtwopi(x)
|
296
|
-
return +num_class.context(:precision=>num_class.context.precision*3){x.modulo(one_cycle)}
|
297
|
-
end
|
298
|
-
|
299
|
-
# Reduce angle to [0,2Pi)
|
300
|
-
def reduce_angle(a)
|
301
|
-
modtwopi(a)
|
302
|
-
end
|
303
|
-
|
304
|
-
# Reduce angle to [0,Pi/k0) (result is not rounded to precision)
|
305
|
-
def reduce_angle2(a,k0=nil) # divisor of pi or nil for pi*2
|
306
|
-
# we could reduce first to pi*2 to avoid the mod k0 operation
|
307
|
-
k,r,divisor = DecNum.context do
|
308
|
-
num_class.context.precision *= 3
|
309
|
-
m = k0.nil? ? one_cycle : half_cycle/k0
|
310
|
-
a.divmod(m)+[m]
|
311
|
-
end
|
312
|
-
[r, k.modulo(k0*2).to_i, divisor]
|
313
|
-
end
|
314
|
-
|
315
|
-
def one_cycle
|
316
|
-
case num_class.context.angle
|
317
|
-
when :rad
|
318
|
-
pi2
|
319
|
-
when :deg
|
320
|
-
num_class.Num(360)
|
321
|
-
when :grad
|
322
|
-
num_class.Num(400)
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
def half_cycle
|
327
|
-
case num_class.context.angle
|
328
|
-
when :rad
|
329
|
-
pi
|
330
|
-
when :deg
|
331
|
-
num_class.Num(180)
|
332
|
-
when :grad
|
333
|
-
num_class.Num(200)
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
def quarter_cycle
|
338
|
-
case DecNum.context.angle
|
339
|
-
when :rad
|
340
|
-
half*pi
|
341
|
-
when :deg
|
342
|
-
num_class.Num(90)
|
343
|
-
when :grad
|
344
|
-
num_class.Num(100)
|
345
|
-
end
|
346
|
-
end
|
347
|
-
|
348
|
-
def to_rad(x)
|
349
|
-
case num_class.context.angle
|
350
|
-
when :rad
|
351
|
-
+x
|
352
|
-
else
|
353
|
-
+num_class.context(:precision=>num_class.context.precision+3){x*pi/half_cycle}
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
def to_deg(x)
|
358
|
-
case num_class.context.angle
|
359
|
-
when :deg
|
360
|
-
+x
|
361
|
-
else
|
362
|
-
+num_class.context(:precision=>num_class.context.precision+3){x*num_class.Num(180)/half_cycle}
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
|
-
def to_grad(x)
|
367
|
-
case DecNum.context.angle
|
368
|
-
when :deg
|
369
|
-
+x
|
370
|
-
else
|
371
|
-
+num_class.context(:precision=>num_class.context.precision+3){x*num_class.Num(200)/half_cycle}
|
372
|
-
end
|
373
|
-
end
|
374
|
-
|
375
|
-
def to_angle(angular_units, x)
|
376
|
-
return +x if angular_units == num_class.context.angle
|
377
|
-
case angular_units
|
378
|
-
when :rad
|
379
|
-
to_rad(x)
|
380
|
-
when :deg
|
381
|
-
to_deg(x)
|
382
|
-
when :grad
|
383
|
-
to_grad(x)
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
def rad_to(x)
|
388
|
-
case num_class.context.angle
|
389
|
-
when :rad
|
390
|
-
+x
|
391
|
-
else
|
392
|
-
+num_class.context(:precision=>num_class.context.precision+3){x*half_cycle/pi}
|
393
|
-
end
|
394
|
-
end
|
395
|
-
|
396
|
-
def deg_to(x)
|
397
|
-
case num_class.context.angle
|
398
|
-
when :deg
|
399
|
-
+x
|
400
|
-
else
|
401
|
-
+num_class.context(:precision=>num_class.context.precision+3){x*half_cycle/num_class.Num(180)}
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
def grad_to(x)
|
406
|
-
case num_class.context.angle
|
407
|
-
when :grad
|
408
|
-
+x
|
409
|
-
else
|
410
|
-
+num_class.context(:precision=>num_class.context.precision+3){x*half_cycle/num_class.Num(200)}
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
def angle_to(x, angular_units)
|
415
|
-
return +x if angular_units == num_class.context.angle
|
416
|
-
case angular_units
|
417
|
-
when :rad
|
418
|
-
rad_to(x)
|
419
|
-
when :deg
|
420
|
-
deg_to(x)
|
421
|
-
when :grad
|
422
|
-
grad_to(x)
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
#end
|
427
|
-
|
428
49
|
end
|
429
50
|
|
51
|
+
# Math module for DecNum; uses the current DecNum Context. See Flt::MathBase.
|
52
|
+
module DecNum::Math
|
53
|
+
include MathBase
|
54
|
+
num_class DecNum
|
55
|
+
math_function *Trigonometry.public_instance_methods
|
56
|
+
math_function :exp, :log, :log2, :log10, :sqrt
|
57
|
+
end
|
430
58
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
extend MathBase # make available for class methods
|
439
|
-
|
440
|
-
module Support
|
441
|
-
#private
|
442
|
-
def num_class
|
443
|
-
DecNum
|
444
|
-
end
|
445
|
-
|
446
|
-
def half
|
447
|
-
num_class.Num('0.5')
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
include Support
|
452
|
-
extend Support
|
453
|
-
|
454
|
-
module_function
|
455
|
-
|
456
|
-
|
457
|
-
# Pi
|
458
|
-
@@pi_cache = nil # truncated pi digits as a string
|
459
|
-
@@pi_cache_digits = 0
|
460
|
-
PI_MARGIN = 10
|
461
|
-
def pi(round_digits=nil)
|
462
|
-
|
463
|
-
round_digits ||= DecNum.context.precision
|
464
|
-
digits = round_digits
|
465
|
-
if @@pi_cache_digits <= digits # we need at least one more truncated digit
|
466
|
-
continue = true
|
467
|
-
while continue
|
468
|
-
margin = PI_MARGIN # margin to reduce recomputing with more digits to avoid ending in 0 or 5
|
469
|
-
digits += margin + 1
|
470
|
-
fudge = 10
|
471
|
-
unity = 10**(digits+fudge)
|
472
|
-
v = 4*(4*iarccot(5, unity) - iarccot(239, unity))
|
473
|
-
v = v.to_s[0,digits]
|
474
|
-
# if the last digit is 0 or 5 the truncated value may not be good for rounding
|
475
|
-
loop do
|
476
|
-
#last_digit = v%10
|
477
|
-
last_digit = v[-1,1].to_i
|
478
|
-
continue = (last_digit==5 || last_digit==0)
|
479
|
-
if continue && margin>0
|
480
|
-
# if we have margin we back-up one digit
|
481
|
-
margin -= 1
|
482
|
-
v = v[0...-1]
|
483
|
-
else
|
484
|
-
break
|
485
|
-
end
|
486
|
-
end
|
487
|
-
end
|
488
|
-
@@pi_cache_digits = digits + margin - PI_MARGIN # @pi_cache.size
|
489
|
-
@@pi_cache = v # DecNum(+1, v, 1-digits) # cache truncated value
|
490
|
-
end
|
491
|
-
# Now we avoid rounding too much because it is slow
|
492
|
-
l = round_digits + 1
|
493
|
-
while (l<@@pi_cache_digits) && [0,5].include?(@@pi_cache[l-1,1].to_i)
|
494
|
-
l += 1
|
495
|
-
end
|
496
|
-
v = @@pi_cache[0,l]
|
497
|
-
num_class.context(:precision=>round_digits){+num_class.Num(+1,v.to_i,1-l)}
|
498
|
-
end
|
499
|
-
|
500
|
-
|
501
|
-
end # DecNum::Math
|
502
|
-
|
503
|
-
class DecNum::Context
|
504
|
-
include DecNum::Math
|
505
|
-
public :sin, :cos, :tan, :atan, :asin, :acos, :atan2, :hypot, :pi, :e
|
506
|
-
end
|
507
|
-
|
508
|
-
def self.pi
|
509
|
-
self::Math.pi
|
510
|
-
end
|
511
|
-
|
512
|
-
def self.e
|
513
|
-
self::Math.e
|
514
|
-
end
|
515
|
-
|
516
|
-
end # DecNum
|
517
|
-
|
518
|
-
class BinNum
|
519
|
-
|
520
|
-
module Math
|
521
|
-
|
522
|
-
extend Flt # to access constructor methods DecNum
|
523
|
-
|
524
|
-
include MathBase # make available for instance methods
|
525
|
-
extend MathBase # make available for class methods
|
526
|
-
|
527
|
-
module Support
|
528
|
-
#private
|
529
|
-
def num_class
|
530
|
-
BinNum
|
531
|
-
end
|
532
|
-
|
533
|
-
def half
|
534
|
-
num_class.Num('0.5')
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
include Support
|
539
|
-
extend Support
|
540
|
-
|
541
|
-
module_function
|
542
|
-
|
543
|
-
# Pi
|
544
|
-
@@pi = nil
|
545
|
-
@@pi_cache = [num_class.Num(3), 3, 1, 0, 0, 24]
|
546
|
-
@@pi_digits = 0
|
547
|
-
def pi(round_digits=nil)
|
548
|
-
round_digits ||= num_class.context.precision
|
549
|
-
if @@pi_digits < round_digits
|
550
|
-
# provisional implementation (very slow)
|
551
|
-
lasts = 0
|
552
|
-
t, s, n, na, d, da = @@pi_cache
|
553
|
-
num_class.context do |local_context|
|
554
|
-
local_context.precision = round_digits + 6
|
555
|
-
while s != lasts
|
556
|
-
lasts = s
|
557
|
-
n, na = n+na, na+8
|
558
|
-
d, da = d+da, da+32
|
559
|
-
t = (t * n) / d
|
560
|
-
s += t
|
561
|
-
end
|
562
|
-
end
|
563
|
-
@pi_cache = [t, s, n, na, d, da]
|
564
|
-
@@pi = s
|
565
|
-
@@pi_digits = round_digits
|
566
|
-
end
|
567
|
-
num_class.context(:precision=>round_digits){+@@pi}
|
568
|
-
end
|
569
|
-
|
570
|
-
end # BinNum::Math
|
571
|
-
|
572
|
-
class BinNum::Context
|
573
|
-
include BinNum::Math
|
574
|
-
public :sin, :cos, :tan, :atan, :asin, :acos, :atan2, :hypot, :pi, :e
|
575
|
-
end
|
576
|
-
|
577
|
-
def self.pi
|
578
|
-
self::Math.pi
|
579
|
-
end
|
580
|
-
|
581
|
-
def self.e
|
582
|
-
self::Math.e
|
583
|
-
end
|
584
|
-
|
585
|
-
end # BinNum
|
59
|
+
# Math module for DecNum; uses the current DecNum Context. See Flt::MathBase.
|
60
|
+
module BinNum::Math
|
61
|
+
include MathBase
|
62
|
+
num_class BinNum
|
63
|
+
math_function *Trigonometry.public_instance_methods
|
64
|
+
math_function :exp, :log, :log2, :log10, :sqrt
|
65
|
+
end
|
586
66
|
|
587
|
-
end # Flt
|
67
|
+
end # Flt
|