nio 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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 %*