nio 0.2.1 → 0.2.2

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,10 @@
1
+ == 0.2.2 2008-03-04
2
+
3
+ * Minor enhancements
4
+ - show_plus can be passed a string (e.g. ' ') that is used as the plus sign;
5
+ added new show_exp_plus to control the sign display of the exponent in
6
+ scientific notation.
7
+
1
8
  == 0.2.1 2007-12-15
2
9
 
3
10
  * Minor enhancements
@@ -1,20 +1,19 @@
1
1
  History.txt
2
2
  License.txt
3
3
  Manifest.txt
4
- README.txt
4
+ README.txt
5
5
  SOURCE.txt
6
6
  Rakefile
7
7
  config/hoe.rb
8
8
  config/requirements.rb
9
9
  lib/nio.rb
10
- lib/nio/version.rb
11
- lib/nio/repdec.rb
12
- lib/nio/flttol.rb
13
- lib/nio/tools.rb
14
- lib/nio/rtnlzr.rb
15
- lib/nio/fmt.rb
16
- lib/nio/sugar.rb
17
- log/debug.log
10
+ lib/nio/version.rb
11
+ lib/nio/repdec.rb
12
+ lib/nio/flttol.rb
13
+ lib/nio/tools.rb
14
+ lib/nio/rtnlzr.rb
15
+ lib/nio/fmt.rb
16
+ lib/nio/sugar.rb
18
17
  script/destroy
19
18
  script/destroy.cmd
20
19
  script/generate
@@ -23,12 +22,12 @@ script/txt2html
23
22
  script/txt2html.cmd
24
23
  setup.rb
25
24
  tasks/nuweb.rake
26
- tasks/deployment.rake
25
+ tasks/deployment.rake
27
26
  tasks/environment.rake
28
- tasks/website.rake
29
- test/data.yaml
27
+ tasks/website.rake
28
+ test/data.yaml
30
29
  test/test_helper.rb
31
- test/test_tools.rb
30
+ test/test_tools.rb
32
31
  test/test_repdec.rb
33
- test/test_rtnlzr.rb
34
- test/test_fmt.rb
32
+ test/test_rtnlzr.rb
33
+ test/test_fmt.rb
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
1
  require 'config/requirements'
2
2
  require 'config/hoe' # setup Hoe + all gem configuration
3
3
 
4
- Dir['tasks/**/*.rake'].each { |rake| load rake }
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -1,4 +1,4 @@
1
- require 'nio/version'
1
+ require File.join(File.dirname(__FILE__),'../source/lib/nio/version')
2
2
 
3
3
  AUTHOR = 'Javier Goizueta' # can also be an array of Authors
4
4
  EMAIL = "javier@goizueta.info"
@@ -8,6 +8,7 @@ RUBYFORGE_PROJECT = 'nio' # The unix name for your project
8
8
  HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
9
  DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
10
 
11
+ =begin
11
12
  @config_file = "C:/Documents and Settings/jgoizueta/.rubyforge/user-config.yml"
12
13
  @config = nil
13
14
  RUBYFORGE_USERNAME = "jgoizueta"
@@ -31,7 +32,6 @@ end
31
32
  REV = nil
32
33
  # UNCOMMENT IF REQUIRED:
33
34
  # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
- VERS = Nio::VERSION::STRING + (REV ? ".#{REV}" : "")
35
35
  RDOC_OPTS = ['--quiet', '--title', 'Nio documentation',
36
36
  "--opname", "index.html",
37
37
  "--line-numbers",
@@ -44,30 +44,32 @@ class Hoe
44
44
  @extra_deps
45
45
  end
46
46
  end
47
+ =end
47
48
 
48
49
  # Generate all the Rake tasks
49
50
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
- hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
- p.author = AUTHOR
51
+ $hoe = Hoe.new(GEM_NAME, Nio::VERSION::STRING) do |p|
52
+ p.developer AUTHOR, EMAIL
52
53
  p.description = DESCRIPTION
53
- p.email = EMAIL
54
54
  p.summary = DESCRIPTION
55
55
  p.url = HOMEPATH
56
56
  p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
57
57
  p.test_globs = ["test/**/test_*.rb"]
58
58
  p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
59
59
 
60
- # == Optional
60
+
61
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
62
+ #p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
63
+ p.remote_rdoc_dir = '' # we start using the rdoc as the project home-page, later we'll setup separate page
64
+ p.rsync_args = '-av --delete --ignore-errors'
61
65
  p.changes = p.paragraphs_of("History.txt", 0..1).join("\\n\\n")
66
+
62
67
  #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
63
68
 
64
- #p.spec_extras = {} # A hash of extra values to set in the gemspec.
65
-
69
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
70
+
66
71
  #p.spec_extras = { :autorequire=>'nio' }
67
72
 
68
73
  end
69
74
 
70
- CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
71
- PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
72
- #hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
73
- hoe.remote_rdoc_dir = '' # we start using the rdoc as the project home-page, later we'll setup separate page
75
+ require 'newgem/tasks' # load /tasks/*.rake
@@ -2,7 +2,7 @@ require 'fileutils'
2
2
  include FileUtils
3
3
 
4
4
  require 'rubygems'
5
- %w[rake hoe newgem rubigen].each do |req_gem|
5
+ %w[rubygems rake newgem rubigen].each do |req_gem|
6
6
  begin
7
7
  require req_gem
8
8
  rescue LoadError
@@ -14,4 +14,4 @@ end
14
14
 
15
15
  $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
16
 
17
- #require 'nio'
17
+ #require 'nio'
@@ -1,657 +1,657 @@
1
- # Floating point tolerance
2
- #--
3
- # Copyright (C) 2003-2005, Javier Goizueta <javier@goizueta.info>
4
- #
5
- # This program is free software; you can redistribute it and/or
6
- # modify it under the terms of the GNU General Public License
7
- # as published by the Free Software Foundation; either version 2
8
- # of the License, or (at your option) any later version.
9
- #++
10
- #
11
- # Author:: Javier Goizueta (mailto:javier@goizueta.info)
12
- # Copyright:: Copyright (c) 2002-2004 Javier Goizueta
13
- # License:: Distributes under the GPL license
14
- #
15
- # This module provides a numeric tolerance class for Float and BigDecimal.
16
-
17
- require 'bigdecimal'
18
- require 'bigdecimal/math' if ::VERSION>='1.8.1'
19
- require 'nio/tools'
20
-
21
-
22
- class Float
23
- unless const_defined?(:RADIX) # old Ruby versions didn't have this
24
- # Base of the Float representation
25
- RADIX = 2
26
-
27
- x = 1.0
28
- _bits_ = 0
29
- while 1!=x+1
30
- _bits_ += 1
31
- x /= 2
32
- end
33
- if ((1.0+2*x)-1.0)>2*x
34
- _bits_ -= 1
35
- end
36
-
37
- # Number of RADIX-base digits of precision in a Float
38
- MANT_DIG = _bits_
39
- # Number of decimal digits that can be stored in a Float and recovered
40
- DIG = ((MANT_DIG-1)*Math.log(RADIX)/Math.log(10)).floor
41
- # Smallest value that added to 1.0 produces something different from 1.0
42
- EPSILON = Math.ldexp(*Math.frexp(1).collect{|e| e.kind_of?(Integer) ? e-(MANT_DIG-1) : e})
43
- end
44
- # Decimal precision required to represent a Float and be able to recover its value
45
- DECIMAL_DIG = (MANT_DIG*Math.log(RADIX)/Math.log(10)).ceil+1
46
- end
47
-
48
- # :stopdoc:
49
- # A problem has been detected with Float#to_i() in some Ruby versiones
50
- # (it has been found in Ruby 1.8.4 compiled for x86_64_linux|)
51
- # This problem makes to_i produce an incorrect sign on some cases.
52
- # Here we try to detect the problem and apply a quick patch,
53
- # although this will slow down the method.
54
- if 4.611686018427388e+018.to_i < 0
55
- class Float
56
- alias _to_i to_i
57
- def to_i
58
- neg = (self < 0)
59
- i = _to_i
60
- i_neg = (i < 0)
61
- i = -i if neg != i_neg
62
- i
63
- end
64
- end
65
- end
66
- # :startdoc:
67
-
68
-
69
- # This module contains some constructor-like module functions
70
- # to help with the creation of tolerances and big-decimals.
71
- #
72
- # =BigDec
73
- # BigDec(x) -> a BigDecimal
74
- # BigDec(x,precision) -> a BigDecimal
75
- # BigDec(x,:exact) -> a BigDecimal
76
- # This is a shortcut to define a BigDecimal without using quotes
77
- # and a general conversion to BigDecimal method.
78
- #
79
- # The second parameter can be :exact to try for an exact conversion
80
- #
81
- # Conversions from Float have issues that should be understood; :exact
82
- # conversion will use the exact internal value of the Float, and when
83
- # no precision is specified, a value as simple as possible expressed as
84
- # a fraction will be used.
85
- #
86
- # =Tol
87
- # Tol(x) -> a Tolerance
88
- # This module function will convert its argument to a Noi::Tolerance
89
- # or a Noi::BigTolerance depending on its argument;
90
- #
91
- # Values of type Tolerance,Float,Integer (for Tolerance) or
92
- # BigTolerance,BigDecimal (for BigTolerance) are accepted.
93
- #
94
- # =BigTol
95
- # BigTol(x) -> a BigTolerance
96
- # This module function will convert its argument to a Noi::BigTolerance
97
- #
98
- # Values of type BigTolerance or Numeric are accepted.
99
- module Nio
100
-
101
- # This class represents floating point tolerances for Float numbers
102
- # and allows comparison within the specified tolerance.
103
- class Tolerance
104
- include StateEquivalent
105
-
106
- # The numeric class this tolerance applies to.
107
- def num_class
108
- Float
109
- end
110
-
111
- # The tolerance mode is either :abs (absolute) :rel (relative) or :sig (significant).
112
- # The last parameter is a flag to specify decimal mode for the :sig mode
113
- def initialize(t=0.0, mode=:abs, decmode=false)
114
- set t, mode, decmode
115
- end
116
-
117
-
118
- #This initializes a Tolerance with a given number of decimals
119
- def decimals(d, mode=:abs, rounded=true)
120
-
121
- @mode = mode
122
- @decimal_mode = true
123
- @d = (d<=0 || d>Float::DIG) ? Float::DIG : d
124
- @t = 10**(-@d)
125
- @t *= 0.5 if rounded
126
-
127
- self
128
- end
129
-
130
- #This initializes a Tolerance with a number of significant decimal digits
131
- def sig_decimals(d, rounded=true)
132
- decimals d, :sig, rounded
133
- end
134
-
135
- #Initialize with a multiple of the internal floating-point precision.
136
- def epsilon(times_epsilon=1, mode=:sig)
137
- set Float::EPSILON*times_epsilon, mode
138
- end
139
-
140
- # As #epsilon but using a somewhat bigger (about twice) precision that
141
- # assures associative multiplication.
142
- def big_epsilon(n=1, mode=:sig)
143
- t = Math.ldexp(0.5*n,3-Float::MANT_DIG) # n*(2*Float::EPSILON/(1-0.5*Float::EPSILON)**2)
144
- set t, mode
145
- end
146
-
147
- # Initialize with a relative fraction
148
- def fraction(f)
149
- set f, :rel
150
- end
151
- # Initialize with a percentage
152
- def percent(x)
153
- fraction x/100.0
154
- end
155
- # Initialize with a per-mille value
156
- def permille(x)
157
- fraction x/1000.0
158
- end
159
-
160
-
161
- #Shortcut notation for get_value
162
- def [](x)
163
- return x.nil? ? @t : get_value(x)
164
- end
165
- #Return tolerance relative to a magnitude
166
- def get_value(x)
167
- rel(x)
168
- end
169
- #Essential equality within tolerance
170
- def equals?(x,y)
171
-
172
- case @mode
173
- when :sig
174
-
175
- if @decimal_mode
176
- begin
177
- x_exp = Math.log10(x.abs)
178
- #x_exp = x_exp.finite? ? x_exp.ceil : 0
179
- x_exp = x_exp.finite? ? x_exp.floor+1 : 0
180
- rescue
181
- x_exp = 0
182
- end
183
- begin
184
- y_exp = Math.log10(y.abs)
185
- #y_exp = y_exp.finite? ? y_exp.ceil : 0
186
- y_exp = y_exp.finite? ? y_exp.floor+1 : 0
187
- rescue
188
- y_exp = 0
189
- end
190
- (y-x).abs <= @t*(10**([x_exp,y_exp].min-@@dec_ref_exp))
191
- else
192
- z,x_exp = Math.frexp(x)
193
- z,y_exp = Math.frexp(y)
194
- (y-x).abs <= Math.ldexp(@t,[x_exp,y_exp].min-@@ref_exp) # (y-x).abs <= @t*(2**([x_exp,y_exp].min-@@ref_exp))
195
- end
196
-
197
- when :rel
198
-
199
- (y-x).abs <= @t*([x.abs,y.abs].min) #reference value is 1
200
-
201
- when :abs
202
- (x-y).abs<@t
203
- end
204
-
205
- end
206
- #Approximate equality within tolerance
207
- def aprx_equals?(x,y)
208
-
209
- case @mode
210
- when :sig
211
-
212
- if @decimal_mode
213
- begin
214
- x_exp = Math.log10(x.abs)
215
- #x_exp = x_exp.finite? ? x_exp.ceil : 0
216
- x_exp = x_exp.finite? ? x_exp.floor+1 : 0
217
- rescue
218
- x_exp = 0
219
- end
220
- begin
221
- y_exp = Math.log10(y.abs)
222
- #y_exp = y_exp.finite? ? y_exp.ceil : 0
223
- y_exp = y_exp.finite? ? y_exp.floor+1 : 0
224
- rescue
225
- y_exp = 0
226
- end
227
- (y-x).abs <= @t*(10**([x_exp,y_exp].max-@@dec_ref_exp))
228
- else
229
- z,x_exp = Math.frexp(x)
230
- z,y_exp = Math.frexp(y)
231
- (y-x).abs <= Math.ldexp(@t,[x_exp,y_exp].max-@@ref_exp) # (y-x).abs <= @t*(2**([x_exp,y_exp].max-@@ref_exp))
232
- end
233
-
234
- when :rel
235
-
236
- (y-x).abs <= @t*([x.abs,y.abs].max) #reference value is 1
237
-
238
- when :abs
239
- (x-y).abs<=@t
240
- end
241
-
242
- end
243
- #Comparison within tolerance
244
- def greater_than?(x,y)
245
- less_than?(y,x)
246
- end
247
- #Comparison within tolerance
248
- def less_than?(x,y)
249
-
250
- case @mode
251
- when :sig
252
-
253
- if @decimal_mode
254
- begin
255
- x_exp = Math.log10(x.abs)
256
- #x_exp = x_exp.finite? ? x_exp.ceil : 0
257
- x_exp = x_exp.finite? ? x_exp.floor+1 : 0
258
- rescue
259
- x_exp = 0
260
- end
261
- begin
262
- y_exp = Math.log10(y.abs)
263
- #y_exp = y_exp.finite? ? y_exp.ceil : 0
264
- y_exp = y_exp.finite? ? y_exp.floor+1 : 0
265
- rescue
266
- y_exp = 0
267
- end
268
- y-x > @t*(10**([x_exp,y_exp].max-@@dec_ref_exp))
269
- else
270
- z,x_exp = Math.frexp(x)
271
- z,y_exp = Math.frexp(y)
272
- y-x > Math.ldexp(@t,[x_exp,y_exp].max-@@ref_exp) # y-x > @t*(2**([x_exp,y_exp].max-@@ref_exp))
273
- end
274
-
275
- when :rel
276
-
277
- y-x > @t*([x.abs,y.abs].max) #reference value is 1
278
-
279
- when :abs
280
- x-y<@t
281
- end
282
-
283
- end
284
- #Comparison within tolerance
285
- def zero?(x,compared_with=nil)
286
- compared_with.nil? ? x.abs<@t : x.abs<rel(compared_with)
287
- end
288
-
289
-
290
- # Returns true if the argument is approximately an integer
291
- def apprx_i?(x)
292
- equals?(x,x.round)
293
- end
294
- # If the argument is close to an integer it rounds it
295
- # and returns it as an object of the specified class (by default, Integer)
296
- def apprx_i(x,result=Integer)
297
- r = x.round
298
- return equals?(x,r) ? r.prec(result) : x
299
- end
300
-
301
-
302
- # Returns the magnitude of the tolerance
303
- def magnitude
304
- @t
305
- end
306
- # Returns the number of decimal digits of the tolerance
307
- def num_decimals
308
- @d
309
- end
310
- # Returns true for decimal-mode tolerance
311
- def decimal?
312
- @decimal_mode
313
- end
314
- # Returns the mode (:abs, :rel, :sig) of the tolerance
315
- def mode
316
- @mode
317
- end
318
-
319
-
320
- private
321
-
322
- def set(t=0.0, mode=:abs, decmode=false)
323
-
324
- @t = t==0 ? Float::EPSILON : t.abs
325
- @t = 0.5 if @t > 0.5
326
- @mode = mode
327
- @t = Float::EPSILON if @mode!=:abs && @t<Float::EPSILON
328
- @decimal_mode = decmode
329
- @d = @t==0 ? 0 : (-Math.log10(2*@t).floor).to_i
330
-
331
- self
332
- end
333
-
334
- @@ref_exp = 1 # Math.frexp(1)[1] => tol. relative to [1,2)
335
-
336
- @@dec_ref_exp = 0 # tol. relative to [0.1,1)
337
-
338
- def rel(x)
339
- r = @t
340
- case @mode
341
- when :sig
342
- if @decimal_mode
343
- d = x==0 ? 0 : (Math.log10(x.abs).floor+1).to_i
344
- r = @t*(10**(d-@@dec_ref_exp))
345
- else
346
- x,exp = Math.frexp(x)
347
- r = Math.ldexp(@t,exp-@@ref_exp)
348
- end
349
- when :rel
350
- r = @t*x.abs
351
- end
352
- r
353
- end
354
-
355
- end
356
-
357
- def Tolerance.decimals(d=0, mode=:abs,rounded=true)
358
- Tolerance.new.decimals(d,mode,rounded)
359
- end
360
- def Tolerance.sig_decimals(d=0, mode=:abs,rounded=true)
361
- Tolerance.new.sig_decimals(d,rounded)
362
- end
363
- def Tolerance.epsilon(n=1, mode=:sig)
364
- Tolerance.new.epsilon(n, mode)
365
- end
366
- def Tolerance.big_epsilon(n=1, mode=:sig)
367
- Tolerance.new.big_epsilon(n, mode)
368
- end
369
- def Tolerance.fraction(f)
370
- Tolerance.new.fraction(f)
371
- end
372
- def Tolerance.percent(p)
373
- Tolerance.new.percent(p)
374
- end
375
- def Tolerance.permille(p)
376
- Tolerance.new.permille(p)
377
- end
378
-
379
- # This class represents floating point tolerances for BigDecimal numbers
380
- # and allows comparison within the specified tolerance.
381
- class BigTolerance
382
- include StateEquivalent
383
- module BgMth # :nodoc:
384
- extend BigMath if ::RUBY_VERSION>='1.8.1'
385
- end
386
-
387
- # The numeric class this tolerance applies to.
388
- def num_class
389
- BigDecimal
390
- end
391
-
392
- #The tolerance mode is either :abs (absolute) :rel (relative) or :sig
393
- def initialize(t=BigDecimal('0'), mode=:abs, decmode=false)
394
- set t, mode, decmode
395
- end
396
-
397
-
398
- #This initializes a BigTolerance with a given number of decimals
399
- def decimals(d, mode=:abs, rounded=true)
400
-
401
- @mode = mode
402
- @decimal_mode = true
403
- @d = d==0 ? 16 : d
404
- if rounded
405
- @t = BigDecimal("0.5E#{-d}") # HALF*(BigDecimal(10)**(-d))
406
- else
407
- @t = BigDecimal("1E#{-d}") # BigDecimal(10)**(-d)
408
- end
409
- @ref_exp = BigDecimal('0.1').exponent # reference for significative mode: [0.1,1)
410
-
411
- self
412
- end
413
-
414
- #This initializes a BigTolerance with a number of significative decimal digits
415
- def sig_decimals(d, rounded=true)
416
- decimals d, :sig, rounded
417
- end
418
-
419
- def fraction(f)
420
- set f, :rel
421
- end
422
- def percent(x)
423
- fraction x*BigDecimal('0.01')
424
- end
425
- def permille(x)
426
- fraction x*BigDecimal('0.001')
427
- end
428
-
429
-
430
- #Shortcut notation for get_value
431
- def [](x)
432
- return x.nil? ? @t : get_value(x)
433
- end
434
- #Return tolerance relative to a magnitude
435
- def get_value(x)
436
- rel(x)
437
- end
438
- #Essential equality within tolerance
439
- def equals?(x,y)
440
-
441
- case @mode
442
- when :sig
443
-
444
- x_exp = x.exponent
445
- y_exp = y.exponent
446
- (y-x).abs <= @t*BigDecimal("1E#{[x_exp,y_exp].min-@ref_exp}")
447
-
448
- when :rel
449
-
450
- (y-x).abs <= @t*([x.abs,y.abs].min) #reference value is 1
451
-
452
- when :abs
453
- (x-y).abs<@t
454
- end
455
-
456
- end
457
- #Approximate equality within tolerance
458
- def aprx_equals?(x,y)
459
-
460
- case @mode
461
- when :sig
462
-
463
- x_exp = x.exponent
464
- y_exp = y.exponent
465
- (y-x).abs <= @t*BigDecimal("1E#{[x_exp,y_exp].max-@ref_exp}")
466
-
467
- when :rel
468
-
469
- (y-x).abs <= @t*([x.abs,y.abs].max) #reference value is 1
470
-
471
- when :abs
472
- (x-y).abs<=@t
473
- end
474
-
475
- end
476
- #Comparison within tolerance
477
- def greater_than?(x,y)
478
- less_than?(y,x)
479
- end
480
- #Comparison within tolerance
481
- def less_than?(x,y)
482
-
483
- case @mode
484
- when :sig
485
-
486
- x_exp = x.exponent
487
- y_exp = y.exponent
488
- y-x > @t*BigDecimal("1E#{[x_exp,y_exp].max-@ref_exp}")
489
-
490
- when :rel
491
-
492
- y-x > @t*([x.abs,y.abs].max) #reference value is 1
493
-
494
- when :abs
495
- x-y<@t
496
- end
497
-
498
- end
499
- #Comparison within tolerance
500
- def zero?(x,compared_with=nil)
501
- compared_with.nil? ? x.abs<@t : x.abs<rel(compared_with)
502
- end
503
-
504
-
505
- # Returns true if the argument is approximately an integer
506
- def apprx_i?(x)
507
- equals?(x,x.round)
508
- end
509
- # If the argument is close to an integer it rounds it
510
- # and returns it as an object of the specified class (by default, Integer)
511
- def apprx_i(x,result=Integer)
512
- r = x.round
513
- return equals?(x,r) ? r.prec(result) : x
514
- end
515
-
516
-
517
- # Returns the magnitude of the tolerance
518
- def magnitude
519
- @t
520
- end
521
- # Returns the number of decimal digits of the tolerance
522
- def num_decimals
523
- @d
524
- end
525
- # Returns true for decimal-mode tolerance
526
- def decimal?
527
- @decimal_mode
528
- end
529
- # Returns the mode (:abs, :rel, :sig) of the tolerance
530
- def mode
531
- @mode
532
- end
533
-
534
-
535
- private
536
-
537
- HALF = BigDecimal('0.5')
538
-
539
- def set(t=BigDecimal('0'), mode=:abs, decmode=false)
540
-
541
- @t = t
542
- @t = HALF if @t > HALF
543
- raise TypeError,"El valor de tolerancia debe ser de tipo BigDecimal" if @t.class!=BigDecimal
544
- @mode = mode
545
- @decimal_mode = decmode
546
- @d = @t.zero? ? 0 : -(@t*2).exponent+1
547
- @ref_exp = BigDecimal('1').exponent # reference for significative mode: [1,10)
548
-
549
- self
550
- end
551
-
552
- def rel(x)
553
- r = @t
554
- case @mode
555
- when :sig
556
- d = x==0 ? 0 : x.exponent
557
- r = @t*BigDecimal("1E#{d-@ref_exp}")
558
- when :rel
559
- r = @t*x.abs
560
- end
561
- r
562
- end
563
-
564
- end
565
-
566
- def BigTolerance.decimals(d=0, mode=:abs)
567
- BigTolerance.new.decimals(d,mode)
568
- end
569
- def BigTolerance.sig_decimals(d=0, mode=:abs)
570
- BigTolerance.new.sig_decimals(d)
571
- end
572
- def BigTolerance.fraction(f)
573
- BigTolerance.new.fraction(f)
574
- end
575
- def BigTolerance.percent(p)
576
- BigTolerance.new.percent(p)
577
- end
578
- def BigTolerance.permille(p)
579
- BigTolerance.new.permille(p)
580
- end
581
-
582
- module_function
583
-
584
- # Tol(x) -> a Tolerance
585
- # This module function will convert its argument to a Noi::Tolerance
586
- # or a Noi::BigTolerance depending on its argument;
587
- #
588
- # Values of type Tolerance,Float,Integer (for Tolerance) or
589
- # BigTolerance,BigDecimal (for BigTolerance) are accepted.
590
- def Tol(x) # :doc:
591
- case x
592
- when Tolerance
593
- x
594
- when BigTolerance
595
- x
596
- when BigDecimal
597
- BigTolerance.new(x)
598
- when Float
599
- Tolerance.new(x)
600
- when Integer
601
- Tolerance.sig_decimals(x)
602
- else # e.g. Rational
603
- x
604
- end
605
- end
606
-
607
- # BigTol(x) -> a BigTolerance
608
- # This module function will convert its argument to a Noi::BigTolerance
609
- #
610
- # Values of type BigTolerance or Numeric are accepted.
611
- def BigTol(x) # :doc:
612
- case x
613
- when BigTolerance
614
- x
615
- when Integer
616
- BigTolerance.sig_decimals(x)
617
- when Rational
618
- x
619
- else
620
- BigTolerance.new(BigDec(x))
621
- end
622
- end
623
-
624
- # BigDec(x) -> a BigDecimal
625
- # BigDec(x,precision) -> a BigDecimal
626
- # BigDec(x,:exact) -> a BigDecimal
627
- # This is a shortcut to define a BigDecimal without using quotes
628
- # and a general conversion to BigDecimal method.
629
- #
630
- # The second parameter can be :exact to try for an exact conversion
631
- #
632
- # Conversions from Float have issues that should be understood; :exact
633
- # conversion will use the exact internal value of the Float, and when
634
- # no precision is specified, a value as simple as possible expressed as
635
- # a fraction will be used.
636
- def BigDec(x,prec=nil) # :doc:
637
- if x.respond_to?(:to_str)
638
- x = BigDecimal(x.to_str, prec||0)
639
- else
640
- case x
641
- when Integer
642
- x = BigDecimal(x.to_s)
643
- when Rational
644
- if prec && prec!=:exact
645
- x = BigDecimal.new(x.numerator.to_s).div(x.denominator,prec)
646
- else
647
- x = BigDecimal.new(x.numerator.to_s)/BigDecimal.new(x.denominator.to_s)
648
- end
649
- when BigDecimal
650
- when Float
651
- x = nio_float_to_bigdecimal(x,prec)
652
- end
653
- end
654
- x
655
- end
656
-
657
- end
1
+ # Floating point tolerance
2
+ #--
3
+ # Copyright (C) 2003-2005, Javier Goizueta <javier@goizueta.info>
4
+ #
5
+ # This program is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU General Public License
7
+ # as published by the Free Software Foundation; either version 2
8
+ # of the License, or (at your option) any later version.
9
+ #++
10
+ #
11
+ # Author:: Javier Goizueta (mailto:javier@goizueta.info)
12
+ # Copyright:: Copyright (c) 2002-2004 Javier Goizueta
13
+ # License:: Distributes under the GPL license
14
+ #
15
+ # This module provides a numeric tolerance class for Float and BigDecimal.
16
+
17
+ require 'bigdecimal'
18
+ require 'bigdecimal/math' if RUBY_VERSION>='1.8.1'
19
+ require 'nio/tools'
20
+
21
+
22
+ class Float
23
+ unless const_defined?(:RADIX) # old Ruby versions didn't have this
24
+ # Base of the Float representation
25
+ RADIX = 2
26
+
27
+ x = 1.0
28
+ _bits_ = 0
29
+ while 1!=x+1
30
+ _bits_ += 1
31
+ x /= 2
32
+ end
33
+ if ((1.0+2*x)-1.0)>2*x
34
+ _bits_ -= 1
35
+ end
36
+
37
+ # Number of RADIX-base digits of precision in a Float
38
+ MANT_DIG = _bits_
39
+ # Number of decimal digits that can be stored in a Float and recovered
40
+ DIG = ((MANT_DIG-1)*Math.log(RADIX)/Math.log(10)).floor
41
+ # Smallest value that added to 1.0 produces something different from 1.0
42
+ EPSILON = Math.ldexp(*Math.frexp(1).collect{|e| e.kind_of?(Integer) ? e-(MANT_DIG-1) : e})
43
+ end
44
+ # Decimal precision required to represent a Float and be able to recover its value
45
+ DECIMAL_DIG = (MANT_DIG*Math.log(RADIX)/Math.log(10)).ceil+1
46
+ end
47
+
48
+ # :stopdoc:
49
+ # A problem has been detected with Float#to_i() in some Ruby versiones
50
+ # (it has been found in Ruby 1.8.4 compiled for x86_64_linux|)
51
+ # This problem makes to_i produce an incorrect sign on some cases.
52
+ # Here we try to detect the problem and apply a quick patch,
53
+ # although this will slow down the method.
54
+ if 4.611686018427388e+018.to_i < 0
55
+ class Float
56
+ alias _to_i to_i
57
+ def to_i
58
+ neg = (self < 0)
59
+ i = _to_i
60
+ i_neg = (i < 0)
61
+ i = -i if neg != i_neg
62
+ i
63
+ end
64
+ end
65
+ end
66
+ # :startdoc:
67
+
68
+
69
+ # This module contains some constructor-like module functions
70
+ # to help with the creation of tolerances and big-decimals.
71
+ #
72
+ # =BigDec
73
+ # BigDec(x) -> a BigDecimal
74
+ # BigDec(x,precision) -> a BigDecimal
75
+ # BigDec(x,:exact) -> a BigDecimal
76
+ # This is a shortcut to define a BigDecimal without using quotes
77
+ # and a general conversion to BigDecimal method.
78
+ #
79
+ # The second parameter can be :exact to try for an exact conversion
80
+ #
81
+ # Conversions from Float have issues that should be understood; :exact
82
+ # conversion will use the exact internal value of the Float, and when
83
+ # no precision is specified, a value as simple as possible expressed as
84
+ # a fraction will be used.
85
+ #
86
+ # =Tol
87
+ # Tol(x) -> a Tolerance
88
+ # This module function will convert its argument to a Noi::Tolerance
89
+ # or a Noi::BigTolerance depending on its argument;
90
+ #
91
+ # Values of type Tolerance,Float,Integer (for Tolerance) or
92
+ # BigTolerance,BigDecimal (for BigTolerance) are accepted.
93
+ #
94
+ # =BigTol
95
+ # BigTol(x) -> a BigTolerance
96
+ # This module function will convert its argument to a Noi::BigTolerance
97
+ #
98
+ # Values of type BigTolerance or Numeric are accepted.
99
+ module Nio
100
+
101
+ # This class represents floating point tolerances for Float numbers
102
+ # and allows comparison within the specified tolerance.
103
+ class Tolerance
104
+ include StateEquivalent
105
+
106
+ # The numeric class this tolerance applies to.
107
+ def num_class
108
+ Float
109
+ end
110
+
111
+ # The tolerance mode is either :abs (absolute) :rel (relative) or :sig (significant).
112
+ # The last parameter is a flag to specify decimal mode for the :sig mode
113
+ def initialize(t=0.0, mode=:abs, decmode=false)
114
+ set t, mode, decmode
115
+ end
116
+
117
+
118
+ #This initializes a Tolerance with a given number of decimals
119
+ def decimals(d, mode=:abs, rounded=true)
120
+
121
+ @mode = mode
122
+ @decimal_mode = true
123
+ @d = (d<=0 || d>Float::DIG) ? Float::DIG : d
124
+ @t = 10**(-@d)
125
+ @t *= 0.5 if rounded
126
+
127
+ self
128
+ end
129
+
130
+ #This initializes a Tolerance with a number of significant decimal digits
131
+ def sig_decimals(d, rounded=true)
132
+ decimals d, :sig, rounded
133
+ end
134
+
135
+ #Initialize with a multiple of the internal floating-point precision.
136
+ def epsilon(times_epsilon=1, mode=:sig)
137
+ set Float::EPSILON*times_epsilon, mode
138
+ end
139
+
140
+ # As #epsilon but using a somewhat bigger (about twice) precision that
141
+ # assures associative multiplication.
142
+ def big_epsilon(n=1, mode=:sig)
143
+ t = Math.ldexp(0.5*n,3-Float::MANT_DIG) # n*(2*Float::EPSILON/(1-0.5*Float::EPSILON)**2)
144
+ set t, mode
145
+ end
146
+
147
+ # Initialize with a relative fraction
148
+ def fraction(f)
149
+ set f, :rel
150
+ end
151
+ # Initialize with a percentage
152
+ def percent(x)
153
+ fraction x/100.0
154
+ end
155
+ # Initialize with a per-mille value
156
+ def permille(x)
157
+ fraction x/1000.0
158
+ end
159
+
160
+
161
+ #Shortcut notation for get_value
162
+ def [](x)
163
+ return x.nil? ? @t : get_value(x)
164
+ end
165
+ #Return tolerance relative to a magnitude
166
+ def get_value(x)
167
+ rel(x)
168
+ end
169
+ #Essential equality within tolerance
170
+ def equals?(x,y)
171
+
172
+ case @mode
173
+ when :sig
174
+
175
+ if @decimal_mode
176
+ begin
177
+ x_exp = Math.log10(x.abs)
178
+ #x_exp = x_exp.finite? ? x_exp.ceil : 0
179
+ x_exp = x_exp.finite? ? x_exp.floor+1 : 0
180
+ rescue
181
+ x_exp = 0
182
+ end
183
+ begin
184
+ y_exp = Math.log10(y.abs)
185
+ #y_exp = y_exp.finite? ? y_exp.ceil : 0
186
+ y_exp = y_exp.finite? ? y_exp.floor+1 : 0
187
+ rescue
188
+ y_exp = 0
189
+ end
190
+ (y-x).abs <= @t*(10**([x_exp,y_exp].min-@@dec_ref_exp))
191
+ else
192
+ z,x_exp = Math.frexp(x)
193
+ z,y_exp = Math.frexp(y)
194
+ (y-x).abs <= Math.ldexp(@t,[x_exp,y_exp].min-@@ref_exp) # (y-x).abs <= @t*(2**([x_exp,y_exp].min-@@ref_exp))
195
+ end
196
+
197
+ when :rel
198
+
199
+ (y-x).abs <= @t*([x.abs,y.abs].min) #reference value is 1
200
+
201
+ when :abs
202
+ (x-y).abs<@t
203
+ end
204
+
205
+ end
206
+ #Approximate equality within tolerance
207
+ def aprx_equals?(x,y)
208
+
209
+ case @mode
210
+ when :sig
211
+
212
+ if @decimal_mode
213
+ begin
214
+ x_exp = Math.log10(x.abs)
215
+ #x_exp = x_exp.finite? ? x_exp.ceil : 0
216
+ x_exp = x_exp.finite? ? x_exp.floor+1 : 0
217
+ rescue
218
+ x_exp = 0
219
+ end
220
+ begin
221
+ y_exp = Math.log10(y.abs)
222
+ #y_exp = y_exp.finite? ? y_exp.ceil : 0
223
+ y_exp = y_exp.finite? ? y_exp.floor+1 : 0
224
+ rescue
225
+ y_exp = 0
226
+ end
227
+ (y-x).abs <= @t*(10**([x_exp,y_exp].max-@@dec_ref_exp))
228
+ else
229
+ z,x_exp = Math.frexp(x)
230
+ z,y_exp = Math.frexp(y)
231
+ (y-x).abs <= Math.ldexp(@t,[x_exp,y_exp].max-@@ref_exp) # (y-x).abs <= @t*(2**([x_exp,y_exp].max-@@ref_exp))
232
+ end
233
+
234
+ when :rel
235
+
236
+ (y-x).abs <= @t*([x.abs,y.abs].max) #reference value is 1
237
+
238
+ when :abs
239
+ (x-y).abs<=@t
240
+ end
241
+
242
+ end
243
+ #Comparison within tolerance
244
+ def greater_than?(x,y)
245
+ less_than?(y,x)
246
+ end
247
+ #Comparison within tolerance
248
+ def less_than?(x,y)
249
+
250
+ case @mode
251
+ when :sig
252
+
253
+ if @decimal_mode
254
+ begin
255
+ x_exp = Math.log10(x.abs)
256
+ #x_exp = x_exp.finite? ? x_exp.ceil : 0
257
+ x_exp = x_exp.finite? ? x_exp.floor+1 : 0
258
+ rescue
259
+ x_exp = 0
260
+ end
261
+ begin
262
+ y_exp = Math.log10(y.abs)
263
+ #y_exp = y_exp.finite? ? y_exp.ceil : 0
264
+ y_exp = y_exp.finite? ? y_exp.floor+1 : 0
265
+ rescue
266
+ y_exp = 0
267
+ end
268
+ y-x > @t*(10**([x_exp,y_exp].max-@@dec_ref_exp))
269
+ else
270
+ z,x_exp = Math.frexp(x)
271
+ z,y_exp = Math.frexp(y)
272
+ y-x > Math.ldexp(@t,[x_exp,y_exp].max-@@ref_exp) # y-x > @t*(2**([x_exp,y_exp].max-@@ref_exp))
273
+ end
274
+
275
+ when :rel
276
+
277
+ y-x > @t*([x.abs,y.abs].max) #reference value is 1
278
+
279
+ when :abs
280
+ x-y<@t
281
+ end
282
+
283
+ end
284
+ #Comparison within tolerance
285
+ def zero?(x,compared_with=nil)
286
+ compared_with.nil? ? x.abs<@t : x.abs<rel(compared_with)
287
+ end
288
+
289
+
290
+ # Returns true if the argument is approximately an integer
291
+ def apprx_i?(x)
292
+ equals?(x,x.round)
293
+ end
294
+ # If the argument is close to an integer it rounds it
295
+ # and returns it as an object of the specified class (by default, Integer)
296
+ def apprx_i(x,result=Integer)
297
+ r = x.round
298
+ return equals?(x,r) ? r.prec(result) : x
299
+ end
300
+
301
+
302
+ # Returns the magnitude of the tolerance
303
+ def magnitude
304
+ @t
305
+ end
306
+ # Returns the number of decimal digits of the tolerance
307
+ def num_decimals
308
+ @d
309
+ end
310
+ # Returns true for decimal-mode tolerance
311
+ def decimal?
312
+ @decimal_mode
313
+ end
314
+ # Returns the mode (:abs, :rel, :sig) of the tolerance
315
+ def mode
316
+ @mode
317
+ end
318
+
319
+
320
+ private
321
+
322
+ def set(t=0.0, mode=:abs, decmode=false)
323
+
324
+ @t = t==0 ? Float::EPSILON : t.abs
325
+ @t = 0.5 if @t > 0.5
326
+ @mode = mode
327
+ @t = Float::EPSILON if @mode!=:abs && @t<Float::EPSILON
328
+ @decimal_mode = decmode
329
+ @d = @t==0 ? 0 : (-Math.log10(2*@t).floor).to_i
330
+
331
+ self
332
+ end
333
+
334
+ @@ref_exp = 1 # Math.frexp(1)[1] => tol. relative to [1,2)
335
+
336
+ @@dec_ref_exp = 0 # tol. relative to [0.1,1)
337
+
338
+ def rel(x)
339
+ r = @t
340
+ case @mode
341
+ when :sig
342
+ if @decimal_mode
343
+ d = x==0 ? 0 : (Math.log10(x.abs).floor+1).to_i
344
+ r = @t*(10**(d-@@dec_ref_exp))
345
+ else
346
+ x,exp = Math.frexp(x)
347
+ r = Math.ldexp(@t,exp-@@ref_exp)
348
+ end
349
+ when :rel
350
+ r = @t*x.abs
351
+ end
352
+ r
353
+ end
354
+
355
+ end
356
+
357
+ def Tolerance.decimals(d=0, mode=:abs,rounded=true)
358
+ Tolerance.new.decimals(d,mode,rounded)
359
+ end
360
+ def Tolerance.sig_decimals(d=0, mode=:abs,rounded=true)
361
+ Tolerance.new.sig_decimals(d,rounded)
362
+ end
363
+ def Tolerance.epsilon(n=1, mode=:sig)
364
+ Tolerance.new.epsilon(n, mode)
365
+ end
366
+ def Tolerance.big_epsilon(n=1, mode=:sig)
367
+ Tolerance.new.big_epsilon(n, mode)
368
+ end
369
+ def Tolerance.fraction(f)
370
+ Tolerance.new.fraction(f)
371
+ end
372
+ def Tolerance.percent(p)
373
+ Tolerance.new.percent(p)
374
+ end
375
+ def Tolerance.permille(p)
376
+ Tolerance.new.permille(p)
377
+ end
378
+
379
+ # This class represents floating point tolerances for BigDecimal numbers
380
+ # and allows comparison within the specified tolerance.
381
+ class BigTolerance
382
+ include StateEquivalent
383
+ module BgMth # :nodoc:
384
+ extend BigMath if ::RUBY_VERSION>='1.8.1'
385
+ end
386
+
387
+ # The numeric class this tolerance applies to.
388
+ def num_class
389
+ BigDecimal
390
+ end
391
+
392
+ #The tolerance mode is either :abs (absolute) :rel (relative) or :sig
393
+ def initialize(t=BigDecimal('0'), mode=:abs, decmode=false)
394
+ set t, mode, decmode
395
+ end
396
+
397
+
398
+ #This initializes a BigTolerance with a given number of decimals
399
+ def decimals(d, mode=:abs, rounded=true)
400
+
401
+ @mode = mode
402
+ @decimal_mode = true
403
+ @d = d==0 ? 16 : d
404
+ if rounded
405
+ @t = BigDecimal("0.5E#{-d}") # HALF*(BigDecimal(10)**(-d))
406
+ else
407
+ @t = BigDecimal("1E#{-d}") # BigDecimal(10)**(-d)
408
+ end
409
+ @ref_exp = BigDecimal('0.1').exponent # reference for significative mode: [0.1,1)
410
+
411
+ self
412
+ end
413
+
414
+ #This initializes a BigTolerance with a number of significative decimal digits
415
+ def sig_decimals(d, rounded=true)
416
+ decimals d, :sig, rounded
417
+ end
418
+
419
+ def fraction(f)
420
+ set f, :rel
421
+ end
422
+ def percent(x)
423
+ fraction x*BigDecimal('0.01')
424
+ end
425
+ def permille(x)
426
+ fraction x*BigDecimal('0.001')
427
+ end
428
+
429
+
430
+ #Shortcut notation for get_value
431
+ def [](x)
432
+ return x.nil? ? @t : get_value(x)
433
+ end
434
+ #Return tolerance relative to a magnitude
435
+ def get_value(x)
436
+ rel(x)
437
+ end
438
+ #Essential equality within tolerance
439
+ def equals?(x,y)
440
+
441
+ case @mode
442
+ when :sig
443
+
444
+ x_exp = x.exponent
445
+ y_exp = y.exponent
446
+ (y-x).abs <= @t*BigDecimal("1E#{[x_exp,y_exp].min-@ref_exp}")
447
+
448
+ when :rel
449
+
450
+ (y-x).abs <= @t*([x.abs,y.abs].min) #reference value is 1
451
+
452
+ when :abs
453
+ (x-y).abs<@t
454
+ end
455
+
456
+ end
457
+ #Approximate equality within tolerance
458
+ def aprx_equals?(x,y)
459
+
460
+ case @mode
461
+ when :sig
462
+
463
+ x_exp = x.exponent
464
+ y_exp = y.exponent
465
+ (y-x).abs <= @t*BigDecimal("1E#{[x_exp,y_exp].max-@ref_exp}")
466
+
467
+ when :rel
468
+
469
+ (y-x).abs <= @t*([x.abs,y.abs].max) #reference value is 1
470
+
471
+ when :abs
472
+ (x-y).abs<=@t
473
+ end
474
+
475
+ end
476
+ #Comparison within tolerance
477
+ def greater_than?(x,y)
478
+ less_than?(y,x)
479
+ end
480
+ #Comparison within tolerance
481
+ def less_than?(x,y)
482
+
483
+ case @mode
484
+ when :sig
485
+
486
+ x_exp = x.exponent
487
+ y_exp = y.exponent
488
+ y-x > @t*BigDecimal("1E#{[x_exp,y_exp].max-@ref_exp}")
489
+
490
+ when :rel
491
+
492
+ y-x > @t*([x.abs,y.abs].max) #reference value is 1
493
+
494
+ when :abs
495
+ x-y<@t
496
+ end
497
+
498
+ end
499
+ #Comparison within tolerance
500
+ def zero?(x,compared_with=nil)
501
+ compared_with.nil? ? x.abs<@t : x.abs<rel(compared_with)
502
+ end
503
+
504
+
505
+ # Returns true if the argument is approximately an integer
506
+ def apprx_i?(x)
507
+ equals?(x,x.round)
508
+ end
509
+ # If the argument is close to an integer it rounds it
510
+ # and returns it as an object of the specified class (by default, Integer)
511
+ def apprx_i(x,result=Integer)
512
+ r = x.round
513
+ return equals?(x,r) ? r.prec(result) : x
514
+ end
515
+
516
+
517
+ # Returns the magnitude of the tolerance
518
+ def magnitude
519
+ @t
520
+ end
521
+ # Returns the number of decimal digits of the tolerance
522
+ def num_decimals
523
+ @d
524
+ end
525
+ # Returns true for decimal-mode tolerance
526
+ def decimal?
527
+ @decimal_mode
528
+ end
529
+ # Returns the mode (:abs, :rel, :sig) of the tolerance
530
+ def mode
531
+ @mode
532
+ end
533
+
534
+
535
+ private
536
+
537
+ HALF = BigDecimal('0.5')
538
+
539
+ def set(t=BigDecimal('0'), mode=:abs, decmode=false)
540
+
541
+ @t = t
542
+ @t = HALF if @t > HALF
543
+ raise TypeError,"El valor de tolerancia debe ser de tipo BigDecimal" if @t.class!=BigDecimal
544
+ @mode = mode
545
+ @decimal_mode = decmode
546
+ @d = @t.zero? ? 0 : -(@t*2).exponent+1
547
+ @ref_exp = BigDecimal('1').exponent # reference for significative mode: [1,10)
548
+
549
+ self
550
+ end
551
+
552
+ def rel(x)
553
+ r = @t
554
+ case @mode
555
+ when :sig
556
+ d = x==0 ? 0 : x.exponent
557
+ r = @t*BigDecimal("1E#{d-@ref_exp}")
558
+ when :rel
559
+ r = @t*x.abs
560
+ end
561
+ r
562
+ end
563
+
564
+ end
565
+
566
+ def BigTolerance.decimals(d=0, mode=:abs)
567
+ BigTolerance.new.decimals(d,mode)
568
+ end
569
+ def BigTolerance.sig_decimals(d=0, mode=:abs)
570
+ BigTolerance.new.sig_decimals(d)
571
+ end
572
+ def BigTolerance.fraction(f)
573
+ BigTolerance.new.fraction(f)
574
+ end
575
+ def BigTolerance.percent(p)
576
+ BigTolerance.new.percent(p)
577
+ end
578
+ def BigTolerance.permille(p)
579
+ BigTolerance.new.permille(p)
580
+ end
581
+
582
+ module_function
583
+
584
+ # Tol(x) -> a Tolerance
585
+ # This module function will convert its argument to a Noi::Tolerance
586
+ # or a Noi::BigTolerance depending on its argument;
587
+ #
588
+ # Values of type Tolerance,Float,Integer (for Tolerance) or
589
+ # BigTolerance,BigDecimal (for BigTolerance) are accepted.
590
+ def Tol(x) # :doc:
591
+ case x
592
+ when Tolerance
593
+ x
594
+ when BigTolerance
595
+ x
596
+ when BigDecimal
597
+ BigTolerance.new(x)
598
+ when Float
599
+ Tolerance.new(x)
600
+ when Integer
601
+ Tolerance.sig_decimals(x)
602
+ else # e.g. Rational
603
+ x
604
+ end
605
+ end
606
+
607
+ # BigTol(x) -> a BigTolerance
608
+ # This module function will convert its argument to a Noi::BigTolerance
609
+ #
610
+ # Values of type BigTolerance or Numeric are accepted.
611
+ def BigTol(x) # :doc:
612
+ case x
613
+ when BigTolerance
614
+ x
615
+ when Integer
616
+ BigTolerance.sig_decimals(x)
617
+ when Rational
618
+ x
619
+ else
620
+ BigTolerance.new(BigDec(x))
621
+ end
622
+ end
623
+
624
+ # BigDec(x) -> a BigDecimal
625
+ # BigDec(x,precision) -> a BigDecimal
626
+ # BigDec(x,:exact) -> a BigDecimal
627
+ # This is a shortcut to define a BigDecimal without using quotes
628
+ # and a general conversion to BigDecimal method.
629
+ #
630
+ # The second parameter can be :exact to try for an exact conversion
631
+ #
632
+ # Conversions from Float have issues that should be understood; :exact
633
+ # conversion will use the exact internal value of the Float, and when
634
+ # no precision is specified, a value as simple as possible expressed as
635
+ # a fraction will be used.
636
+ def BigDec(x,prec=nil) # :doc:
637
+ if x.respond_to?(:to_str)
638
+ x = BigDecimal(x.to_str, prec||0)
639
+ else
640
+ case x
641
+ when Integer
642
+ x = BigDecimal(x.to_s)
643
+ when Rational
644
+ if prec && prec!=:exact
645
+ x = BigDecimal.new(x.numerator.to_s).div(x.denominator,prec)
646
+ else
647
+ x = BigDecimal.new(x.numerator.to_s)/BigDecimal.new(x.denominator.to_s)
648
+ end
649
+ when BigDecimal
650
+ when Float
651
+ x = nio_float_to_bigdecimal(x,prec)
652
+ end
653
+ end
654
+ x
655
+ end
656
+
657
+ end