frac 0.9.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.
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
+