fibonacci 0.1.5 → 0.1.6
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.
- 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:
|