fibonacci 0.1.9 → 0.1.10
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.
- checksums.yaml +4 -4
- data/ext/fibonacci/fibonacci.c +306 -413
- data/lib/fibonacci/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 308698f8ba3046c3c5739f458419a27d9737e749c2ab4f5bfdff9ea2c12828ca
|
|
4
|
+
data.tar.gz: 7e58056a369c590049551d87bbb241964932dcd676fd8b89f036ae6b00a00ec8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ed07c3ff1409a4d0daaf4dce7fc34c5eb51a27631ffe0eb9de0ce09d9445d4f26d482328861f1cacec171cb446bf889c2fc037212751e1d6e1128e93f7bd66bd
|
|
7
|
+
data.tar.gz: 51133cbf54f16a20481dee806b028f4efa077b9cf73653c5fa2bccd3e4205bc5b9e7b778ee85609eddfd9fff675e659d3c5fef3f612e7a00d0fdfb164757d131
|
data/ext/fibonacci/fibonacci.c
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
2
|
*
|
|
3
|
-
* Fibonacci Series
|
|
3
|
+
* Fibonacci Series (Modern Ruby C API version)
|
|
4
4
|
*
|
|
5
5
|
* Author: NagaChaitanya Vellanki
|
|
6
|
+
* Updated: 2026 - Ruby 3.0+ compatible
|
|
6
7
|
*
|
|
7
|
-
|
|
8
|
+
***************************************************************************/
|
|
8
9
|
|
|
9
10
|
#include "ruby.h"
|
|
10
11
|
|
|
12
|
+
/* Ruby version compatibility */
|
|
13
|
+
#define RUBY_VERSION_MAJOR RUBY_API_VERSION_MAJOR
|
|
14
|
+
#define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
|
15
|
+
|
|
11
16
|
#define ONE INT2NUM(1)
|
|
12
17
|
#define ZERO INT2NUM(0)
|
|
13
18
|
#define TWO INT2NUM(2)
|
|
@@ -16,156 +21,137 @@
|
|
|
16
21
|
#define ARY_LEN 2L
|
|
17
22
|
|
|
18
23
|
static VALUE cFibonacci;
|
|
24
|
+
|
|
25
|
+
/* Pre-cached method IDs - initialized at module load time */
|
|
19
26
|
static ID id_plus, id_lte, id_gte, id_lt, id_pow, id_minus, id_fdiv, id_div;
|
|
20
27
|
static ID id_to_i, id_log10, id_floor, id_sqrt, id_mul, id_eq, id_not_eq;
|
|
21
|
-
static ID id_mod, id_bit_and, id_log2;
|
|
28
|
+
static ID id_mod, id_bit_and, id_log2, id_to_s;
|
|
29
|
+
|
|
30
|
+
/* Inline helper for safer integer type checking */
|
|
31
|
+
static inline int fib_is_valid_index(VALUE n) { return FIXNUM_P(n); }
|
|
22
32
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return self;
|
|
33
|
+
/* Inline helper to check if number is negative */
|
|
34
|
+
static inline int fib_is_negative(VALUE n) {
|
|
35
|
+
return RTEST(rb_funcall(n, id_lt, 1, ZERO));
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
VALUE num_str = rb_funcall(num, rb_intern("to_s"), 0);
|
|
33
|
-
char *cptr = StringValuePtr(num_str);
|
|
34
|
-
printf("%s\n", cptr);
|
|
35
|
-
return Qnil;
|
|
38
|
+
/* Inline helper to compare equality with zero */
|
|
39
|
+
static inline int fib_is_zero(VALUE n) {
|
|
40
|
+
return RTEST(rb_funcall(n, id_eq, 1, ZERO));
|
|
36
41
|
}
|
|
37
42
|
|
|
43
|
+
/* Inline helper for safe output */
|
|
44
|
+
static inline void fib_print_value(VALUE num) {
|
|
45
|
+
VALUE num_str = rb_funcall(num, id_to_s, 0);
|
|
46
|
+
printf("%s\n", StringValueCStr(num_str));
|
|
47
|
+
}
|
|
38
48
|
|
|
39
49
|
/* call-seq:
|
|
40
50
|
* fib.fast_val(n)
|
|
41
51
|
*
|
|
42
|
-
* Returns a Fixnum or Bignum.
|
|
52
|
+
* Returns a Fixnum or Bignum using fast matrix-based algorithm.
|
|
43
53
|
*
|
|
44
54
|
* fib.fast_val(100)
|
|
45
55
|
* #=> 354224848179261915075
|
|
46
56
|
*
|
|
47
|
-
* fib.fast_val(10)
|
|
48
|
-
* #=> 55
|
|
49
|
-
*
|
|
50
|
-
* fib.fast_val(200)
|
|
51
|
-
* #=> 280571172992510140037611932413038677189525
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
57
|
* ref: Daisuke Takahashi, A fast algorithm for computing large Fibonacci
|
|
55
58
|
* numbers, Information Processing Letters, Volume 75, Issue 6, 30 November
|
|
56
59
|
* 2000, Pages 243-246, ISSN 0020-0190, 10.1016/S0020-0190(00)00112-5.
|
|
57
60
|
*/
|
|
61
|
+
static VALUE rb_fast_val(VALUE self, VALUE n) {
|
|
62
|
+
VALUE f, l, sign, mask, i, logn, logn_min_1, temp;
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if(TYPE(n) != T_FIXNUM)
|
|
65
|
-
{
|
|
66
|
-
rb_raise(rb_eArgError, "Invalid argument for type Fixnum");
|
|
67
|
-
return Qnil;
|
|
68
|
-
}
|
|
64
|
+
if (!fib_is_valid_index(n)) {
|
|
65
|
+
rb_raise(rb_eArgError, "Fibonacci index must be an integer");
|
|
66
|
+
return Qnil;
|
|
67
|
+
}
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
f = rb_funcall(f, id_plus, 1, l);
|
|
113
|
-
f = rb_funcall(f, id_div, 1, TWO);
|
|
114
|
-
l = rb_funcall(TWO, id_mul, 1, temp);
|
|
115
|
-
l = rb_funcall(l, id_plus, 1, f);
|
|
116
|
-
sign = MINUS_ONE;
|
|
117
|
-
}
|
|
118
|
-
mask = rb_funcall(mask, id_div, 1, TWO);
|
|
119
|
-
}
|
|
120
|
-
if(rb_equal(rb_funcall(n, id_bit_and, 1, mask), ZERO))
|
|
121
|
-
{
|
|
122
|
-
f = rb_funcall(f, id_mul, 1, l);
|
|
123
|
-
}
|
|
124
|
-
else
|
|
125
|
-
{
|
|
126
|
-
f = rb_funcall(f, id_plus, 1, l);
|
|
127
|
-
f = rb_funcall(f, id_div, 1, TWO);
|
|
128
|
-
f = rb_funcall(f, id_mul, 1, l);
|
|
129
|
-
f = rb_funcall(f, id_minus, 1, sign);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
69
|
+
if (fib_is_negative(n)) {
|
|
70
|
+
rb_raise(rb_eArgError, "Fibonacci index cannot be negative");
|
|
71
|
+
return Qnil;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (fib_is_zero(n)) {
|
|
75
|
+
return ZERO;
|
|
76
|
+
}
|
|
77
|
+
if (rb_equal(n, ONE)) {
|
|
78
|
+
return ONE;
|
|
79
|
+
}
|
|
80
|
+
if (rb_equal(n, TWO)) {
|
|
81
|
+
return ONE;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
f = ONE;
|
|
85
|
+
l = ONE;
|
|
86
|
+
sign = MINUS_ONE;
|
|
87
|
+
logn = rb_funcall(rb_mMath, id_log2, 1, n);
|
|
88
|
+
logn = rb_funcall(logn, id_floor, 0);
|
|
89
|
+
logn_min_1 = rb_funcall(logn, id_minus, 1, ONE);
|
|
90
|
+
mask = rb_funcall(TWO, id_pow, 1, logn_min_1);
|
|
91
|
+
|
|
92
|
+
for (i = ONE; RTEST(rb_funcall(i, id_lte, 1, logn_min_1));
|
|
93
|
+
i = rb_funcall(i, id_plus, 1, ONE)) {
|
|
94
|
+
temp = rb_funcall(f, id_mul, 1, f);
|
|
95
|
+
f = rb_funcall(f, id_plus, 1, l);
|
|
96
|
+
f = rb_funcall(f, id_div, 1, TWO);
|
|
97
|
+
f = rb_funcall(rb_funcall(f, id_mul, 1, f), id_mul, 1, TWO);
|
|
98
|
+
f = rb_funcall(f, id_minus, 1, rb_funcall(temp, id_mul, 1, THREE));
|
|
99
|
+
f = rb_funcall(f, id_minus, 1, rb_funcall(sign, id_mul, 1, TWO));
|
|
100
|
+
l = rb_funcall(temp, id_mul, 1, INT2NUM(5));
|
|
101
|
+
l = rb_funcall(l, id_plus, 1, rb_funcall(TWO, id_mul, 1, sign));
|
|
102
|
+
sign = ONE;
|
|
103
|
+
|
|
104
|
+
if (!rb_equal(rb_funcall(n, id_bit_and, 1, mask), ZERO)) {
|
|
105
|
+
temp = f;
|
|
106
|
+
f = rb_funcall(f, id_plus, 1, l);
|
|
107
|
+
f = rb_funcall(f, id_div, 1, TWO);
|
|
108
|
+
l = rb_funcall(TWO, id_mul, 1, temp);
|
|
109
|
+
l = rb_funcall(l, id_plus, 1, f);
|
|
110
|
+
sign = MINUS_ONE;
|
|
132
111
|
}
|
|
133
|
-
|
|
134
|
-
|
|
112
|
+
mask = rb_funcall(mask, id_div, 1, TWO);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (rb_equal(rb_funcall(n, id_bit_and, 1, mask), ZERO)) {
|
|
116
|
+
f = rb_funcall(f, id_mul, 1, l);
|
|
117
|
+
} else {
|
|
118
|
+
f = rb_funcall(f, id_plus, 1, l);
|
|
119
|
+
f = rb_funcall(f, id_div, 1, TWO);
|
|
120
|
+
f = rb_funcall(f, id_mul, 1, l);
|
|
121
|
+
f = rb_funcall(f, id_minus, 1, sign);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return f;
|
|
135
125
|
}
|
|
136
126
|
|
|
137
|
-
static VALUE
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
temp = rb_funcall(rb_ary_entry(rb_ary_entry(ary1, i), k), id_mul,
|
|
162
|
-
1, rb_ary_entry(rb_ary_entry(ary2, k), j));
|
|
163
|
-
rb_ary_store(rb_ary_entry(tmp_ary, i), j, rb_funcall(temp, id_plus, 1, rb_ary_entry(rb_ary_entry(tmp_ary, i), j)));
|
|
164
|
-
}
|
|
165
|
-
}
|
|
127
|
+
static VALUE rb_matrix_mul(VALUE ary1, VALUE ary2) {
|
|
128
|
+
long i, j, k;
|
|
129
|
+
VALUE temp;
|
|
130
|
+
VALUE tmp_ary = rb_ary_new2(ARY_LEN);
|
|
131
|
+
VALUE zero_ary = rb_ary_new2(ARY_LEN);
|
|
132
|
+
|
|
133
|
+
rb_ary_push(zero_ary, ZERO);
|
|
134
|
+
rb_ary_push(zero_ary, ZERO);
|
|
135
|
+
rb_ary_push(tmp_ary, zero_ary);
|
|
136
|
+
|
|
137
|
+
zero_ary = rb_ary_new2(ARY_LEN);
|
|
138
|
+
rb_ary_push(zero_ary, ZERO);
|
|
139
|
+
rb_ary_push(zero_ary, ZERO);
|
|
140
|
+
rb_ary_push(tmp_ary, zero_ary);
|
|
141
|
+
|
|
142
|
+
for (i = 0; i < 2; i++) {
|
|
143
|
+
for (j = 0; j < 2; j++) {
|
|
144
|
+
for (k = 0; k < 2; k++) {
|
|
145
|
+
temp = rb_funcall(rb_ary_entry(rb_ary_entry(ary1, i), k), id_mul, 1,
|
|
146
|
+
rb_ary_entry(rb_ary_entry(ary2, k), j));
|
|
147
|
+
rb_ary_store(rb_ary_entry(tmp_ary, i), j,
|
|
148
|
+
rb_funcall(temp, id_plus, 1,
|
|
149
|
+
rb_ary_entry(rb_ary_entry(tmp_ary, i), j)));
|
|
150
|
+
}
|
|
166
151
|
}
|
|
152
|
+
}
|
|
167
153
|
|
|
168
|
-
|
|
154
|
+
return tmp_ary;
|
|
169
155
|
}
|
|
170
156
|
|
|
171
157
|
/* call-seq:
|
|
@@ -175,195 +161,131 @@ rb_matrix_mul(VALUE ary1, VALUE ary2)
|
|
|
175
161
|
*
|
|
176
162
|
* fib.matrix(10)
|
|
177
163
|
* #=> [[89, 55], [55, 34]]
|
|
178
|
-
*
|
|
179
|
-
* fib.matrix(100)
|
|
180
|
-
* #=> [[573147844013817084101, 354224848179261915075], [354224848179261915075,218922995834555169026]]
|
|
181
|
-
*
|
|
182
|
-
* arr = fib.matrix(15)
|
|
183
|
-
* #=> [[987, 610], [610, 377]]
|
|
184
|
-
*
|
|
185
|
-
* arr[0][1] or arr[1][0] is the value of nth term
|
|
186
|
-
*
|
|
187
|
-
* Refer to http://en.wikipedia.org/wiki/Fibonacci_number#Matrix_form
|
|
188
164
|
*/
|
|
165
|
+
static VALUE rb_matrix_form(VALUE self, VALUE n) {
|
|
166
|
+
VALUE base_ary, res_ary, tmp_ary;
|
|
189
167
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
VALUE res_ary;
|
|
195
|
-
VALUE tmp_ary;
|
|
196
|
-
long ary_len = 2;
|
|
197
|
-
|
|
198
|
-
if(TYPE(n) != T_FIXNUM)
|
|
199
|
-
{
|
|
200
|
-
rb_raise(rb_eArgError, "Invalid argument for type Fixnum");
|
|
201
|
-
return Qnil;
|
|
202
|
-
}
|
|
168
|
+
if (!fib_is_valid_index(n)) {
|
|
169
|
+
rb_raise(rb_eArgError, "Matrix index must be an integer");
|
|
170
|
+
return Qnil;
|
|
171
|
+
}
|
|
203
172
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
base_ary = rb_matrix_mul(base_ary, base_ary);
|
|
242
|
-
}
|
|
243
|
-
else
|
|
244
|
-
{
|
|
245
|
-
n = rb_funcall(n, id_minus, 1, ONE);
|
|
246
|
-
res_ary = rb_matrix_mul(res_ary, base_ary);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
173
|
+
if (fib_is_negative(n)) {
|
|
174
|
+
rb_raise(rb_eArgError, "Matrix index cannot be negative");
|
|
175
|
+
return Qnil;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
base_ary = rb_ary_new2(ARY_LEN);
|
|
179
|
+
res_ary = rb_ary_new2(ARY_LEN);
|
|
180
|
+
|
|
181
|
+
/* base is {{1, 1}, {1, 0}} */
|
|
182
|
+
tmp_ary = rb_ary_new2(ARY_LEN);
|
|
183
|
+
rb_ary_push(tmp_ary, ONE);
|
|
184
|
+
rb_ary_push(tmp_ary, ONE);
|
|
185
|
+
rb_ary_push(base_ary, tmp_ary);
|
|
186
|
+
|
|
187
|
+
tmp_ary = rb_ary_new2(ARY_LEN);
|
|
188
|
+
rb_ary_push(tmp_ary, ONE);
|
|
189
|
+
rb_ary_push(tmp_ary, ZERO);
|
|
190
|
+
rb_ary_push(base_ary, tmp_ary);
|
|
191
|
+
|
|
192
|
+
/* res is {{1, 0}, {0, 1}} */
|
|
193
|
+
tmp_ary = rb_ary_new2(ARY_LEN);
|
|
194
|
+
rb_ary_push(tmp_ary, ONE);
|
|
195
|
+
rb_ary_push(tmp_ary, ZERO);
|
|
196
|
+
rb_ary_push(res_ary, tmp_ary);
|
|
197
|
+
|
|
198
|
+
tmp_ary = rb_ary_new2(ARY_LEN);
|
|
199
|
+
rb_ary_push(tmp_ary, ZERO);
|
|
200
|
+
rb_ary_push(tmp_ary, ONE);
|
|
201
|
+
rb_ary_push(res_ary, tmp_ary);
|
|
202
|
+
|
|
203
|
+
while (!rb_equal(n, ZERO)) {
|
|
204
|
+
if (rb_equal(rb_funcall(n, id_mod, 1, TWO), ZERO)) {
|
|
205
|
+
n = rb_funcall(n, id_div, 1, TWO);
|
|
206
|
+
base_ary = rb_matrix_mul(base_ary, base_ary);
|
|
207
|
+
} else {
|
|
208
|
+
n = rb_funcall(n, id_minus, 1, ONE);
|
|
209
|
+
res_ary = rb_matrix_mul(res_ary, base_ary);
|
|
249
210
|
}
|
|
211
|
+
}
|
|
250
212
|
|
|
251
|
-
|
|
213
|
+
return res_ary;
|
|
252
214
|
}
|
|
253
215
|
|
|
254
216
|
/* call-seq:
|
|
255
217
|
* fib[n]
|
|
256
218
|
*
|
|
257
|
-
* Returns
|
|
219
|
+
* Returns the nth Fibonacci number (iterative calculation).
|
|
258
220
|
*
|
|
259
221
|
* fib[100]
|
|
260
222
|
* #=> 354224848179261915075
|
|
261
|
-
*
|
|
262
|
-
* fib[10]
|
|
263
|
-
* #=> 55
|
|
264
|
-
*
|
|
265
|
-
* fib[200]
|
|
266
|
-
* #=> 280571172992510140037611932413038677189525
|
|
267
|
-
*
|
|
268
|
-
* The value of nth term is calculated iteratively.
|
|
269
|
-
*
|
|
270
|
-
* Refer to http://en.wikipedia.org/wiki/Fibonacci_number#First_identity
|
|
271
223
|
*/
|
|
224
|
+
static VALUE rb_iterative_val(VALUE self, VALUE n) {
|
|
225
|
+
VALUE start = TWO;
|
|
226
|
+
VALUE fib_n_1 = ONE;
|
|
227
|
+
VALUE fib_n_2 = ZERO;
|
|
228
|
+
VALUE fib_n = ZERO;
|
|
229
|
+
|
|
230
|
+
if (!fib_is_valid_index(n)) {
|
|
231
|
+
rb_raise(rb_eArgError, "Index must be an integer");
|
|
232
|
+
return Qnil;
|
|
233
|
+
}
|
|
272
234
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
{
|
|
289
|
-
rb_raise(rb_eArgError, "n cannot be negative");
|
|
290
|
-
return Qnil;
|
|
235
|
+
if (fib_is_negative(n)) {
|
|
236
|
+
rb_raise(rb_eArgError, "Index cannot be negative");
|
|
237
|
+
return Qnil;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (fib_is_zero(n)) {
|
|
241
|
+
fib_n = ZERO;
|
|
242
|
+
} else if (rb_equal(n, ONE)) {
|
|
243
|
+
fib_n = ONE;
|
|
244
|
+
} else {
|
|
245
|
+
for (start; RTEST(rb_funcall(start, id_lte, 1, n));
|
|
246
|
+
start = rb_funcall(start, id_plus, 1, ONE)) {
|
|
247
|
+
fib_n = rb_funcall(fib_n_1, id_plus, 1, fib_n_2);
|
|
248
|
+
fib_n_2 = fib_n_1;
|
|
249
|
+
fib_n_1 = fib_n;
|
|
291
250
|
}
|
|
251
|
+
}
|
|
292
252
|
|
|
293
|
-
|
|
294
|
-
{
|
|
295
|
-
fib_n = ZERO;
|
|
296
|
-
}
|
|
297
|
-
else if(rb_equal(n, ONE))
|
|
298
|
-
{
|
|
299
|
-
fib_n = ONE;
|
|
300
|
-
}
|
|
301
|
-
else
|
|
302
|
-
{
|
|
303
|
-
for(start; RTEST(rb_funcall(start, id_lte, 1, n)); start = rb_funcall(start, id_plus, 1, ONE))
|
|
304
|
-
{
|
|
305
|
-
fib_n = rb_funcall(fib_n_1, id_plus, 1, fib_n_2);
|
|
306
|
-
fib_n_2 = fib_n_1;
|
|
307
|
-
fib_n_1 = fib_n;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return fib_n;
|
|
253
|
+
return fib_n;
|
|
311
254
|
}
|
|
312
255
|
|
|
313
256
|
/* call-seq:
|
|
314
257
|
* fib.terms(n)
|
|
315
258
|
*
|
|
316
|
-
* Returns
|
|
259
|
+
* Returns array with the first n terms of the series
|
|
317
260
|
*
|
|
318
261
|
* fib.terms(5)
|
|
319
262
|
* #=> [0, 1, 1, 2, 3]
|
|
320
|
-
*
|
|
321
|
-
* fib.terms(10)
|
|
322
|
-
* #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
|
|
323
|
-
*
|
|
324
|
-
* fib.terms(15)
|
|
325
|
-
* #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
|
|
326
|
-
*
|
|
327
|
-
* fib.terms(0)
|
|
328
|
-
* #=> []
|
|
329
|
-
*
|
|
330
|
-
* Refer to http://en.wikipedia.org/wiki/Fibonacci_number#First_identity
|
|
331
263
|
*/
|
|
264
|
+
static VALUE terms(VALUE self, VALUE n) {
|
|
265
|
+
long ary_len = NUM2LONG(n);
|
|
266
|
+
long i;
|
|
267
|
+
VALUE ary;
|
|
332
268
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
{
|
|
342
|
-
|
|
343
|
-
|
|
269
|
+
if (ary_len < 0) {
|
|
270
|
+
rb_raise(rb_eArgError, "Number of terms cannot be negative");
|
|
271
|
+
return Qnil;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
ary = rb_ary_new2(ary_len);
|
|
275
|
+
|
|
276
|
+
for (i = 0; i < ary_len; i++) {
|
|
277
|
+
if (i == 0) {
|
|
278
|
+
rb_ary_store(ary, i, ZERO);
|
|
279
|
+
} else if (i <= 2) {
|
|
280
|
+
rb_ary_store(ary, i, ONE);
|
|
281
|
+
} else {
|
|
282
|
+
rb_ary_store(ary, i,
|
|
283
|
+
rb_funcall(rb_ary_entry(ary, i - 1), id_plus, 1,
|
|
284
|
+
rb_ary_entry(ary, i - 2)));
|
|
344
285
|
}
|
|
286
|
+
}
|
|
345
287
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
for(i=0; i < ary_len; i++)
|
|
349
|
-
{
|
|
350
|
-
if(i == 0)
|
|
351
|
-
{
|
|
352
|
-
rb_ary_store(ary, i, ZERO);
|
|
353
|
-
}
|
|
354
|
-
if((i > 0))
|
|
355
|
-
{
|
|
356
|
-
if(i <= 2)
|
|
357
|
-
{
|
|
358
|
-
rb_ary_store(ary, i, ONE);
|
|
359
|
-
}
|
|
360
|
-
else
|
|
361
|
-
{
|
|
362
|
-
rb_ary_store(ary, i, rb_funcall(rb_ary_entry(ary, i-1), id_plus, 1, rb_ary_entry(ary, i-2)));
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
return ary;
|
|
288
|
+
return ary;
|
|
367
289
|
}
|
|
368
290
|
|
|
369
291
|
/* call-seq:
|
|
@@ -371,162 +293,133 @@ terms(VALUE self, VALUE n)
|
|
|
371
293
|
*
|
|
372
294
|
* Prints the first n terms of the series.
|
|
373
295
|
*
|
|
374
|
-
* fib.print(1)
|
|
375
|
-
* #=> 0
|
|
376
|
-
*
|
|
377
|
-
* fib.print(2)
|
|
378
|
-
* #=> 0
|
|
379
|
-
* 1
|
|
380
296
|
* fib.print(5)
|
|
381
297
|
* #=> 0
|
|
382
298
|
* 1
|
|
383
299
|
* 1
|
|
384
300
|
* 2
|
|
385
301
|
* 3
|
|
386
|
-
*
|
|
387
302
|
*/
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if(TYPE(n) != T_FIXNUM)
|
|
398
|
-
{
|
|
399
|
-
rb_raise(rb_eArgError, "Invalid argument for type Fixnum");
|
|
400
|
-
return Qnil;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if(RTEST(rb_funcall(n, id_lt, 1, ZERO)))
|
|
404
|
-
{
|
|
405
|
-
rb_raise(rb_eArgError, "n cannot be negative");
|
|
406
|
-
return Qnil;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
for(start; RTEST(rb_funcall(start, id_lt, 1, n)); start = rb_funcall(start, id_plus, 1, ONE))
|
|
410
|
-
{
|
|
411
|
-
if(rb_equal(start, ZERO))
|
|
412
|
-
{
|
|
413
|
-
rb_print_num(ZERO);
|
|
414
|
-
}
|
|
415
|
-
else if(rb_equal(start, ONE))
|
|
416
|
-
{
|
|
417
|
-
rb_print_num(ONE);
|
|
418
|
-
}
|
|
419
|
-
else
|
|
420
|
-
{
|
|
421
|
-
fib_n = rb_funcall(fib_n_1, id_plus, 1, fib_n_2);
|
|
422
|
-
fib_n_2 = fib_n_1;
|
|
423
|
-
fib_n_1 = fib_n;
|
|
424
|
-
rb_print_num(fib_n);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
303
|
+
static VALUE print_terms(VALUE self, VALUE n) {
|
|
304
|
+
VALUE start = ZERO;
|
|
305
|
+
VALUE fib_n_1 = ONE;
|
|
306
|
+
VALUE fib_n_2 = ZERO;
|
|
307
|
+
VALUE fib_n = ZERO;
|
|
308
|
+
|
|
309
|
+
if (!fib_is_valid_index(n)) {
|
|
310
|
+
rb_raise(rb_eArgError, "Argument must be an integer");
|
|
427
311
|
return Qnil;
|
|
428
|
-
}
|
|
312
|
+
}
|
|
429
313
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
{
|
|
314
|
+
if (fib_is_negative(n)) {
|
|
315
|
+
rb_raise(rb_eArgError, "Argument cannot be negative");
|
|
433
316
|
return Qnil;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
for (start; RTEST(rb_funcall(start, id_lt, 1, n));
|
|
320
|
+
start = rb_funcall(start, id_plus, 1, ONE)) {
|
|
321
|
+
if (rb_equal(start, ZERO)) {
|
|
322
|
+
fib_print_value(ZERO);
|
|
323
|
+
} else if (rb_equal(start, ONE)) {
|
|
324
|
+
fib_print_value(ONE);
|
|
325
|
+
} else {
|
|
326
|
+
fib_n = rb_funcall(fib_n_1, id_plus, 1, fib_n_2);
|
|
327
|
+
fib_n_2 = fib_n_1;
|
|
328
|
+
fib_n_1 = fib_n;
|
|
329
|
+
fib_print_value(fib_n);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return Qnil;
|
|
434
334
|
}
|
|
435
335
|
|
|
436
336
|
/* call-seq:
|
|
437
337
|
* fib.num_digits(n)
|
|
438
338
|
*
|
|
439
|
-
* Returns the number of digits in the nth
|
|
440
|
-
*
|
|
441
|
-
* fib.num_digits(10)
|
|
442
|
-
* #=> 2
|
|
339
|
+
* Returns the number of digits in the nth Fibonacci number
|
|
443
340
|
*
|
|
444
341
|
* fib.num_digits(100)
|
|
445
342
|
* #=> 21
|
|
446
|
-
*
|
|
447
|
-
* Refer to http://en.wikipedia.org/wiki/Fibonacci_number#Computation_by_rounding
|
|
448
343
|
*/
|
|
344
|
+
static VALUE num_digits(VALUE self, VALUE n) {
|
|
345
|
+
VALUE phi, num_digits, log_sqrt_5, sqrt_5;
|
|
449
346
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
{
|
|
455
|
-
rb_raise(rb_eArgError, "Invalid argument for type Fixnum");
|
|
456
|
-
return Qnil;
|
|
457
|
-
}
|
|
347
|
+
if (!fib_is_valid_index(n)) {
|
|
348
|
+
rb_raise(rb_eArgError, "Argument must be an integer");
|
|
349
|
+
return Qnil;
|
|
350
|
+
}
|
|
458
351
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
352
|
+
if (fib_is_negative(n)) {
|
|
353
|
+
rb_raise(rb_eArgError, "Argument cannot be negative");
|
|
354
|
+
return Qnil;
|
|
355
|
+
}
|
|
464
356
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
VALUE sqrt_5;
|
|
357
|
+
if (fib_is_zero(n)) {
|
|
358
|
+
return ZERO;
|
|
359
|
+
}
|
|
469
360
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
}
|
|
361
|
+
if (rb_equal(n, ONE)) {
|
|
362
|
+
return ONE;
|
|
363
|
+
}
|
|
474
364
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
{
|
|
479
|
-
return ONE;
|
|
480
|
-
}
|
|
365
|
+
if (!RTEST(rb_funcall(n, id_gte, 1, TWO))) {
|
|
366
|
+
return Qnil;
|
|
367
|
+
}
|
|
481
368
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
log_sqrt_5 = rb_funcall(rb_mMath, id_log10, 1, sqrt_5);
|
|
369
|
+
phi = ONE;
|
|
370
|
+
num_digits = ZERO;
|
|
371
|
+
log_sqrt_5 = ZERO;
|
|
486
372
|
|
|
487
|
-
|
|
488
|
-
|
|
373
|
+
sqrt_5 = rb_funcall(rb_mMath, id_sqrt, 1, INT2NUM(5));
|
|
374
|
+
log_sqrt_5 = rb_funcall(rb_mMath, id_log10, 1, sqrt_5);
|
|
489
375
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
num_digits = rb_funcall(num_digits, id_minus, 1, log_sqrt_5);
|
|
376
|
+
phi = rb_funcall(phi, id_plus, 1, sqrt_5);
|
|
377
|
+
phi = rb_funcall(phi, id_fdiv, 1, TWO);
|
|
493
378
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
379
|
+
num_digits = rb_funcall(rb_mMath, id_log10, 1, phi);
|
|
380
|
+
num_digits = rb_funcall(num_digits, id_mul, 1, n);
|
|
381
|
+
num_digits = rb_funcall(num_digits, id_minus, 1, log_sqrt_5);
|
|
382
|
+
num_digits = rb_funcall(num_digits, id_floor, 0);
|
|
383
|
+
num_digits = rb_funcall(num_digits, id_plus, 1, ONE);
|
|
384
|
+
num_digits = rb_funcall(num_digits, id_to_i, 0);
|
|
497
385
|
|
|
498
|
-
|
|
499
|
-
}
|
|
386
|
+
return num_digits;
|
|
500
387
|
}
|
|
501
388
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
389
|
+
static VALUE fibonacci_init(VALUE self) { return self; }
|
|
390
|
+
|
|
391
|
+
/* Initialize Ruby module and methods */
|
|
392
|
+
void Init_fibonacci_ext(void) {
|
|
393
|
+
/* Cache commonly used method IDs at initialization time */
|
|
394
|
+
id_plus = rb_intern("+");
|
|
395
|
+
id_lte = rb_intern("<=");
|
|
396
|
+
id_lt = rb_intern("<");
|
|
397
|
+
id_gte = rb_intern(">=");
|
|
398
|
+
id_pow = rb_intern("**");
|
|
399
|
+
id_mul = rb_intern("*");
|
|
400
|
+
id_minus = rb_intern("-");
|
|
401
|
+
id_fdiv = rb_intern("fdiv");
|
|
402
|
+
id_div = rb_intern("/");
|
|
403
|
+
id_to_i = rb_intern("to_i");
|
|
404
|
+
id_log10 = rb_intern("log10");
|
|
405
|
+
id_log2 = rb_intern("log2");
|
|
406
|
+
id_floor = rb_intern("floor");
|
|
407
|
+
id_sqrt = rb_intern("sqrt");
|
|
408
|
+
id_eq = rb_intern("==");
|
|
409
|
+
id_not_eq = rb_intern("!=");
|
|
410
|
+
id_mod = rb_intern("%");
|
|
411
|
+
id_bit_and = rb_intern("&");
|
|
412
|
+
id_to_s = rb_intern("to_s");
|
|
413
|
+
|
|
414
|
+
/* Define the Fibonacci class */
|
|
415
|
+
cFibonacci = rb_define_class("Fibonacci", rb_cObject);
|
|
416
|
+
|
|
417
|
+
/* Define instance methods */
|
|
418
|
+
rb_define_method(cFibonacci, "initialize", fibonacci_init, 0);
|
|
419
|
+
rb_define_method(cFibonacci, "print", print_terms, 1);
|
|
420
|
+
rb_define_method(cFibonacci, "terms", terms, 1);
|
|
421
|
+
rb_define_method(cFibonacci, "num_digits", num_digits, 1);
|
|
422
|
+
rb_define_method(cFibonacci, "[]", rb_iterative_val, 1);
|
|
423
|
+
rb_define_method(cFibonacci, "matrix", rb_matrix_form, 1);
|
|
424
|
+
rb_define_method(cFibonacci, "fast_val", rb_fast_val, 1);
|
|
532
425
|
}
|
data/lib/fibonacci/version.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
VERSION = "0.1.
|
|
1
|
+
VERSION = "0.1.10"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fibonacci
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- NagaChaitanya Vellanki
|
|
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
76
76
|
- !ruby/object:Gem::Version
|
|
77
77
|
version: '0'
|
|
78
78
|
requirements: []
|
|
79
|
-
rubygems_version: 4.0.
|
|
79
|
+
rubygems_version: 4.0.13
|
|
80
80
|
specification_version: 4
|
|
81
81
|
summary: Fibonacci
|
|
82
82
|
test_files:
|