nio 0.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.
data/lib/nio/rtnlzr.rb ADDED
@@ -0,0 +1,406 @@
1
+ # Rationalization of floating point numbers.
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 & Joe Horn
13
+ # License:: Distributes under the GPL license
14
+ #
15
+ # This file provides conversion from floating point numbers
16
+ # to rational numbers.
17
+ # Algorithms by Joe Horn are used.
18
+ #
19
+ # The rational approximation algorithms are implemented in the class Nio::Rtnlzr
20
+ # and there's an interface to the chosen algorithms through:
21
+ # * Float#nio_r
22
+ # * BigDecimal#nio_r
23
+ # There's also exact rationalization implemented in:
24
+ # * Float#nio_xr
25
+ # * BigDecimal#nio_r
26
+
27
+
28
+ require 'nio/tools'
29
+
30
+ require 'nio/flttol'
31
+
32
+ require 'rational'
33
+
34
+ require 'bigdecimal'
35
+
36
+
37
+ class Float
38
+ # Conversion to Rational preserving the exact value of the number.
39
+ def nio_xr
40
+ return Rational(self.to_i,1) if self.modulo(1)==0
41
+ if !self.finite?
42
+ return Rational(0,0) if self.nan?
43
+ return self<0 ? Rational(-1,0) : Rational(1,0)
44
+ end
45
+
46
+ f,e = Math.frexp(self)
47
+
48
+ if e < Float::MIN_EXP
49
+ bits = e+Float::MANT_DIG-Float::MIN_EXP
50
+ else
51
+ bits = [Float::MANT_DIG,e].max
52
+ #return Rational(self.to_i,1) if bits<e
53
+ end
54
+ p = Math.ldexp(f,bits)
55
+ e = bits - e
56
+ if e<Float::MAX_EXP
57
+ q = Math.ldexp(1,e)
58
+ else
59
+ q = Float::RADIX**e
60
+ end
61
+ return Rational(p.to_i,q.to_i)
62
+ end
63
+ end
64
+
65
+ class BigDecimal
66
+ # Conversion to Rational preserving the exact value of the number.
67
+ def nio_xr
68
+ s,f,b,e = split
69
+ p = f.to_i
70
+ p = -p if s<0
71
+ e = f.size-e
72
+ if e<0
73
+ p *= b**(-e)
74
+ e = 0
75
+ end
76
+ q = b**(e)
77
+ return Rational(p,q)
78
+ end
79
+ end
80
+
81
+ class Integer
82
+
83
+ def nio_xr
84
+ return Rational(self,1)
85
+ end
86
+ end
87
+
88
+ class Rational
89
+
90
+ def nio_xr
91
+ return self
92
+ end
93
+
94
+ # helper method to return both the numerator and denominator
95
+ def nio_num_den
96
+ return [numerator,denominator]
97
+ end
98
+ end
99
+
100
+
101
+ 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)
111
+ case tol
112
+ when Integer
113
+ Rational(*Nio::Rtnlzr.max_denominator(self,tol,Float))
114
+ else
115
+ Rational(*Nio::Rtnlzr.new(Nio::Tol(tol)).rationalize(self))
116
+ end
117
+ end
118
+ end
119
+
120
+ 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.
129
+ def nio_r(tol = nil)
130
+ tol ||= BigTolerance.decimals([precs[0],Float::DIG].max,:sig)
131
+ case tol
132
+ when Integer
133
+ Rational(*Nio::Rtnlzr.max_denominator(self,tol,BigDecimal))
134
+ else
135
+ Rational(*Nio::Rtnlzr.new(Nio::BigTol(tol)).rationalize(self))
136
+ end
137
+ end
138
+ end
139
+
140
+ module Nio
141
+
142
+
143
+ # This class provides conversion of fractions
144
+ # (as approximate floating point numbers)
145
+ # to rational numbers.
146
+ class Rtnlzr
147
+ include StateEquivalent
148
+
149
+ # Create Rationalizator with given tolerance.
150
+ def initialize(tol=Tolerance.new)
151
+ @tol = tol
152
+ end
153
+
154
+ # Rationalization method that finds the fraction with
155
+ # smallest denominator fraction within the tolerance distance
156
+ # of an approximate (floating point) number.
157
+ #
158
+ # It uses the algorithm which has been found most efficient, rationalize_Knuth.
159
+ def rationalize(x)
160
+ rationalize_Knuth(x)
161
+ end
162
+
163
+ # This algorithm is derived from exercise 39 of 4.5.3 in
164
+ # "The Art of Computer Programming", by Donald E. Knuth.
165
+ def rationalize_Knuth(x)
166
+
167
+
168
+ num_tol = @tol.kind_of?(Numeric)
169
+ if !num_tol && @tol.zero?(x)
170
+ # num,den = x.nio_xr.nio_num_den
171
+ num,den = 0,1
172
+ else
173
+ negans=false
174
+ if x<0
175
+ negans = true
176
+ x = -x
177
+ end
178
+ dx = num_tol ? @tol : @tol.get_value(x)
179
+
180
+
181
+ x = x.nio_xr
182
+ dx = dx.nio_xr
183
+ xp,xq = (x-dx).nio_num_den
184
+ yp,yq = (x+dx).nio_num_den
185
+
186
+ a = []
187
+ fin,odd = false,false
188
+ while !fin && xp!=0 && yp!=0
189
+ odd = !odd
190
+ xp,xq = xq,xp
191
+ ax = xp.div(xq)
192
+ xp -= ax*xq
193
+
194
+ yp,yq = yq,yp
195
+ ay = yp.div(yq)
196
+ yp -= ay*yq
197
+
198
+ if ax!=ay
199
+ fin = true
200
+ ax,xp,xq = ay,yp,yq if odd
201
+ end
202
+ a << ax # .to_i
203
+ end
204
+ a[-1] += 1 if xp!=0 && a.size>0
205
+ p,q = 1,0
206
+ (1..a.size).each{|i| p,q=q+p*a[-i],p}
207
+ num,den = q,p
208
+
209
+
210
+ num = -num if negans
211
+ end
212
+ return num,den
213
+
214
+
215
+ end
216
+ # This is algorithm PDQ2 by Joe Horn.
217
+ def rationalize_Horn(x)
218
+
219
+
220
+ num_tol = @tol.kind_of?(Numeric)
221
+ if !num_tol && @tol.zero?(x)
222
+ # num,den = x.nio_xr.nio_num_den
223
+ num,den = 0,1
224
+ else
225
+ negans=false
226
+ if x<0
227
+ negans = true
228
+ x = -x
229
+ end
230
+ dx = num_tol ? @tol : @tol.get_value(x)
231
+
232
+
233
+ z,t = x,dx # renaming
234
+
235
+ a,b = t.nio_xr.nio_num_den
236
+ n0,d0 = (n,d = z.nio_xr.nio_num_den)
237
+ cn,x,pn,cd,y,pd,lo,hi,mid,q,r = 1,1,0,0,0,1,0,1,1,0,0
238
+ begin
239
+ q,r = n.divmod(d)
240
+ x = q*cn+pn
241
+ y = q*cd+pd
242
+ pn = cn
243
+ cn = x
244
+ pd = cd
245
+ cd = y
246
+ n,d = d,r
247
+ end until b*(n0*y-d0*x).abs <= a*d0*y
248
+
249
+ if q>1
250
+ hi = q
251
+ begin
252
+ mid = (lo+hi).div(2)
253
+ x = cn-pn*mid
254
+ y = cd-pd*mid
255
+ if b*(n0*y-d0*x).abs <= a*d0*y
256
+ lo = mid
257
+ else
258
+ hi = mid
259
+ end
260
+ end until hi-lo <= 1
261
+ x = cn - pn*lo
262
+ y = cd - pd*lo
263
+ end
264
+
265
+ num,den = x,y # renaming
266
+
267
+
268
+ num = -num if negans
269
+ end
270
+ return num,den
271
+
272
+
273
+ end
274
+ # This is from a RPL program by Tony Hutchins (PDR6).
275
+ def rationalize_HornHutchins(x)
276
+
277
+
278
+ num_tol = @tol.kind_of?(Numeric)
279
+ if !num_tol && @tol.zero?(x)
280
+ # num,den = x.nio_xr.nio_num_den
281
+ num,den = 0,1
282
+ else
283
+ negans=false
284
+ if x<0
285
+ negans = true
286
+ x = -x
287
+ end
288
+ dx = num_tol ? @tol : @tol.get_value(x)
289
+
290
+
291
+ z,t = x,dx # renaming
292
+
293
+ a,b = t.nio_xr.nio_num_den
294
+ n0,d0 = (n,d = z.nio_xr.nio_num_den)
295
+ cn,x,pn,cd,y,pd,lo,hi,mid,q,r = 1,1,0,0,0,1,0,1,1,0,0
296
+ begin
297
+ q,r = n.divmod(d)
298
+ x = q*cn+pn
299
+ y = q*cd+pd
300
+ pn = cn
301
+ cn = x
302
+ pd = cd
303
+ cd = y
304
+ n,d = d,r
305
+ end until b*(n0*y-d0*x).abs <= a*d0*y
306
+
307
+ if q>1
308
+ hi = q
309
+ begin
310
+ mid = (lo+hi).div(2)
311
+ x = cn-pn*mid
312
+ y = cd-pd*mid
313
+ if b*(n0*y-d0*x).abs <= a*d0*y
314
+ lo = mid
315
+ else
316
+ hi = mid
317
+ end
318
+ end until hi-lo <= 1
319
+ x = cn - pn*lo
320
+ y = cd - pd*lo
321
+ end
322
+
323
+ num,den = x,y # renaming
324
+
325
+
326
+ num = -num if negans
327
+ end
328
+ return num,den
329
+
330
+
331
+ end
332
+ end
333
+
334
+ # Best fraction given maximum denominator
335
+ # Algorithm Copyright (c) 1991 by Joseph K. Horn.
336
+ #
337
+ # The implementation of this method uses floating point
338
+ # arithmetic which limits the magnitude and precision of the results, specially
339
+ # using Float values.
340
+ def Rtnlzr.max_denominator(f, max_den=1000000000, num_class=nil)
341
+ return nil if max_den<1
342
+ num_class ||= f.class
343
+ return mth.ip(f),1 if mth.fp(f)==0
344
+
345
+ one = 1.prec(num_class)
346
+
347
+ sign = f<0
348
+ f = -f if sign
349
+
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
355
+
356
+
357
+ if b>max_den
358
+ b -= a*mth.ceil((b-max_den)/Float(a))
359
+ end
360
+
361
+
362
+ f1,f2 = [a,b].collect{|x| mth.abs(mth.rnd(x*f)/x.prec(num_class)-f)}
363
+
364
+ a = f1>f2 ? b : a
365
+
366
+ num,den = mth.rnd(a*f).to_i,a
367
+ den = 1 if mth.abs(den)<1
368
+
369
+ num = -num if sign
370
+
371
+ return num,den
372
+ end
373
+
374
+ class Rtnlzr
375
+ private
376
+ #Auxiliary floating-point functions
377
+ module Mth # :nodoc:
378
+ def self.fp(x)
379
+ # y =x.modulo(1); return x<0 ? -y : y;
380
+ x-ip(x)
381
+ end
382
+
383
+ def self.ip(x)
384
+ # x.to_i.to_f
385
+ (x<0 ? x.ceil : x.floor).to_i
386
+ end
387
+
388
+ def self.rnd(x)
389
+ #x.round.to_i
390
+ x.round
391
+ end
392
+
393
+ def self.abs(x)
394
+ x.abs
395
+ end
396
+
397
+ def self.ceil(x)
398
+ x.ceil.to_i
399
+ end
400
+ end
401
+ def self.mth; Mth; end
402
+ end
403
+
404
+ module_function
405
+
406
+ end
data/lib/nio/sugar.rb ADDED
@@ -0,0 +1,99 @@
1
+ # This file provides some syntactic sugar for the Nio module.
2
+ # Some methods here: #to_r(), #to_xr, may collide with methods in other
3
+ # libraries.
4
+ #
5
+ # This non mondule-function is equivalent to +Nio::Fmt.convert+
6
+ # Nio.convert(x, type, arpx=true)
7
+ # There's also a module-function synonim useful for including the Nio namespace:
8
+ # Nio.nio_convert(x, type, aprx=true)
9
+ # (the convert() method seems too likely for name collisions)
10
+ # Some aliases for nio_write and nio_read:
11
+ # fmt << x -> x.nio_write(fmt)
12
+ # fmt.write(x) -> x.nio_write(fmt)
13
+ # Fmt << x -> x.nio_write()
14
+ # Fmt.write(x) -> x.nio_write()
15
+ # fmt >> [cls,txt] -> cls.nio_read(txt, fmt)
16
+ # fmt.read(cls,txt) -> cls.nio_read(txt, fmt)
17
+ # Fmt >> [cls,txt] -> cls.nio_read(txt)
18
+ # Fmt.read(cls,txt) -> cls.nio_read(txt)
19
+ # Also methods #to_r and #to_xr are added to Float,BigDecimal, etc. as
20
+ # synonims for #nio_r, #nio_xr
21
+
22
+ require 'nio/rtnlzr'
23
+ require 'nio/fmt'
24
+
25
+ # This is not a module function: this provides a shorthand access to Nio::Fmt.convert
26
+ def Nio.convert(x, type, mode=:approx)
27
+ Nio::Fmt.convert x, type, mode
28
+ end
29
+
30
+ module Nio
31
+ module_function
32
+ # This module function can be used after <tt>import Nio</tt>
33
+ def nio_convert(x, type, mode=:approx)
34
+ Nio::Fmt.convert x, type, mode
35
+ end
36
+ # :stopdoc:
37
+ class Fmt
38
+ def <<(x)
39
+ x.nio_write(self)
40
+ end
41
+ def write(x)
42
+ x.nio_write(self)
43
+ end
44
+ def Fmt.<<(x)
45
+ x.nio_write
46
+ end
47
+ def Fmt.write(x)
48
+ x.nio_write
49
+ end
50
+ def >>(cls_txt)
51
+ cls,txt = cls_txt
52
+ cls.nio_read(txt,self)
53
+ end
54
+ def read(cls,txt)
55
+ cls.nio_read(txt,self)
56
+ end
57
+ def Fmt.>>(cls_txt)
58
+ cls,txt = cls_txt
59
+ cls.nio_read(txt)
60
+ end
61
+ def Fmt.read(cls,txt)
62
+ cls.nio_read(txt)
63
+ end
64
+ end
65
+ # :startdoc:
66
+ end
67
+
68
+ # to be considered: for cls in [Float,BigDecimal,Integer,Rational]
69
+ # def cls.<<(txt_fmt); txt,fmt=txt_fmt; cls.nio_read(txt,fmt); end
70
+
71
+ # :stopdoc:
72
+
73
+ #~ class Numeric
74
+ #~ def to_xr
75
+ #~ nio_xr
76
+ #~ end
77
+ #~ end
78
+
79
+ for cls in [Integer,Rational,Float,BigDecimal]
80
+ cls.class_eval {
81
+ def to_xr
82
+ nio_xr
83
+ end
84
+ }
85
+ end
86
+
87
+ class Float
88
+ def to_r(tol = Nio::Tolerance.big_epsilon)
89
+ nio_r(tol)
90
+ end
91
+ end
92
+ class BigFloat
93
+ def to_r(tol = nil)
94
+ nio_r(tol)
95
+ end
96
+ end
97
+
98
+ # :startdoc:
99
+
data/lib/nio/tools.rb ADDED
@@ -0,0 +1,44 @@
1
+ # Common Utilities
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
+ require 'rubygems'
12
+
13
+
14
+
15
+ module Nio
16
+
17
+ module StateEquivalent
18
+ def ==(obj); test_equal(obj); end
19
+ def eql?(obj); test_equal(obj); end
20
+ def ===(obj); test_equal(obj); end
21
+ def hash
22
+ h = 0
23
+ self.instance_variables.each do |var|
24
+ v = self.instance_eval var
25
+ h ^= v.hash unless v.nil?
26
+ end
27
+ h
28
+ end
29
+
30
+ private
31
+ def test_equal(obj)
32
+ return false unless self.class == obj.class
33
+ (self.instance_variables + obj.instance_variables).uniq.each do |var|
34
+ v1 = self.instance_eval var
35
+ v2 = obj.instance_eval var
36
+ return false unless v1 == v2
37
+ end
38
+ true
39
+ end
40
+ end
41
+
42
+ module_function
43
+
44
+ end
@@ -0,0 +1,9 @@
1
+ module Nio #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/nio.rb ADDED
@@ -0,0 +1,8 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'nio/version'
4
+ require 'nio/tools'
5
+ require 'nio/flttol'
6
+ require 'nio/repdec'
7
+ require 'nio/rtnlzr'
8
+ require 'nio/fmt'
data/log/debug.log ADDED
File without changes
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1 @@
1
+ @ruby script/destroy %*
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1 @@
1
+ @ruby script/generate %*
data/script/txt2html ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ begin
5
+ require 'newgem'
6
+ rescue LoadError
7
+ puts "\n\nGenerating the website requires the newgem RubyGem"
8
+ puts "Install: gem install newgem\n\n"
9
+ exit(1)
10
+ end
11
+ require 'redcloth'
12
+ require 'syntax/convertors/html'
13
+ require 'erb'
14
+ require File.dirname(__FILE__) + '/../lib/nio/version.rb'
15
+
16
+ version = Nio::VERSION::STRING
17
+ download = 'http://rubyforge.org/projects/nio'
18
+
19
+ class Fixnum
20
+ def ordinal
21
+ # teens
22
+ return 'th' if (10..19).include?(self % 100)
23
+ # others
24
+ case self % 10
25
+ when 1: return 'st'
26
+ when 2: return 'nd'
27
+ when 3: return 'rd'
28
+ else return 'th'
29
+ end
30
+ end
31
+ end
32
+
33
+ class Time
34
+ def pretty
35
+ return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
36
+ end
37
+ end
38
+
39
+ def convert_syntax(syntax, source)
40
+ return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
41
+ end
42
+
43
+ if ARGV.length >= 1
44
+ src, template = ARGV
45
+ template ||= File.join(File.dirname(__FILE__), '/../website/template.rhtml')
46
+
47
+ else
48
+ puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
49
+ exit!
50
+ end
51
+
52
+ template = ERB.new(File.open(template).read)
53
+
54
+ title = nil
55
+ body = nil
56
+ File.open(src) do |fsrc|
57
+ title_text = fsrc.readline
58
+ body_text = fsrc.read
59
+ syntax_items = []
60
+ body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
61
+ ident = syntax_items.length
62
+ element, syntax, source = $1, $2, $3
63
+ syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
64
+ "syntax-temp-#{ident}"
65
+ }
66
+ title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
67
+ body = RedCloth.new(body_text).to_html
68
+ body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
69
+ end
70
+ stat = File.stat(src)
71
+ created = stat.ctime
72
+ modified = stat.mtime
73
+
74
+ $stdout << template.result(binding)
@@ -0,0 +1 @@
1
+ @ruby script/txt2html %*