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