flt 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ == 1.2.0 2010-06-15
2
+
3
+ * New Features
4
+ - Trigonometry in radians/degrees/gradians
5
+
1
6
  == 1.1.2 2010-06-01
2
7
 
3
8
  * New Features
data/README.txt CHANGED
@@ -567,7 +567,8 @@ EXPAND+
567
567
 
568
568
  = Roadmap
569
569
 
570
- * Version 1.0.0: First released version of the new flt gem.
571
- * Version 1.1.0: Implement the missing GDA functions:
570
+ * Math (trigonometry) functions for DecNum & BinNum (reorganization of DecNum::Math)
571
+ * Complex support.
572
+ * Implement the missing GDA functions:
572
573
  rotate, shift, trim, and, or, xor, invert,
573
574
  max, min, maxmag, minmag, comparetotal, comparetotmag
@@ -44,9 +44,13 @@ require 'singleton'
44
44
  #
45
45
  # Float::MIN : Minimum normalized positive floating-point number
46
46
  # b**(emin - 1).
47
+ # In JRuby this is the mininimum denormal number!
47
48
  #
48
49
  # Float::ROUNDS : Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown.
49
50
  #
51
+ # Note: Ruby 1.9.2 Adds Float::INFINITY and Float::NAN
52
+ #
53
+ #
50
54
  # Additional contants defined here:
51
55
  #
52
56
  # Float::DECIMAL_DIG : Number of decimal digits, n, such that any floating-point number can be rounded
@@ -56,11 +60,11 @@ require 'singleton'
56
60
  # ceil(1 + pmax * log10(b)) otherwise
57
61
  # DECIMAL_DIG = (MANT_DIG*Math.log(RADIX)/Math.log(10)).ceil+1
58
62
  #
59
- # Float::MIN_N : Minimum normalized number == MAX_D.next == MIN
63
+ # Float::MIN_N : Minimum normalized number == MAX_D.next == MIN (not in JRuby)
60
64
  #
61
65
  # Float::MAX_D : Maximum denormal number == MIN_N.prev
62
66
  #
63
- # Float::MIN_D : Minimum non zero positive denormal number == 0.0.next
67
+ # Float::MIN_D : Minimum non zero positive denormal number == 0.0.next (== MIN in JRuby)
64
68
  #
65
69
  # Float::MAX_F : Maximum significand
66
70
  class Float
@@ -110,7 +114,7 @@ class Flt::FloatContext
110
114
 
111
115
  # NaN (not a number value)
112
116
  def nan
113
- 0.0/0.0
117
+ 0.0/0.0 # Ruby 1.9.2: Float::NAN
114
118
  end
115
119
 
116
120
  # zero value with specified sign
@@ -120,7 +124,7 @@ class Flt::FloatContext
120
124
 
121
125
  # infinity value with specified sign
122
126
  def infinity(sign=+1)
123
- (sign < 0) ? -1.0/0.0 : 1.0/0.0
127
+ (sign < 0) ? -1.0/0.0 : 1.0/0.0 # Ruby 1.9.2: (sing < 0) ? -Float::INFINITY : Float::INFINITY
124
128
  end
125
129
 
126
130
  def int_radix_power(n)
@@ -1,10 +1,5 @@
1
1
  require 'flt/dec_num'
2
2
 
3
- # TODO:
4
- # * convert arguments as Context#_convert does, to accept non DecNum arguments
5
- # * Better precision (currently is within about 2 ulps of the correct result)
6
- # * Speed optimization
7
-
8
3
  module Flt
9
4
  class DecNum
10
5
  module Math
@@ -18,7 +13,6 @@ module Flt
18
13
  HALF = DecNum('0.5')
19
14
 
20
15
  # Pi
21
- $no_cache = false
22
16
  @@pi_cache = nil # truncated pi digits as a string
23
17
  @@pi_cache_digits = 0
24
18
  PI_MARGIN = 10
@@ -68,7 +62,10 @@ module Flt
68
62
  end
69
63
  end
70
64
 
71
- # Cosine of angle in radians
65
+ # Cosine of an angle given in the units specified by DecNum.context.angle:
66
+ # * :rad for radians
67
+ # * :deg for degrees
68
+ # * :grad for gradians
72
69
  def cos(x)
73
70
  x = x.abs
74
71
  rev_sign = false
@@ -82,6 +79,7 @@ module Flt
82
79
  else
83
80
  rev_sign = !rev_sign
84
81
  end
82
+ x = to_rad(x)
85
83
  i, lasts, fact, num = 1, 0, 1, DecNum(x)
86
84
  s = num
87
85
  x2 = -x*x
@@ -96,7 +94,10 @@ module Flt
96
94
  return rev_sign ? (-s) : (+s)
97
95
  end
98
96
 
99
- # Sine of angle in radians
97
+ # Sine of an angle given in the units specified by DecNum.context.angle:
98
+ # * :rad for radians
99
+ # * :deg for degrees
100
+ # * :grad for gradians
100
101
  def sin(x)
101
102
  sign = x.sign
102
103
  s = nil
@@ -106,7 +107,7 @@ module Flt
106
107
  x,k,pi_2 = reduce_angle2(x,2)
107
108
  sign = -sign if k>1
108
109
  x = pi_2 - x if k % 2 == 1
109
- x = +x
110
+ x = to_rad(x)
110
111
  i, lasts, fact, num = 1, 0, 1, DecNum(x)
111
112
  s = num
112
113
  x2 = -x*x
@@ -121,6 +122,7 @@ module Flt
121
122
  return (+s).copy_sign(sign)
122
123
  end
123
124
 
125
+ # Tangent of an angle
124
126
  def tan(x)
125
127
  +DecNum.context do |local_context|
126
128
  local_context.precision += 2 # extra digits for intermediate steps
@@ -129,19 +131,22 @@ module Flt
129
131
  end
130
132
  end
131
133
 
132
- # Arc-tangent.
134
+ # Arc-tangent in units specified by DecNum.context.angle
133
135
  def atan(x)
134
136
  s = nil
137
+ conversion = true
135
138
  DecNum.context do |local_context|
136
139
  local_context.precision += 2
137
140
  if x == 0
138
141
  return DecNum.zero
139
142
  elsif x.abs > 1
140
143
  if x.infinite?
141
- s = (pi*HALF).copy_sign(x)
144
+ s = (quarter_cycle).copy_sign(x)
145
+ conversion = false
142
146
  break
143
147
  else
144
- c = (pi*HALF).copy_sign(x)
148
+ # c = (quarter_cycle).copy_sign(x)
149
+ c = (HALF*pi).copy_sign(x)
145
150
  x = 1 / x
146
151
  end
147
152
  end
@@ -161,7 +166,7 @@ module Flt
161
166
  s = c - s
162
167
  end
163
168
  end
164
- return +s
169
+ return conversion ? rad_to(s) : +s
165
170
  end
166
171
 
167
172
  def atan2(y, x)
@@ -172,19 +177,19 @@ module Flt
172
177
  if x != 0
173
178
  if y_is_real
174
179
  a = y!=0 ? atan(y / x) : DecNum.zero
175
- a += pi.copy_sign(y) if x < 0
180
+ a += half_cycle.copy_sign(y) if x < 0
176
181
  return a
177
182
  elsif abs_y == abs_x
178
183
  x = DecNum(1).copy_sign(x)
179
184
  y = DecNum(1).copy_sign(y)
180
- return pi * (2 - x) / (4 * y)
185
+ return half_cycle * (2 - x) / (4 * y)
181
186
  end
182
187
  end
183
188
 
184
189
  if y != 0
185
190
  return atan(DecNum.infinity(y.sign))
186
191
  elsif x < 0
187
- return pi.copy_sign(x)
192
+ return half_cycle.copy_sign(x)
188
193
  else
189
194
  return DecNum.zero
190
195
  end
@@ -195,11 +200,11 @@ module Flt
195
200
  return DecNum.context.exception(Num::InvalidOperation, 'asin needs -1 <= x <= 1') if x.abs > 1
196
201
 
197
202
  if x == -1
198
- return -pi*HALF
203
+ return -quarter_cycle
199
204
  elsif x == 0
200
205
  return DecNum.zero
201
206
  elsif x == 1
202
- return pi*HALF
207
+ return quarter_cycle
203
208
  end
204
209
 
205
210
  DecNum.context do |local_context|
@@ -212,29 +217,21 @@ module Flt
212
217
 
213
218
  def acos(x)
214
219
 
215
- # We can compute acos(x) = pi/2 - asin(x)
216
- # but we must take care with x near 1, where that formula would cause loss of precision
217
-
218
220
  return DecNum.context.exception(Num::InvalidOperation, 'acos needs -1 <= x <= 2') if x.abs > 1
219
221
 
220
222
  if x == -1
221
- return pi
223
+ return half_cycle
222
224
  elsif x == 0
223
- return +DecNum.context(:precision=>DecNum.context.precision+3){pi*HALF}
225
+ return quarter_cycle
224
226
  elsif x == 1
225
227
  return DecNum.zero
226
228
  end
227
229
 
228
- # some identities:
229
- # acos(x) = pi/2 - asin(x) # (but this losses accuracy near x=+1)
230
- # acos(x) = pi/2 - atan(x/(1-x*x).sqrt) # this too
231
- # acos(x) = asin((1-x*x).sqrt) for x>=0; for x<=0 acos(x) = pi/2 - asin((1-x*x).sqrt)
232
-
233
230
  if x < HALF
234
231
  DecNum.context do |local_context|
235
232
  local_context.precision += 3
236
233
  x = x/(1-x*x).sqrt
237
- x = pi*HALF - atan(x)
234
+ x = quarter_cycle - atan(x)
238
235
  end
239
236
  else
240
237
  # valid for x>=0
@@ -255,7 +252,7 @@ module Flt
255
252
  end
256
253
  end
257
254
 
258
- # TODO: degrees mode or radians/degrees conversion
255
+ # TODO: add angular units to context; add support for degrees
259
256
 
260
257
  def pi2(decimals=nil)
261
258
  decimals ||= DecNum.context.precision
@@ -298,34 +295,7 @@ module Flt
298
295
  end
299
296
 
300
297
  def modtwopi(x)
301
- return +DecNum.context(:precision=>DecNum.context.precision*3){x.modulo(pi2)}
302
- # This seems to be slower and less accurate:
303
- # prec = DecNum.context.precision
304
- # pi_2 = pi2(prec*2)
305
- # return x if x < pi_2
306
- # ex = x.fractional_exponent
307
- # DecNum.context do |local_context|
308
- # # x.modulo(pi_2)
309
- # local_context.precision *= 2
310
- # if ex > prec
311
- # # consider exponent separately
312
- # fd = nil
313
- # excess = ex - prec
314
- # x = x.scaleb(prec-ex)
315
- # # now obtain 2*prec digits from inv2pi after the initial excess digits
316
- # digits = nil
317
- # inv_2pi = inv2pi(local_context.precision+excess)
318
- # DecNum.context do |extended_context|
319
- # extended_context.precision += excess
320
- # digits = (inv2pi.scaleb(excess)).fraction_part
321
- # end
322
- # x *= digits*pi_2
323
- # end
324
- # # compute the fractional part of the division by 2pi
325
- # inv_2pi ||= inv2pi
326
- # x = pi_2*((x*inv2pi).fraction_part)
327
- # end
328
- # +x
298
+ return +DecNum.context(:precision=>DecNum.context.precision*3){x.modulo(one_cycle)}
329
299
  end
330
300
 
331
301
  # Reduce angle to [0,2Pi)
@@ -338,12 +308,123 @@ module Flt
338
308
  # we could reduce first to pi*2 to avoid the mod k0 operation
339
309
  k,r,divisor = DecNum.context do
340
310
  DecNum.context.precision *= 3
341
- m = k0.nil? ? pi2 : pi/k0
311
+ m = k0.nil? ? one_cycle : half_cycle/k0
342
312
  a.divmod(m)+[m]
343
313
  end
344
314
  [r, k.modulo(k0*2).to_i, divisor]
345
315
  end
346
316
 
317
+ def one_cycle
318
+ case DecNum.context.angle
319
+ when :rad
320
+ pi2
321
+ when :deg
322
+ DecNum(360)
323
+ when :grad
324
+ DecNum(400)
325
+ end
326
+ end
327
+
328
+ def half_cycle
329
+ case DecNum.context.angle
330
+ when :rad
331
+ pi
332
+ when :deg
333
+ DecNum(180)
334
+ when :grad
335
+ DecNum(200)
336
+ end
337
+ end
338
+
339
+ def quarter_cycle
340
+ case DecNum.context.angle
341
+ when :rad
342
+ HALF*pi
343
+ when :deg
344
+ DecNum(90)
345
+ when :grad
346
+ DecNum(100)
347
+ end
348
+ end
349
+
350
+ def to_rad(x)
351
+ case DecNum.context.angle
352
+ when :rad
353
+ +x
354
+ else
355
+ +DecNum.context(:precision=>DecNum.context.precision+3){x*pi/half_cycle}
356
+ end
357
+ end
358
+
359
+ def to_deg(x)
360
+ case DecNum.context.angle
361
+ when :deg
362
+ +x
363
+ else
364
+ +DecNum.context(:precision=>DecNum.context.precision+3){x*DecNum(180)/half_cycle}
365
+ end
366
+ end
367
+
368
+ def to_grad(x)
369
+ case DecNum.context.angle
370
+ when :deg
371
+ +x
372
+ else
373
+ +DecNum.context(:precision=>DecNum.context.precision+3){x*DecNum(200)/half_cycle}
374
+ end
375
+ end
376
+
377
+ def to_angle(angular_units, x)
378
+ return +x if angular_units == DecNum.context.angle
379
+ case angular_units
380
+ when :rad
381
+ to_rad(x)
382
+ when :deg
383
+ to_deg(x)
384
+ when :grad
385
+ to_grad(x)
386
+ end
387
+ end
388
+
389
+ def rad_to(x)
390
+ case DecNum.context.angle
391
+ when :rad
392
+ +x
393
+ else
394
+ +DecNum.context(:precision=>DecNum.context.precision+3){x*half_cycle/pi}
395
+ end
396
+ end
397
+
398
+ def deg_to(x)
399
+ case DecNum.context.angle
400
+ when :deg
401
+ +x
402
+ else
403
+ +DecNum.context(:precision=>DecNum.context.precision+3){x*half_cycle/DecNum(180)}
404
+ end
405
+ end
406
+
407
+ def grad_to(x)
408
+ case DecNum.context.angle
409
+ when :grad
410
+ +x
411
+ else
412
+ +DecNum.context(:precision=>DecNum.context.precision+3){x*half_cycle/DecNum(200)}
413
+ end
414
+ end
415
+
416
+ def angle_to(x, angular_units)
417
+ return +x if angular_units == DecNum.context.angle
418
+ case angular_units
419
+ when :rad
420
+ rad_to(x)
421
+ when :deg
422
+ deg_to(x)
423
+ when :grad
424
+ grad_to(x)
425
+ end
426
+ end
427
+
347
428
  #end
348
429
 
349
430
  end # Math
@@ -408,6 +408,7 @@ class Num < Numeric
408
408
  @flags = Num::Flags()
409
409
  @coercible_type_handlers = num_class.base_coercible_types.dup
410
410
  @conversions = num_class.base_conversions.dup
411
+ @angle = :rad # angular units: :rad (radians) / :deg (degrees) / :grad (gradians)
411
412
  end
412
413
  assign options.first
413
414
 
@@ -476,7 +477,7 @@ class Num < Numeric
476
477
  @num_class.int_div_radix_power(x,n)
477
478
  end
478
479
 
479
- attr_accessor :rounding, :emin, :emax, :flags, :traps, :ignored_flags, :capitals, :clamp
480
+ attr_accessor :rounding, :emin, :emax, :flags, :traps, :ignored_flags, :capitals, :clamp, :angle
480
481
 
481
482
  # TODO: consider the convenience of adding accessors of this kind:
482
483
  # def rounding(new_rounding=nil)
@@ -593,6 +594,7 @@ class Num < Numeric
593
594
  @capitals = options[:capitals ] unless options[:capitals ].nil?
594
595
  @clamp = options[:clamp ] unless options[:clamp ].nil?
595
596
  @exact = options[:exact ] unless options[:exact ].nil?
597
+ @angle = options[:angle ] unless options[:angle ].nil?
596
598
  update_precision
597
599
  end
598
600
  end
@@ -615,6 +617,7 @@ class Num < Numeric
615
617
  @exact = other.exact
616
618
  @coercible_type_handlers = other.coercible_type_handlers.dup
617
619
  @conversions = other.conversions.dup
620
+ @angle = other.angle
618
621
  end
619
622
 
620
623
  def dup
@@ -971,7 +974,7 @@ class Num < Numeric
971
974
  def inspect
972
975
  class_name = self.class.to_s.split('::').last
973
976
  "<#{class_name}:\n" +
974
- instance_variables.map { |v| " #{v}: #{eval(v).inspect}"}.join("\n") +
977
+ instance_variables.map { |v| " #{v}: #{instance_variable_get(v).inspect}"}.join("\n") +
975
978
  ">\n"
976
979
  end
977
980
 
@@ -4151,7 +4154,8 @@ class Num < Numeric
4151
4154
  :traps=>[DivisionByZero, Overflow, InvalidOperation],
4152
4155
  :ignored_flags=>[],
4153
4156
  :capitals=>true,
4154
- :clamp=>true
4157
+ :clamp=>true,
4158
+ :angle=>:rad
4155
4159
  )
4156
4160
 
4157
4161
  end
@@ -1,8 +1,8 @@
1
1
  module Flt
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 1
5
- TINY = 2
4
+ MINOR = 2
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,53 +1,59 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
- def exp(x,c=nil)
4
- i, lasts, s, fact, num = 0, 0, 1, 1, 1
5
- DecNum.local_context(c) do
6
- # result context
7
- DecNum.local_context do |context|
8
- # working context
9
- context.precision += 2
10
- context.rounding = DecNum::ROUND_HALF_EVEN
11
- while s != lasts
12
- lasts = s
13
- i += 1
14
- fact *= i
15
- num *= x
16
- s += num / fact
3
+ module TestFunctions
4
+
5
+ module_function
6
+
7
+ def exp(x,c=nil)
8
+
9
+ i, lasts, s, fact, num = 0, 0, 1, 1, 1
10
+ DecNum.local_context(c) do
11
+ # result context
12
+ DecNum.local_context do |context|
13
+ # working context
14
+ context.precision += 2
15
+ context.rounding = DecNum::ROUND_HALF_EVEN
16
+ while s != lasts
17
+ lasts = s
18
+ i += 1
19
+ fact *= i
20
+ num *= x
21
+ s += num / fact
22
+ end
17
23
  end
24
+ +s
18
25
  end
19
- +s
20
26
  end
21
- end
22
27
 
23
- def exp1(x, c=nil)
24
- return DecNum(BigDecimal("NaN")) if x.infinite? || x.nan?
25
- y = nil
26
- ext = 2
27
- DecNum.local_context(c) do |context|
28
- n = (context.precision += ext)
29
-
30
- one = DecNum("1")
31
- x1 = one
32
- y = one
33
- d = y
34
- z = one
35
- i = 0
36
- while d.nonzero? && ((m = n - (y.fractional_exponent - d.fractional_exponent).abs) > 0)
37
- m = ext if m < ext
38
- x1 *= x
39
- i += 1
40
- z *= i
41
-
42
- #d = x1.divide(z,:precision=>m)
43
- context.precision = m
44
- d = x1/z
45
- context.precision = n
46
-
47
- y += d
28
+ def exp1(x, c=nil)
29
+ return DecNum(BigDecimal("NaN")) if x.infinite? || x.nan?
30
+ y = nil
31
+ ext = 2
32
+ DecNum.local_context(c) do |context|
33
+ n = (context.precision += ext)
34
+
35
+ one = DecNum("1")
36
+ x1 = one
37
+ y = one
38
+ d = y
39
+ z = one
40
+ i = 0
41
+ while d.nonzero? && ((m = n - (y.fractional_exponent - d.fractional_exponent).abs) > 0)
42
+ m = ext if m < ext
43
+ x1 *= x
44
+ i += 1
45
+ z *= i
46
+
47
+ #d = x1.divide(z,:precision=>m)
48
+ context.precision = m
49
+ d = x1/z
50
+ context.precision = n
51
+
52
+ y += d
53
+ end
48
54
  end
55
+ return +y
49
56
  end
50
- return +y
51
57
  end
52
58
 
53
59
  def return_from_local_context
@@ -324,10 +330,10 @@ class TestBasic < Test::Unit::TestCase
324
330
  DecNum.context.precision = 100
325
331
  DecNum.context.rounding = :half_even
326
332
  e_100 = "2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427"
327
- assert_equal e_100, exp(DecNum(1)).to_s
328
- assert_equal DecNum(e_100), exp(DecNum(1))
329
- assert_equal e_100, exp1(DecNum(1)).to_s
330
- assert_equal DecNum(e_100), exp1(DecNum(1))
333
+ assert_equal e_100, TestFunctions.exp(DecNum(1)).to_s
334
+ assert_equal DecNum(e_100), TestFunctions.exp(DecNum(1))
335
+ assert_equal e_100, TestFunctions.exp1(DecNum(1)).to_s
336
+ assert_equal DecNum(e_100), TestFunctions.exp1(DecNum(1))
331
337
  end
332
338
 
333
339
  def test_special
@@ -23,7 +23,7 @@ class TestBin < Test::Unit::TestCase
23
23
  assert_equal 0.1, BinNum('0.1', :fixed)
24
24
 
25
25
  assert_equal Float::MAX, BinNum.context.maximum_finite
26
- assert_equal Float::MIN, BinNum.context.minimum_normal
26
+ assert_equal Float::MIN_N, BinNum.context.minimum_normal
27
27
 
28
28
  numbers = %w{
29
29
  0.123437
@@ -125,7 +125,8 @@ class TestBasic < Test::Unit::TestCase
125
125
 
126
126
  File.open(fn,'r') do |file|
127
127
  file.each_line do |line|
128
- next if line[0,2]=='--' || line.strip.empty?
128
+ line = line.split('--').first.strip if line.include?('--')
129
+ next if line.strip.empty?
129
130
 
130
131
  if line.include?(' -> ')
131
132
  # test
@@ -148,7 +149,7 @@ class TestBasic < Test::Unit::TestCase
148
149
  if funct
149
150
  # do test
150
151
  msg = " Test #{id}: #{funct}(#{valstemp.join(',')}) = #{ans}"
151
- File.open('dectests.txt','a'){|f| f.puts msg}
152
+ #File.open('dectests.txt','a'){|f| f.puts msg}
152
153
  expected = result = result_flags = nil
153
154
  DecNum.local_context do |context|
154
155
  context.flags.clear!
@@ -7,70 +7,101 @@ class TestTrig < Test::Unit::TestCase
7
7
 
8
8
 
9
9
  def setup
10
- @data12 = {}
11
- [:sin, :cos, :tan, :asin, :acos, :atan].each do |f|
12
- @data12[f] = File.read(File.join(File.dirname(__FILE__), "trigtest/#{f}12.txt")).split("\n").map do |line|
13
- line.split.map{|x| Flt::DecNum(x)}
10
+ @data = {}
11
+ Dir[File.join(File.dirname(__FILE__), "trigtest/*.txt")].each do |fn|
12
+ if File.basename(fn) =~ /\A([a-z]+)(\d+)_(\d+)_([a-z]+)\.txt\Z/
13
+ method = $1.to_sym
14
+ radix = $2.to_i
15
+ prec = $3.to_i
16
+ angle = $4.to_sym
17
+ @data[radix] ||= {}
18
+ @data[radix][angle] ||= {}
19
+ @data[radix][angle][prec] ||= {}
20
+ @data[radix][angle][prec][method] = File.read(fn).split("\n").map do |line|
21
+ line.split.map{|x| Flt::DecNum(x)}
22
+ end
14
23
  end
15
24
  end
16
25
  end
17
26
 
18
- def check(f)
19
- DecNum.context(:precision=>12) do
20
- data = @data12[f]
21
- data.each do |x, result|
22
- assert_equal result, DecNum::Math.send(f, x), "#{f}(#{x})==#{result}"
27
+ def check(f, radix=10, angle=:rad)
28
+ class_num = Num[radix]
29
+ @data[radix][angle].keys.each do |prec|
30
+ class_num.context(:precision=>prec, :angle=>angle) do
31
+ class_num.context.traps[DecNum::DivisionByZero] = false
32
+ data = @data[radix][angle][prec][f]
33
+ data.each do |x, result|
34
+ assert_equal result, class_num::Math.send(f, x), "#{f}(#{x})==#{result} [#{radix} #{angle} #{prec}]"
35
+ end
23
36
  end
24
37
  end
25
38
  end
26
39
 
27
- def check_relaxed(f, ulps=2)
28
- DecNum.context(:precision=>12) do
29
- data = @data12[f]
30
- data.each do |x, result|
31
- y = DecNum::Math.send(f, x)
32
- err_ulps = (y-result).abs/result.ulp
33
- assert err_ulps<=ulps, "#{f}(#{x})==#{result} to within #{ulps} ulps; error: #{err_ulps} ulps (#{y}) [#{DecNum.context.precision}]"
40
+ def check_relaxed(f, radix=10, angle=:rad, ulps=1)
41
+ class_num = Num[radix]
42
+ @data[radix][angle].keys.each do |prec|
43
+ class_num.context(:precision=>prec, :angle=>angle) do
44
+ class_num.context.traps[DecNum::DivisionByZero] = false
45
+ data = @data[radix][angle][prec][f]
46
+ data.each do |x, result|
47
+ y = class_num::Math.send(f, x)
48
+ if result.special?
49
+ assert_equal result, y, "#{f}(#{x})==#{result} [#{radix} #{angle} #{prec}]"
50
+ else
51
+ err_ulps = (y-result).abs/result.ulp
52
+ assert err_ulps<=ulps, "#{f}(#{x})==#{result} to within #{ulps} ulps; error: #{err_ulps} ulps (#{y}) [#{radix} #{angle} #{prec}]"
53
+ end
54
+ end
34
55
  end
35
56
  end
36
57
  end
37
58
 
38
-
39
- # def test_trig
40
- # DecNum.context(:precision=>12) do
41
- # @data12.keys.each do |f|
42
- # data = @data12[f]
43
- # data.each do |x, result|
44
- # assert_equal result, DecNum::Math.send(f, x), "#{f}(#{x})==#{result}"
45
- # end
46
- # end
47
- # end
48
- # end
49
-
50
- # separate tests per function
51
-
52
59
  def test_sin
53
- check_relaxed :sin
60
+ check :sin, 10, :rad
54
61
  end
55
62
 
56
63
  def test_cos
57
- check_relaxed :cos
64
+ check :cos, 10, :rad
58
65
  end
59
66
 
60
67
  def test_tan
61
- check_relaxed :tan
68
+ check_relaxed :tan, 10, :rad
62
69
  end
63
70
 
64
71
  def test_asin
65
- check_relaxed :asin
72
+ check_relaxed :asin, 10, :rad
66
73
  end
67
74
 
68
75
  def test_acos
69
- check_relaxed :acos
76
+ check_relaxed :acos, 10, :rad
70
77
  end
71
78
 
72
79
  def test_atan
73
- check_relaxed :atan
80
+ check_relaxed :atan, 10, :rad
81
+ end
82
+
83
+ def test_sin_deg
84
+ check_relaxed :sin, 10, :deg
85
+ end
86
+
87
+ def test_cos_deg
88
+ check_relaxed :cos, 10, :deg
89
+ end
90
+
91
+ def test_tan_deg
92
+ check_relaxed :tan, 10, :deg
93
+ end
94
+
95
+ def test_asin_deg
96
+ check_relaxed :asin, 10, :deg
97
+ end
98
+
99
+ def test_acos_deg
100
+ check_relaxed :acos, 10, :deg
101
+ end
102
+
103
+ def test_atan_deg
104
+ check_relaxed :atan, 10, :deg
74
105
  end
75
106
 
76
107
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flt
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
5
4
  prerelease: false
6
5
  segments:
7
6
  - 1
8
- - 1
9
7
  - 2
10
- version: 1.1.2
8
+ - 0
9
+ version: 1.2.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Javier Goizueta
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-06-01 00:00:00 +02:00
17
+ date: 2010-06-15 00:00:00 +02:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
@@ -26,7 +25,6 @@ dependencies:
26
25
  requirements:
27
26
  - - ">="
28
27
  - !ruby/object:Gem::Version
29
- hash: 9
30
28
  segments:
31
29
  - 2
32
30
  - 1
@@ -125,7 +123,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
123
  requirements:
126
124
  - - ">="
127
125
  - !ruby/object:Gem::Version
128
- hash: 3
129
126
  segments:
130
127
  - 0
131
128
  version: "0"
@@ -134,7 +131,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
131
  requirements:
135
132
  - - ">="
136
133
  - !ruby/object:Gem::Version
137
- hash: 3
138
134
  segments:
139
135
  - 0
140
136
  version: "0"