flt 1.1.2 → 1.2.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.
@@ -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"