nio 0.2.3 → 0.2.4

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.
@@ -48,8 +48,8 @@ module Nio
48
48
  ch_code = ch_code.chr if ch_code.kind_of?(Numeric)
49
49
  @dncase ? ch_code.downcase[0] : ch_code.upcase[0]
50
50
  end
51
- end
52
-
51
+ end
52
+
53
53
 
54
54
  # RepDec handles repeating decimals (repeating numerals actually)
55
55
  class RepDec
@@ -76,7 +76,7 @@ module Nio
76
76
 
77
77
  @max_d = 5000
78
78
 
79
- end
79
+ end
80
80
  attr_accessor :begin_rep, :end_rep, :auto_rep, :dec_sep, :grp_sep, :grp, :max_d
81
81
  attr_accessor :nan_txt, :inf_txt
82
82
 
@@ -105,7 +105,7 @@ module Nio
105
105
  end
106
106
 
107
107
  def set_digits(ds, dncase=false, casesens=false)
108
- if ds
108
+ if ds
109
109
  @digits_defined = true
110
110
  if ds.kind_of?(DigitsDef)
111
111
  @digits = ds
@@ -144,7 +144,7 @@ module Nio
144
144
  self
145
145
  end
146
146
 
147
- def setS(str, opt=DEF_OPT)
147
+ def setS(str, opt=DEF_OPT)
148
148
  setZ(opt.digits_defined? ? opt.digits.radix : @radix);
149
149
  sgn,i_str,f_str,ri,detect_rep = RepDec.parse(str,opt)
150
150
  if i_str.kind_of?(Symbol)
@@ -155,7 +155,7 @@ module Nio
155
155
  @sign = sgn
156
156
  @rep_i = ri if ri
157
157
  f_str.each_byte{|b| @d.push opt.digits.digit_value(b)} unless f_str.nil?
158
-
158
+
159
159
  if detect_rep then
160
160
 
161
161
  for l in 1..(@d.length/2)
@@ -169,30 +169,30 @@ module Nio
169
169
  if @d[-m..-1]!=@d[-i*m...-i*m+m] then
170
170
  reduce_l = false;
171
171
  break;
172
- end
172
+ end
173
173
  end
174
174
  if reduce_l then
175
175
  l = m
176
176
  break
177
- end
177
+ end
178
178
  end
179
179
  end
180
-
180
+
181
181
 
182
182
  @rep_i = @d.length - 2*l;
183
183
  l.times { @d.pop }
184
184
 
185
185
 
186
- while @d.length >= 2*l && @d[-l..-1]==@d[-2*l...-l]
186
+ while @d.length >= 2*l && @d[-l..-1]==@d[-2*l...-l]
187
187
 
188
188
  @rep_i = @d.length - 2*l;
189
189
  l.times { @d.pop }
190
190
 
191
191
  end
192
-
192
+
193
193
  break
194
194
  end
195
- end
195
+ end
196
196
 
197
197
  end
198
198
 
@@ -201,10 +201,10 @@ module Nio
201
201
  if @d.length==@rep_i+1 && @d[@rep_i]==0 then
202
202
  @rep_i = nil;
203
203
  @d.pop;
204
- end
204
+ end
205
205
  end
206
206
  @d.pop while @d[@d.length-1]==0
207
-
207
+
208
208
  self
209
209
  end
210
210
 
@@ -248,7 +248,7 @@ module Nio
248
248
  end
249
249
 
250
250
  unless i_str.kind_of?(Symbol)
251
- j = 0;
251
+ j = 0;
252
252
  f_str = ''
253
253
  while i<l
254
254
  ch = str[i,1];
@@ -301,9 +301,9 @@ module Nio
301
301
  check.setS s+opt.auto_rep, opt;
302
302
  #print " s=",s,"\n"
303
303
  #print " self=",self.to_s,"\n"
304
- while check!=self
304
+ while check!=self
305
305
  for i in @rep_i...@d.length
306
- s << opt.digits.digit_char(@d[i])
306
+ s << opt.digits.digit_char(@d[i])
307
307
  end
308
308
  check.setS s+opt.auto_rep, opt;
309
309
  end
@@ -311,7 +311,7 @@ module Nio
311
311
  s += opt.auto_rep;
312
312
  end
313
313
  else
314
- s += opt.end_rep if @rep_i!=nil;
314
+ s += opt.end_rep if @rep_i!=nil;
315
315
  end
316
316
  return s;
317
317
  end
@@ -337,7 +337,7 @@ module Nio
337
337
  @d.pop if i==@d.length;
338
338
  end
339
339
  i -= 1;
340
- end
340
+ end
341
341
  @ip += carry;
342
342
 
343
343
  end
@@ -424,10 +424,10 @@ module Nio
424
424
  x *= @radix
425
425
  d,x = x.divmod(y)
426
426
  @d.push d
427
- i += 1;
427
+ i += 1;
428
428
  end
429
429
  end
430
- self
430
+ self
431
431
  end
432
432
 
433
433
  def getQ(opt=DEF_OPT)
@@ -442,7 +442,7 @@ module Nio
442
442
  end if
443
443
 
444
444
 
445
- n = @d.length
445
+ n = @d.length
446
446
  a = @ip
447
447
  b = a
448
448
  for i in 0...n
@@ -463,25 +463,25 @@ module Nio
463
463
  d = Nio.gcd(x,y)
464
464
  x /= d
465
465
  y /= d
466
-
466
+
467
467
  x = -x if @sign<0
468
-
469
- return x,y;
468
+
469
+ return x,y;
470
470
  end
471
471
 
472
472
  #protected
473
473
 
474
474
  attr_reader :d, :ip, :rep_i, :sign;
475
475
  attr_writer :d, :ip, :rep_i, :sign;
476
-
477
- end
478
476
 
477
+ end
478
+
479
479
 
480
480
  def RepDec.group_digits(digits, opt)
481
481
  if opt.grp_sep!=nil && opt.grp_sep!='' && opt.grp.length>0
482
- grouped = ''
482
+ grouped = ''
483
483
  i = 0
484
- while digits.length>0
484
+ while digits.length>0
485
485
  l = opt.grp[i]
486
486
  l = digits.length if l>digits.length
487
487
  grouped = opt.grp_sep + grouped if grouped.length>0
@@ -492,7 +492,7 @@ module Nio
492
492
  grouped
493
493
  else
494
494
  digits
495
- end
495
+ end
496
496
  end
497
497
 
498
498
  module_function
@@ -501,7 +501,7 @@ module Nio
501
501
  while b!=0 do
502
502
  a,b = b, a.modulo(b)
503
503
  end
504
- return a.abs;
504
+ return a.abs;
505
505
  end
506
506
 
507
507
  end
@@ -1,11 +1,6 @@
1
1
  # Rationalization of floating point numbers.
2
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.
3
+
9
4
  #++
10
5
  #
11
6
  # Author:: Javier Goizueta (mailto:javier@goizueta.info)
@@ -27,12 +22,14 @@
27
22
 
28
23
  require 'nio/tools'
29
24
 
30
- require 'nio/flttol'
25
+ require 'flt/tolerance'
31
26
 
32
27
  require 'rational'
33
28
 
34
29
  require 'bigdecimal'
35
30
 
31
+ require 'flt'
32
+
36
33
 
37
34
  class Float
38
35
  # Conversion to Rational preserving the exact value of the number.
@@ -42,15 +39,15 @@ class Float
42
39
  return Rational(0,0) if self.nan?
43
40
  return self<0 ? Rational(-1,0) : Rational(1,0)
44
41
  end
45
-
42
+
46
43
  f,e = Math.frexp(self)
47
-
44
+
48
45
  if e < Float::MIN_EXP
49
46
  bits = e+Float::MANT_DIG-Float::MIN_EXP
50
47
  else
51
- bits = [Float::MANT_DIG,e].max
48
+ bits = [Float::MANT_DIG,e].max
52
49
  #return Rational(self.to_i,1) if bits<e
53
- end
50
+ end
54
51
  p = Math.ldexp(f,bits)
55
52
  e = bits - e
56
53
  if e<Float::MAX_EXP
@@ -78,6 +75,13 @@ class BigDecimal
78
75
  end
79
76
  end
80
77
 
78
+ class Flt::Num
79
+
80
+ def nio_xr
81
+ to_r
82
+ end
83
+ end
84
+
81
85
  class Integer
82
86
 
83
87
  def nio_xr
@@ -90,7 +94,7 @@ class Rational
90
94
  def nio_xr
91
95
  return self
92
96
  end
93
-
97
+
94
98
  # helper method to return both the numerator and denominator
95
99
  def nio_num_den
96
100
  return [numerator,denominator]
@@ -99,40 +103,39 @@ end
99
103
 
100
104
 
101
105
  class Float
102
- # Conversion to Rational. The optional argument must be one of:
103
- # - a Nio::Tolerance that defines the admisible tolerance;
104
- # in that case, the smallest denominator rational within the
105
- # tolerance will be found (which may take a long time for
106
- # small tolerances.)
107
- # - an integer that defines a maximum value for the denominator.
108
- # in which case, the best approximation with that maximum
109
- # denominator will be returned.
110
- def nio_r(tol = Nio::Tolerance.big_epsilon)
106
+
107
+ def nio_r(tol = Flt.Tolerance(:big_epsilon))
111
108
  case tol
112
109
  when Integer
113
110
  Rational(*Nio::Rtnlzr.max_denominator(self,tol,Float))
114
111
  else
115
- Rational(*Nio::Rtnlzr.new(Nio::Tol(tol)).rationalize(self))
112
+ Rational(*Nio::Rtnlzr.new(tol).rationalize(self))
116
113
  end
117
114
  end
118
115
  end
119
116
 
120
117
  class BigDecimal
121
- # Conversion to Rational. The optional argument must be one of:
122
- # - a Nio::BigTolerance that defines the admisible tolerance;
123
- # in that case, the smallest denominator rational within the
124
- # tolerance will be found (which may take a long time for
125
- # small tolerances.)
126
- # - an integer that defines a maximum value for the denominator.
127
- # in which case, the best approximation with that maximum
128
- # denominator will be returned.
118
+
129
119
  def nio_r(tol = nil)
130
- tol ||= BigTolerance.decimals([precs[0],Float::DIG].max,:sig)
120
+ tol ||= Flt.Tolerance([precs[0],Float::DIG].max,:sig_decimals)
131
121
  case tol
132
122
  when Integer
133
123
  Rational(*Nio::Rtnlzr.max_denominator(self,tol,BigDecimal))
134
124
  else
135
- Rational(*Nio::Rtnlzr.new(Nio::BigTol(tol)).rationalize(self))
125
+ Rational(*Nio::Rtnlzr.new(tol).rationalize(self))
126
+ end
127
+ end
128
+ end
129
+
130
+ class Flt::Num
131
+
132
+ def nio_r(tol = nil)
133
+ tol ||= Flt.Tolerance(Rational(1,2),:ulps)
134
+ case tol
135
+ when Integer
136
+ Rational(*Nio::Rtnlzr.max_denominator(self,tol,num_class))
137
+ else
138
+ Rational(*Nio::Rtnlzr.new(tol).rationalize(self))
136
139
  end
137
140
  end
138
141
  end
@@ -140,14 +143,14 @@ end
140
143
  module Nio
141
144
 
142
145
 
143
- # This class provides conversion of fractions
146
+ # This class provides conversion of fractions
144
147
  # (as approximate floating point numbers)
145
148
  # to rational numbers.
146
149
  class Rtnlzr
147
150
  include StateEquivalent
148
151
 
149
152
  # Create Rationalizator with given tolerance.
150
- def initialize(tol=Tolerance.new)
153
+ def initialize(tol=Flt.Tolerance(:epsilon))
151
154
  @tol = tol
152
155
  end
153
156
 
@@ -159,8 +162,8 @@ module Nio
159
162
  def rationalize(x)
160
163
  rationalize_Knuth(x)
161
164
  end
162
-
163
- # This algorithm is derived from exercise 39 of 4.5.3 in
165
+
166
+ # This algorithm is derived from exercise 39 of 4.5.3 in
164
167
  # "The Art of Computer Programming", by Donald E. Knuth.
165
168
  def rationalize_Knuth(x)
166
169
 
@@ -175,14 +178,14 @@ module Nio
175
178
  negans = true
176
179
  x = -x
177
180
  end
178
- dx = num_tol ? @tol : @tol.get_value(x)
179
-
181
+ dx = num_tol ? @tol : @tol.value(x)
182
+
180
183
 
181
184
  x = x.nio_xr
182
185
  dx = dx.nio_xr
183
186
  xp,xq = (x-dx).nio_num_den
184
187
  yp,yq = (x+dx).nio_num_den
185
-
188
+
186
189
  a = []
187
190
  fin,odd = false,false
188
191
  while !fin && xp!=0 && yp!=0
@@ -205,13 +208,13 @@ module Nio
205
208
  p,q = 1,0
206
209
  (1..a.size).each{|i| p,q=q+p*a[-i],p}
207
210
  num,den = q,p
208
-
209
211
 
212
+
210
213
  num = -num if negans
211
214
  end
212
215
  return num,den
213
216
 
214
-
217
+
215
218
  end
216
219
  # This is algorithm PDQ2 by Joe Horn.
217
220
  def rationalize_Horn(x)
@@ -227,8 +230,8 @@ module Nio
227
230
  negans = true
228
231
  x = -x
229
232
  end
230
- dx = num_tol ? @tol : @tol.get_value(x)
231
-
233
+ dx = num_tol ? @tol : @tol.value(x)
234
+
232
235
 
233
236
  z,t = x,dx # renaming
234
237
 
@@ -257,19 +260,19 @@ module Nio
257
260
  else
258
261
  hi = mid
259
262
  end
260
- end until hi-lo <= 1
263
+ end until hi-lo <= 1
261
264
  x = cn - pn*lo
262
- y = cd - pd*lo
263
- end
264
-
265
+ y = cd - pd*lo
266
+ end
267
+
265
268
  num,den = x,y # renaming
266
-
267
269
 
270
+
268
271
  num = -num if negans
269
272
  end
270
273
  return num,den
271
274
 
272
-
275
+
273
276
  end
274
277
  # This is from a RPL program by Tony Hutchins (PDR6).
275
278
  def rationalize_HornHutchins(x)
@@ -285,8 +288,8 @@ module Nio
285
288
  negans = true
286
289
  x = -x
287
290
  end
288
- dx = num_tol ? @tol : @tol.get_value(x)
289
-
291
+ dx = num_tol ? @tol : @tol.value(x)
292
+
290
293
 
291
294
  z,t = x,dx # renaming
292
295
 
@@ -315,19 +318,19 @@ module Nio
315
318
  else
316
319
  hi = mid
317
320
  end
318
- end until hi-lo <= 1
321
+ end until hi-lo <= 1
319
322
  x = cn - pn*lo
320
- y = cd - pd*lo
321
- end
322
-
323
+ y = cd - pd*lo
324
+ end
325
+
323
326
  num,den = x,y # renaming
324
-
325
327
 
328
+
326
329
  num = -num if negans
327
330
  end
328
331
  return num,den
329
332
 
330
-
333
+
331
334
  end
332
335
  end
333
336
 
@@ -340,33 +343,36 @@ module Nio
340
343
  def Rtnlzr.max_denominator(f, max_den=1000000000, num_class=nil)
341
344
  return nil if max_den<1
342
345
  num_class ||= f.class
346
+ context = num_class.context
343
347
  return mth.ip(f),1 if mth.fp(f)==0
344
348
 
345
- one = Nio.numeric_cast(1, num_class)
346
-
347
- sign = f<0
348
- f = -f if sign
349
+ cast = lambda{|x| context.Num(x)}
349
350
 
350
- a,b,c = 0,1,f
351
- while b<max_den and c!=0
352
- cc = one/c
353
- a,b,c = b, mth.ip(cc)*b+a, mth.fp(cc)
354
- end
351
+ one = cast.call(1)
355
352
 
356
-
357
- if b>max_den
358
- b -= a*mth.ceil((b-max_den)/Float(a))
359
- end
360
-
353
+ sign = f<0
354
+ f = -f if sign
361
355
 
362
- f1,f2 = [a,b].collect{|x| mth.abs(mth.rnd(x*f)/Nio.numeric_cast(x, num_class)-f)}
356
+ a,b,c = 0,1,f
357
+ while b<max_den and c!=0
358
+ cc = one/c
359
+ a,b,c = b, mth.ip(cc)*b+a, mth.fp(cc)
360
+ end
363
361
 
364
- a = f1>f2 ? b : a
365
362
 
366
- num,den = mth.rnd(a*f).to_i,a
367
- den = 1 if mth.abs(den)<1
368
-
369
- num = -num if sign
363
+ if b>max_den
364
+ b -= a*mth.ceil(cast.call(b-max_den)/a)
365
+ end
366
+
367
+
368
+ f1,f2 = [a,b].collect{|x| mth.abs(cast.call(mth.rnd(x*f))/x-f)}
369
+
370
+ a = f1>f2 ? b : a
371
+
372
+ num,den = mth.rnd(a*f).to_i,a
373
+ den = 1 if mth.abs(den)<1
374
+
375
+ num = -num if sign
370
376
 
371
377
  return num,den
372
378
  end
@@ -381,13 +387,13 @@ module Nio
381
387
  end
382
388
 
383
389
  def self.ip(x)
384
- # x.to_i.to_f
390
+ # Note that ceil, floor return an Integer for Float and Flt::Num, but not for BigDecimal
385
391
  (x<0 ? x.ceil : x.floor).to_i
386
392
  end
387
393
 
388
394
  def self.rnd(x)
389
- #x.round.to_i
390
- x.round
395
+ # Note that round returns an Integer for Float and Flt::Num, but not for BigDecimal
396
+ x.round.to_i
391
397
  end
392
398
 
393
399
  def self.abs(x)
@@ -395,8 +401,9 @@ module Nio
395
401
  end
396
402
 
397
403
  def self.ceil(x)
404
+ # Note that ceil returns an Integer for Float and Flt::Num, but not for BigDecimal
398
405
  x.ceil.to_i
399
- end
406
+ end
400
407
  end
401
408
  def self.mth; Mth; end
402
409
  end