frac 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/ext/extconf.rb +4 -0
  2. data/ext/frac_ext.c +83 -0
  3. data/lib/frac.rb +10 -0
  4. metadata +64 -0
data/ext/extconf.rb ADDED
@@ -0,0 +1,4 @@
1
+
2
+ require 'mkmf'
3
+
4
+ create_makefile("frac_ext")
data/ext/frac_ext.c ADDED
@@ -0,0 +1,83 @@
1
+ // http://www.ics.uci.edu/~eppstein/numth/frap.c
2
+ /*
3
+ ** find rational approximation to given real number
4
+ ** David Eppstein / UC Irvine / 8 Aug 1993
5
+ **
6
+ ** With corrections from Arno Formella, May 2008
7
+ **
8
+ ** usage: a.out r d
9
+ ** r is real number to approx
10
+ ** d is the maximum denominator allowed
11
+ **
12
+ ** based on the theory of continued fractions
13
+ ** if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
14
+ ** then best approximation is found by truncating this series
15
+ ** (with some adjustments in the last term).
16
+ **
17
+ ** Note the fraction can be recovered as the first column of the matrix
18
+ ** ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
19
+ ** ( 1 0 ) ( 1 0 ) ( 1 0 )
20
+ ** Instead of keeping the sequence of continued fraction terms,
21
+ ** we just keep the last partial product of these matrices.
22
+ */
23
+
24
+ #include <stdio.h>
25
+ #include <ruby.h>
26
+
27
+ static VALUE find_fracs(VALUE mod, VALUE rv, VALUE dv)
28
+ {
29
+ VALUE ret;
30
+ long m[2][2];
31
+ double startx, x = RFLOAT_VALUE(rv);
32
+ long ai, maxden = NUM2LONG(dv);
33
+
34
+ startx = x;
35
+
36
+ /* initialize matrix */
37
+ m[0][0] = m[1][1] = 1;
38
+ m[0][1] = m[1][0] = 0;
39
+
40
+ /* loop finding terms until denom gets too big */
41
+ while (m[1][0] * ( ai = (long)x ) + m[1][1] <= maxden) {
42
+ long t;
43
+ t = m[0][0] * ai + m[0][1];
44
+ m[0][1] = m[0][0];
45
+ m[0][0] = t;
46
+ t = m[1][0] * ai + m[1][1];
47
+ m[1][1] = m[1][0];
48
+ m[1][0] = t;
49
+ if(x==(double)ai) break; // AF: division by zero
50
+ x = 1/(x - (double) ai);
51
+ if(x>(double)0x7FFFFFFF) break; // AF: representation failure
52
+ }
53
+
54
+ {
55
+ /* now remaining x is between 0 and 1/ai */
56
+ /* approx as either 0 or 1/m where m is max that will fit in maxden */
57
+ /* first try zero */
58
+ VALUE num1, den1, err1, num2, den2, err2;
59
+
60
+ num1 = LONG2NUM(m[0][0]);
61
+ den1 = LONG2NUM(m[1][0]);
62
+ err1 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0]));
63
+
64
+ /* now try other possibility */
65
+ ai = (maxden - m[1][1]) / m[1][0];
66
+ m[0][0] = m[0][0] * ai + m[0][1];
67
+ m[1][0] = m[1][0] * ai + m[1][1];
68
+
69
+ num2 = LONG2NUM(m[0][0]);
70
+ den2 = LONG2NUM(m[1][0]);
71
+ err2 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0]));
72
+
73
+ return rb_ary_new3(6, num1, den1, err1, num2, den2, err2);
74
+ }
75
+ }
76
+
77
+
78
+ void Init_frac_ext()
79
+ {
80
+ rb_define_module_function(rb_mMath, "find_fracs", find_fracs, 2);
81
+ }
82
+
83
+
data/lib/frac.rb ADDED
@@ -0,0 +1,10 @@
1
+
2
+ require 'frac_ext'
3
+
4
+ module Math
5
+ # Find rational approximation to given real number.
6
+ def self.frac(float, prec)
7
+ arr = find_fracs(float, prec)
8
+ arr[2] > arr[5] ? Rational(arr[3], arr[4]) : Rational(arr[0], arr[1])
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: frac
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 9
8
+ - 0
9
+ version: 0.9.0
10
+ platform: ruby
11
+ authors:
12
+ - Pavel Valodzka
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-25 00:00:00 +03:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Find rational approximation to given real number
22
+ email: pavel@valodzka.name
23
+ executables: []
24
+
25
+ extensions:
26
+ - ext/extconf.rb
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - ext/frac_ext.c
31
+ - ext/extconf.rb
32
+ - lib/frac.rb
33
+ has_rdoc: true
34
+ homepage: http://github.com/valodzka/frac
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.3.6
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: Find rational approximation to given real number. based on the theory of continued fractions if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...))) then best approximation is found by truncating this series (with some adjustments in the last term). Note the fraction can be recovered as the first column of the matrix ( a1 1 ) ( a2 1 ) ( a3 1 ) ... ( 1 0 ) ( 1 0 ) ( 1 0 ) Instead of keeping the sequence of continued fraction terms, we just keep the last partial product of these matrices.
63
+ test_files: []
64
+