long-decimal 0.00.06 → 0.00.07
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/README +15 -6
- data/VERSION +1 -1
- data/lib/longdecimal.rb +225 -80
- data/test/testlongdecimal.rb +107 -19
- metadata +2 -2
data/README
CHANGED
|
@@ -6,13 +6,21 @@ load "longdecimal.rb"
|
|
|
6
6
|
to your ruby-file. Please read the code to get an idea how to use this.
|
|
7
7
|
|
|
8
8
|
To test on Linux/Unix:
|
|
9
|
-
put longdecimal.rb
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
./testlongdecimal.rb
|
|
9
|
+
go into a directory long-decimal, put longdecimal.rb into a
|
|
10
|
+
sub-directory lib and testlongdecimal.rb into a sub-directory test.
|
|
11
|
+
This is the directory structure you get when unpacking the tar.gz
|
|
12
|
+
archive. Then:
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
chmod +x test/testlongdecimal.rb
|
|
15
|
+
|
|
16
|
+
and run it:
|
|
17
|
+
|
|
18
|
+
./test/testlongdecimal.rb
|
|
19
|
+
|
|
20
|
+
You should not get any error nor any failure. The tests will take a
|
|
21
|
+
minute or so, depending on the CPU-speed of your machine.
|
|
22
|
+
|
|
23
|
+
License
|
|
16
24
|
-------
|
|
17
25
|
|
|
18
26
|
Ruby's license or LGPL
|
|
@@ -31,3 +39,4 @@ Author
|
|
|
31
39
|
|
|
32
40
|
Karl Brodowsky
|
|
33
41
|
http://www.velofahren.de/cgi-bin/mailform.cgi
|
|
42
|
+
(no direct mail address because I do not like spam)
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.00.
|
|
1
|
+
0.00.07
|
data/lib/longdecimal.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#
|
|
2
2
|
# longdecimal.rb -- Arbitrary precision decimals with fixed decimal point
|
|
3
3
|
#
|
|
4
|
-
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/longdecimal.rb,v 1.
|
|
5
|
-
# CVS-Label: $Name:
|
|
4
|
+
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/longdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $
|
|
5
|
+
# CVS-Label: $Name: PRE_ALPHA_0_07 $
|
|
6
6
|
# Author: $Author: bk1 $ (Karl Brodowsky)
|
|
7
7
|
#
|
|
8
8
|
require "complex"
|
|
@@ -11,33 +11,190 @@ require "rational"
|
|
|
11
11
|
# require "bigdecimal/math"
|
|
12
12
|
|
|
13
13
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# is quite special and should go to some kind of Math-like class in the
|
|
17
|
-
# future.
|
|
14
|
+
# helper functions to support LongDecimal and LongDecimalQuot
|
|
15
|
+
# functions for LongDecimal that do not go as methods of LongDecimal
|
|
18
16
|
#
|
|
19
|
-
|
|
17
|
+
module LongMath
|
|
20
18
|
|
|
21
19
|
MAX_FLOATABLE = Float::MAX.to_i
|
|
22
20
|
MIN_FLOATABLE = Float::MIN.to_i
|
|
23
21
|
|
|
24
22
|
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
23
|
+
# helper method: checks if word_len is of reasonable for splitting a
|
|
24
|
+
# number into parts
|
|
25
|
+
#
|
|
26
|
+
def LongMath.check_word_len(word_len)
|
|
27
|
+
raise TypeError, "word_len must be a positive number <= 1024" unless (word_len.kind_of? Fixnum) && word_len > 0 && word_len <= 1024
|
|
28
|
+
word_len
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# private :check_word_len
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# split number x into parts of word_len bits each
|
|
35
|
+
# such that the concatenation of these parts as bit patterns is x
|
|
36
|
+
#
|
|
37
|
+
def LongMath.split_to_words(x, word_len = 32)
|
|
38
|
+
check_word_len(word_len)
|
|
39
|
+
raise TypeError, "x must be Integer" unless x.kind_of? Integer
|
|
40
|
+
m = x.abs
|
|
41
|
+
s = (x <=> 0)
|
|
42
|
+
bit_pattern = (1 << word_len) - 1
|
|
43
|
+
words = []
|
|
44
|
+
while (m != 0 || words.length == 0) do
|
|
45
|
+
w = m & bit_pattern
|
|
46
|
+
m = m >> word_len
|
|
47
|
+
words.unshift(w)
|
|
48
|
+
end
|
|
49
|
+
if (s < 0) then
|
|
50
|
+
words[0] = -words[0]
|
|
51
|
+
end
|
|
52
|
+
words
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# concatenate numbers given in words as bit patterns
|
|
57
|
+
#
|
|
58
|
+
def LongMath.merge_from_words(words, word_len = 32)
|
|
59
|
+
check_word_len(word_len)
|
|
60
|
+
raise TypeError, "words must be array of length > 0" unless (words.kind_of? Array) && words.length > 0
|
|
61
|
+
y = 0
|
|
62
|
+
s = (words[0] <=> 0)
|
|
63
|
+
if (s < 0) then
|
|
64
|
+
words[0] = -words[0]
|
|
65
|
+
end
|
|
66
|
+
words.each do |w|
|
|
67
|
+
y = y << word_len
|
|
68
|
+
y += w
|
|
69
|
+
end
|
|
70
|
+
if (s < 0) then
|
|
71
|
+
y = -y
|
|
72
|
+
end
|
|
73
|
+
y
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# calculate the square root of an integer using bitwise algorithm
|
|
78
|
+
#
|
|
79
|
+
def LongMath.sqrtb(x)
|
|
80
|
+
a = sqrtb_with_remainder(x)
|
|
81
|
+
a[0]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def LongMath.sqrtb_with_remainder(x)
|
|
85
|
+
raise TypeError, "x must be integer" unless x.kind_of? Integer
|
|
86
|
+
|
|
87
|
+
s = (x <=> 0)
|
|
88
|
+
if (s == 0) then
|
|
89
|
+
return [0, 0]
|
|
90
|
+
elsif (s < 0)
|
|
91
|
+
a = sqrtb_with_remainder(-x)
|
|
92
|
+
return [ Complex(0, a[0]), a[1]]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
xwords = split_to_words(x, 2)
|
|
96
|
+
xi = xwords[0] - 1
|
|
97
|
+
yi = 1
|
|
98
|
+
|
|
99
|
+
1.upto(xwords.length-1) do |i|
|
|
100
|
+
xi = (xi << 2) + xwords[i]
|
|
101
|
+
d0 = (yi << 2) + 1
|
|
102
|
+
r = xi - d0
|
|
103
|
+
b = 0
|
|
104
|
+
if (r >= 0) then
|
|
105
|
+
b = 1
|
|
106
|
+
xi = r
|
|
107
|
+
end
|
|
108
|
+
yi = (yi << 1) + b
|
|
109
|
+
end
|
|
110
|
+
return [yi, xi]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
#
|
|
114
|
+
# calculate the square root of an integer using larger chunks of the number
|
|
115
|
+
#
|
|
116
|
+
def LongMath.sqrtw(x, n = 16)
|
|
117
|
+
a = sqrtw_with_remainder(x, n)
|
|
118
|
+
a[0]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def LongMath.sqrtw_with_remainder(x, n = 16)
|
|
122
|
+
raise TypeError, "x must be integer" unless x.kind_of? Integer
|
|
123
|
+
raise TypeError, "n must be an integer" unless (n.kind_of? Integer)
|
|
124
|
+
n2 = n<<1
|
|
125
|
+
n1 = n+1
|
|
126
|
+
check_word_len(n2)
|
|
127
|
+
|
|
128
|
+
s = (x <=> 0)
|
|
129
|
+
if (s == 0) then
|
|
130
|
+
return [0, 0]
|
|
131
|
+
elsif (s < 0)
|
|
132
|
+
a = sqrtw_with_remainder(-x)
|
|
133
|
+
return [ Complex(0, a[0]), a[1]]
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
xwords = split_to_words(x, n2)
|
|
137
|
+
if (xwords.length == 1) then
|
|
138
|
+
return sqrtb_with_remainder(xwords[0])
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# puts(xwords.inspect + "\n")
|
|
142
|
+
xi = (xwords[0] << n2) + xwords[1]
|
|
143
|
+
a = sqrtb_with_remainder(xi)
|
|
144
|
+
yi = a[0]
|
|
145
|
+
if (xwords.length <= 2) then
|
|
146
|
+
return a
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
xi -= yi*yi
|
|
150
|
+
2.upto(xwords.length-1) do |i|
|
|
151
|
+
xi = (xi << n2) + xwords[i]
|
|
152
|
+
d0 = (yi << n1)
|
|
153
|
+
q = (xi / d0).to_i
|
|
154
|
+
q0 = q
|
|
155
|
+
j = 0
|
|
156
|
+
was_negative = false
|
|
157
|
+
while (true) do
|
|
158
|
+
d = d0 + q
|
|
159
|
+
r = xi - (q * d)
|
|
160
|
+
break if (0 <= r && (r < d || was_negative))
|
|
161
|
+
# puts("i=#{i} j=#{j} q=#{q} d0=#{d0} d=#{d} r=#{r} yi=#{yi} xi=#{xi}\n")
|
|
162
|
+
if (r < 0) then
|
|
163
|
+
was_negative = true
|
|
164
|
+
q = q-1
|
|
165
|
+
else
|
|
166
|
+
q = q+1
|
|
167
|
+
end
|
|
168
|
+
j += 1
|
|
169
|
+
if (j > 10) then
|
|
170
|
+
puts("i=#{i} j=#{j} q=#{q} q0=#{q0} d0=#{d0} d=#{d} r=#{r} yi=#{yi} xi=#{xi}\n")
|
|
171
|
+
break
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
xi = r
|
|
175
|
+
yi = (yi << n) + q
|
|
176
|
+
end
|
|
177
|
+
return [ yi, xi ]
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
#
|
|
181
|
+
# find the gcd of x with b^n0 where n0 is a sufficiently high
|
|
182
|
+
# exponent such that gcd(x, b^m) = gcd(x, b^n)
|
|
27
183
|
# for all m, n > n0
|
|
28
184
|
#
|
|
29
|
-
def gcd_with_high_power(b)
|
|
30
|
-
raise
|
|
185
|
+
def LongMath.gcd_with_high_power(x, b)
|
|
186
|
+
raise TypeError, "gcd_with_high_power can only be calculated for integers, but x=#{x.inspect} is no integer." unless x.kind_of? Integer
|
|
187
|
+
raise ZeroDivisionError, "gcd_with_high_power of zero with \"#{b.inspect}\" would be infinity" if x.zero?
|
|
31
188
|
raise TypeError, "gcd_with_high_power can only be calculated for integers \"#{b.inspect}\" is no integer" unless b.kind_of? Integer
|
|
32
189
|
raise ZeroDivisionError, "gcd_with_high_power with b < 2 is not defined. b=\"#{b.inspect}\"" if b < 2
|
|
33
|
-
s =
|
|
190
|
+
s = x.abs
|
|
34
191
|
exponent = 1
|
|
35
192
|
b = b.abs
|
|
36
193
|
if (b < s && s < MAX_FLOATABLE)
|
|
37
194
|
exponent = (Math.log(s) / Math.log(b)).ceil
|
|
38
195
|
end
|
|
39
|
-
power
|
|
40
|
-
result
|
|
196
|
+
power = b**exponent
|
|
197
|
+
result = 1
|
|
41
198
|
begin
|
|
42
199
|
f = s.gcd(power)
|
|
43
200
|
s /= f
|
|
@@ -51,45 +208,40 @@ class Integer
|
|
|
51
208
|
# self. Only works for prime numbers
|
|
52
209
|
# works even for numbers that exceed the range of Float
|
|
53
210
|
#
|
|
54
|
-
def multiplicity_of_factor(prime_number)
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
211
|
+
def LongMath.multiplicity_of_factor(x, prime_number)
|
|
212
|
+
|
|
213
|
+
if (x.kind_of? Rational) || (x.kind_of? LongDecimalQuot) then
|
|
214
|
+
m1 = multiplicity_of_factor(x.numerator, prime_number)
|
|
215
|
+
m2 = multiplicity_of_factor(x.denominator, prime_number)
|
|
216
|
+
return m1 - m2
|
|
217
|
+
|
|
218
|
+
elsif (x.kind_of? LongDecimal)
|
|
219
|
+
m1 = x.numerator.multiplicity_of_factor(prime_number)
|
|
220
|
+
if (prime_number == 2 || prime_number == 5) then
|
|
221
|
+
return m1 - x.scale
|
|
222
|
+
else
|
|
223
|
+
return m1
|
|
65
224
|
end
|
|
66
|
-
result += (Math.log(power) / Math.log(prime_number)).round
|
|
67
|
-
# result = (BigMath.log(BigDecimal(power.to_s + ".0", power.size)) / BigMath.log(BigDecimal(prime_number.to_s + ".0", prime_number.size))).round
|
|
68
|
-
# raise TypeError, "numbers are too big p=#{prime_number} power=#{power}"
|
|
69
|
-
end
|
|
70
|
-
result
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
225
|
|
|
74
|
-
|
|
75
|
-
# add some functionality to Rational.
|
|
76
|
-
# probably Rational is not the right place for this stuff, because it
|
|
77
|
-
# is quite special and should go to some kind of Math-like class in the
|
|
78
|
-
# future.
|
|
79
|
-
#
|
|
80
|
-
class Rational
|
|
226
|
+
elsif (x.kind_of? Integer)
|
|
81
227
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
228
|
+
power = gcd_with_high_power(x, prime_number)
|
|
229
|
+
if (power.abs < MAX_FLOATABLE) then
|
|
230
|
+
result = (Math.log(power) / Math.log(prime_number)).round
|
|
231
|
+
else
|
|
232
|
+
e = (Math.log(MAX_FLOATABLE) / Math.log(prime_number)).floor
|
|
233
|
+
result = 0
|
|
234
|
+
partial = prime_number ** e
|
|
235
|
+
while (power > partial) do
|
|
236
|
+
power /= partial
|
|
237
|
+
result += e
|
|
238
|
+
end
|
|
239
|
+
result += (Math.log(power) / Math.log(prime_number)).round
|
|
240
|
+
end
|
|
241
|
+
return result
|
|
242
|
+
else
|
|
243
|
+
raise TypeError, "type of x is not supported #{x.class} #{x.inpect}"
|
|
244
|
+
end
|
|
93
245
|
end
|
|
94
246
|
|
|
95
247
|
end
|
|
@@ -134,7 +286,7 @@ end
|
|
|
134
286
|
# digits and the other one the position of the decimal point.
|
|
135
287
|
#
|
|
136
288
|
class LongDecimal < Numeric
|
|
137
|
-
@RCS_ID='-$Id: longdecimal.rb,v 1.
|
|
289
|
+
@RCS_ID='-$Id: longdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $-'
|
|
138
290
|
|
|
139
291
|
include LongDecimalRoundingMode
|
|
140
292
|
|
|
@@ -242,8 +394,8 @@ class LongDecimal < Numeric
|
|
|
242
394
|
# we need to come up with a better rule here.
|
|
243
395
|
# if denominator is any product of powers of 2 and 5, we do not need to round
|
|
244
396
|
denom = x.denominator
|
|
245
|
-
mul_2 =
|
|
246
|
-
mul_5 =
|
|
397
|
+
mul_2 = LongMath.multiplicity_of_factor(denom, 2)
|
|
398
|
+
mul_5 = LongMath.multiplicity_of_factor(denom, 5)
|
|
247
399
|
iscale = [mul_2, mul_5].max
|
|
248
400
|
scale += iscale
|
|
249
401
|
denom /= 2 ** mul_2
|
|
@@ -640,7 +792,7 @@ class LongDecimal < Numeric
|
|
|
640
792
|
end
|
|
641
793
|
if (q.kind_of? LongDecimal) || (q.kind_of? LongDecimalQuot) then
|
|
642
794
|
if (new_scale.nil?) then
|
|
643
|
-
|
|
795
|
+
new_scale = q.scale
|
|
644
796
|
end
|
|
645
797
|
q.round_to_scale(new_scale, rounding_mode)
|
|
646
798
|
else
|
|
@@ -694,20 +846,6 @@ class LongDecimal < Numeric
|
|
|
694
846
|
return q, self - other * q
|
|
695
847
|
end
|
|
696
848
|
|
|
697
|
-
#
|
|
698
|
-
# find the exponent of the highest power of prime number p that divides
|
|
699
|
-
# self. Only works for prime numbers
|
|
700
|
-
# works even for numbers that exceed the range of Float
|
|
701
|
-
#
|
|
702
|
-
def multiplicity_of_factor(prime_number)
|
|
703
|
-
m1 = numerator.multiplicity_of_factor(prime_number)
|
|
704
|
-
if (prime_number == 2 || prime_number == 5) then
|
|
705
|
-
m1 - scale
|
|
706
|
-
else
|
|
707
|
-
m1
|
|
708
|
-
end
|
|
709
|
-
end
|
|
710
|
-
|
|
711
849
|
def %(other)
|
|
712
850
|
q, r = divmod other
|
|
713
851
|
r
|
|
@@ -837,12 +975,29 @@ class LongDecimal < Numeric
|
|
|
837
975
|
protected :move_point_left_int, :move_point_right_int
|
|
838
976
|
|
|
839
977
|
#
|
|
840
|
-
# calculate the
|
|
978
|
+
# calculate the square of self
|
|
841
979
|
#
|
|
842
980
|
def square
|
|
843
981
|
self * self
|
|
844
982
|
end
|
|
845
983
|
|
|
984
|
+
def sqrt(new_scale, rounding_mode)
|
|
985
|
+
raise TypeError, "new_scale #{new_scale.inspect} must be integer" unless new_scale.kind_of? Integer
|
|
986
|
+
raise TypeError, "new_scale #{new_scale.inspect} must be >= 0" unless new_scale >= 0
|
|
987
|
+
raise TypeError, "mode #{mode.inspect} must be legal rounding mode" unless rounding_mode.kind_of? RoundingModeClass
|
|
988
|
+
|
|
989
|
+
new_scale1 = new_scale + 1
|
|
990
|
+
old_scale = (new_scale1 << 1)
|
|
991
|
+
x = round_to_scale(old_scale, rounding_mode)
|
|
992
|
+
root, rem = LongMath.sqrtb_with_remainder(x.int_val)
|
|
993
|
+
if (rem > 0 && (rounding_mode == ROUND_HALF_EVEN || rounding_mode == ROUND_HALF_DOWN)) then
|
|
994
|
+
rounding_mode = ROUND_HALF_UP
|
|
995
|
+
end
|
|
996
|
+
y = LongDecimal(root, new_scale1)
|
|
997
|
+
y.round_to_scale(new_scale, rounding_mode)
|
|
998
|
+
end
|
|
999
|
+
|
|
1000
|
+
|
|
846
1001
|
#
|
|
847
1002
|
# calculate the multiplicative inverse
|
|
848
1003
|
#
|
|
@@ -940,7 +1095,6 @@ class LongDecimal < Numeric
|
|
|
940
1095
|
sprintf("LongDecimal(%s, %s)", int_val.inspect, scale.inspect)
|
|
941
1096
|
end
|
|
942
1097
|
|
|
943
|
-
|
|
944
1098
|
end
|
|
945
1099
|
|
|
946
1100
|
#
|
|
@@ -950,7 +1104,7 @@ end
|
|
|
950
1104
|
#
|
|
951
1105
|
class LongDecimalQuot < Numeric
|
|
952
1106
|
|
|
953
|
-
@RCS_ID='-$Id: longdecimal.rb,v 1.
|
|
1107
|
+
@RCS_ID='-$Id: longdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $-'
|
|
954
1108
|
|
|
955
1109
|
include LongDecimalRoundingMode
|
|
956
1110
|
|
|
@@ -1115,15 +1269,6 @@ class LongDecimalQuot < Numeric
|
|
|
1115
1269
|
# end
|
|
1116
1270
|
# end
|
|
1117
1271
|
|
|
1118
|
-
#
|
|
1119
|
-
# find the exponent of the highest power of prime number p that divides
|
|
1120
|
-
# self. Only works for prime numbers
|
|
1121
|
-
# works even for numbers that exceed the range of Float
|
|
1122
|
-
#
|
|
1123
|
-
def multiplicity_of_factor(prime_number)
|
|
1124
|
-
rat.multiplicity_of_factor(prime_number)
|
|
1125
|
-
end
|
|
1126
|
-
|
|
1127
1272
|
def square
|
|
1128
1273
|
self * self
|
|
1129
1274
|
end
|
data/test/testlongdecimal.rb
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
#
|
|
3
3
|
# testlongdecimal.rb -- runit test for longdecimal.rb
|
|
4
4
|
#
|
|
5
|
-
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/test/testlongdecimal.rb,v 1.
|
|
6
|
-
# CVS-Label: $Name:
|
|
5
|
+
# CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/test/testlongdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $
|
|
6
|
+
# CVS-Label: $Name: PRE_ALPHA_0_07 $
|
|
7
7
|
# Author: $Author: bk1 $ (Karl Brodowsky)
|
|
8
8
|
#
|
|
9
9
|
|
|
@@ -15,38 +15,126 @@ load "lib/longdecimal.rb"
|
|
|
15
15
|
|
|
16
16
|
class TestLongDecimal_class < RUNIT::TestCase
|
|
17
17
|
|
|
18
|
-
@RCS_ID='-$Id: testlongdecimal.rb,v 1.
|
|
18
|
+
@RCS_ID='-$Id: testlongdecimal.rb,v 1.3 2006/02/28 09:57:10 bk1 Exp $-'
|
|
19
|
+
|
|
20
|
+
def check_sqrtb(x, s)
|
|
21
|
+
y = LongMath.sqrtb(x)
|
|
22
|
+
z = y * y
|
|
23
|
+
zz = (y+1)*(y+1)
|
|
24
|
+
assert(0 <= y, "sqrt must be >= 0" + s)
|
|
25
|
+
assert(z <= x && x < zz, "y=#{y}=sqrt(#{x}) and x in [#{z}, #{zz})" + s)
|
|
26
|
+
y
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def _test_sqrtb
|
|
30
|
+
assert_equal(Complex(0,1), LongMath.sqrtb(-1), "sqrt(-1)=i")
|
|
31
|
+
1024.times do |x|
|
|
32
|
+
check_sqrtb(x, " loop x=#{x}")
|
|
33
|
+
end
|
|
34
|
+
512.times do |i|
|
|
35
|
+
x1 = i*i
|
|
36
|
+
y = check_sqrtb(x1, " i*i i=#{i}")
|
|
37
|
+
assert_equal(i, y, "i=#{i} y=#{y}")
|
|
38
|
+
if (i > 0) then
|
|
39
|
+
x2 = x1 + 1
|
|
40
|
+
y = check_sqrtb(x2, " i*i+1 i=#{i}")
|
|
41
|
+
assert_equal(i, y, "i=#{i} y=#{y}")
|
|
42
|
+
x0 = x1 - 1
|
|
43
|
+
y = check_sqrtb(x0, " i*i-1 i=#{i}")
|
|
44
|
+
assert_equal(i-1, y, "i=#{i} y=#{y}")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
x1 = 1 << i
|
|
48
|
+
y = check_sqrtb(x1, " 2**i i=#{i}")
|
|
49
|
+
if (i[0] == 0)
|
|
50
|
+
assert_equal(1 << (i>>1), y, "2^(i/2) i=#{i} y=#{y}")
|
|
51
|
+
end
|
|
52
|
+
if (i > 0) then
|
|
53
|
+
check_sqrtb(x1-1, " 2**i-1 i=#{i}")
|
|
54
|
+
check_sqrtb(x1+1, " 2**i+1 i=#{i}")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
x1 = 3 << i
|
|
58
|
+
check_sqrtb(x1, " 3*2**i i=#{i}")
|
|
59
|
+
check_sqrtb(x1-1, " 3*2**i-1 i=#{i}")
|
|
60
|
+
check_sqrtb(x1+1, " 3*2**i+1 i=#{i}")
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def check_sqrtw(x, s)
|
|
65
|
+
y = LongMath.sqrtw(x)
|
|
66
|
+
z = y * y
|
|
67
|
+
zz = (y+1)*(y+1)
|
|
68
|
+
assert(0 <= y, "sqrt must be >= 0" + s)
|
|
69
|
+
assert(z <= x && x < zz, "y=#{y}=sqrt(#{x}) and x in [#{z}, #{zz})" + s)
|
|
70
|
+
y
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_sqrtw
|
|
74
|
+
assert_equal(Complex(0,1), LongMath.sqrtw(-1), "sqrt(-1)=i")
|
|
75
|
+
1024.times do |x|
|
|
76
|
+
check_sqrtw(x, " loop x=#{x}")
|
|
77
|
+
end
|
|
78
|
+
1024.times do |i|
|
|
79
|
+
x1 = i*i
|
|
80
|
+
y = check_sqrtw(x1, " i*i i=#{i}")
|
|
81
|
+
assert_equal(i, y, "i=#{i} y=#{y}")
|
|
82
|
+
if (i > 0) then
|
|
83
|
+
x2 = x1 + 1
|
|
84
|
+
y = check_sqrtw(x2, " i*i+1 i=#{i}")
|
|
85
|
+
assert_equal(i, y, "i=#{i} y=#{y}")
|
|
86
|
+
x0 = x1 - 1
|
|
87
|
+
y = check_sqrtw(x0, " i*i-1 i=#{i}")
|
|
88
|
+
assert_equal(i-1, y, "i=#{i} y=#{y}")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
x1 = 1 << i
|
|
92
|
+
y = check_sqrtw(x1, " 2**i i=#{i}")
|
|
93
|
+
if (i[0] == 0)
|
|
94
|
+
assert_equal(1 << (i>>1), y, "2^(i/2) i=#{i} y=#{y}")
|
|
95
|
+
end
|
|
96
|
+
if (i > 0) then
|
|
97
|
+
check_sqrtw(x1-1, " 2**i-1 i=#{i}")
|
|
98
|
+
check_sqrtw(x1+1, " 2**i+1 i=#{i}")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
x1 = 3 << i
|
|
102
|
+
check_sqrtw(x1, " 3*2**i i=#{i}")
|
|
103
|
+
check_sqrtw(x1-1, " 3*2**i-1 i=#{i}")
|
|
104
|
+
check_sqrtw(x1+1, " 3*2**i+1 i=#{i}")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
19
107
|
|
|
20
108
|
def test_gcd_with_high_power
|
|
21
109
|
n = 224
|
|
22
|
-
assert_equal(32,
|
|
23
|
-
assert_equal(7,
|
|
24
|
-
assert_equal(1,
|
|
110
|
+
assert_equal(32, LongMath.gcd_with_high_power(n, 2), "2-part of 224 is 32")
|
|
111
|
+
assert_equal(7, LongMath.gcd_with_high_power(n, 7), "7-part of 224 is 7")
|
|
112
|
+
assert_equal(1, LongMath.gcd_with_high_power(n, 3), "3-part of 224 is 1")
|
|
25
113
|
end
|
|
26
114
|
|
|
27
115
|
def test_multiplicity_of_factor
|
|
28
116
|
n = 224
|
|
29
|
-
assert_equal(5,
|
|
30
|
-
assert_equal(1,
|
|
31
|
-
assert_equal(0,
|
|
117
|
+
assert_equal(5, LongMath.multiplicity_of_factor(n, 2), "ny_2(224) is 5")
|
|
118
|
+
assert_equal(1, LongMath.multiplicity_of_factor(n, 7), "ny_7(224) is 1")
|
|
119
|
+
assert_equal(0, LongMath.multiplicity_of_factor(n, 3), "ny_3(224) is 0")
|
|
32
120
|
end
|
|
33
121
|
|
|
34
122
|
def test_rat_multiplicity_of_factor
|
|
35
123
|
n = Rational(224, 225)
|
|
36
|
-
assert_equal(5,
|
|
37
|
-
assert_equal(1,
|
|
38
|
-
assert_equal(-2,
|
|
39
|
-
assert_equal(-2,
|
|
40
|
-
assert_equal(0,
|
|
124
|
+
assert_equal(5, LongMath.multiplicity_of_factor(n, 2), "ny_2(n) is 5")
|
|
125
|
+
assert_equal(1, LongMath.multiplicity_of_factor(n, 7), "ny_7(n) is 1")
|
|
126
|
+
assert_equal(-2, LongMath.multiplicity_of_factor(n, 3), "ny_3(n) is -2")
|
|
127
|
+
assert_equal(-2, LongMath.multiplicity_of_factor(n, 5), "ny_5(n) is -2")
|
|
128
|
+
assert_equal(0, LongMath.multiplicity_of_factor(n, 11), "ny_11(n) is 0")
|
|
41
129
|
end
|
|
42
130
|
|
|
43
131
|
def test_rat_long_multiplicity_of_factor
|
|
44
132
|
n = Rational(224*(10**600+1), 225*(5**800))
|
|
45
|
-
assert_equal(5,
|
|
46
|
-
assert_equal(1,
|
|
47
|
-
assert_equal(-2,
|
|
48
|
-
assert_equal(-802,
|
|
49
|
-
assert_equal(0,
|
|
133
|
+
assert_equal(5, LongMath.multiplicity_of_factor(n, 2), "ny_2(n) is 5")
|
|
134
|
+
assert_equal(1, LongMath.multiplicity_of_factor(n, 7), "ny_7(n) is 1")
|
|
135
|
+
assert_equal(-2, LongMath.multiplicity_of_factor(n, 3), "ny_3(n) is -2")
|
|
136
|
+
assert_equal(-802, LongMath.multiplicity_of_factor(n, 5), "ny_5(n) is -2")
|
|
137
|
+
assert_equal(0, LongMath.multiplicity_of_factor(n, 11), "ny_11(n) is 0")
|
|
50
138
|
end
|
|
51
139
|
|
|
52
140
|
def test_int_init
|
metadata
CHANGED
|
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
|
3
3
|
specification_version: 1
|
|
4
4
|
name: long-decimal
|
|
5
5
|
version: !ruby/object:Gem::Version
|
|
6
|
-
version: 0.00.
|
|
7
|
-
date: 2006-02-
|
|
6
|
+
version: 0.00.07
|
|
7
|
+
date: 2006-02-28 00:00:00 +01:00
|
|
8
8
|
summary: LongDecimal for numbers with fixed point
|
|
9
9
|
require_paths:
|
|
10
10
|
- lib
|