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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92d83c1000268723f80d5fdd0567d04963c2c9553854f7f33bec822a49cf8a26
4
- data.tar.gz: ff9284bf3844d92b0febcba8b21ea148f22bc84c2c3e21af47475d5e56c48d86
3
+ metadata.gz: 308698f8ba3046c3c5739f458419a27d9737e749c2ab4f5bfdff9ea2c12828ca
4
+ data.tar.gz: 7e58056a369c590049551d87bbb241964932dcd676fd8b89f036ae6b00a00ec8
5
5
  SHA512:
6
- metadata.gz: 89c1528d25301f494f457b7a0ef1e20db05bf214b49bb0328f3bee4f1a429f9f7ae37144960ac241563f786443a3bbaed18de59599c14d5b12d5d2d4c27916fd
7
- data.tar.gz: f3dfc2f46a1250257b2fae4f8951bb7c013f3b341cbcd3325849a869c5b13ef3f71e9a78aa44f6c417ab65f40b6451806d5da531ff51ee9120a9ab20b4765b7c
6
+ metadata.gz: ed07c3ff1409a4d0daaf4dce7fc34c5eb51a27631ffe0eb9de0ce09d9445d4f26d482328861f1cacec171cb446bf889c2fc037212751e1d6e1128e93f7bd66bd
7
+ data.tar.gz: 51133cbf54f16a20481dee806b028f4efa077b9cf73653c5fa2bccd3e4205bc5b9e7b778ee85609eddfd9fff675e659d3c5fef3f612e7a00d0fdfb164757d131
@@ -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
- static VALUE
24
- fibonacci_init(VALUE self)
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
- static VALUE
30
- rb_print_num(VALUE num)
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
- static VALUE
60
- rb_fast_val(VALUE self, VALUE n)
61
- {
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
- }
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
- 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
76
- {
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))
86
- {
87
- return ONE;
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
- }
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
- return f;
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
- 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
- }
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
- return tmp_ary;
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
- static VALUE
191
- rb_matrix_form(VALUE self, VALUE n)
192
- {
193
- VALUE base_ary;
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
- 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
- }
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
- return res_ary;
213
+ return res_ary;
252
214
  }
253
215
 
254
216
  /* call-seq:
255
217
  * fib[n]
256
218
  *
257
- * Returns a Fixnum or Bignum.
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
- static VALUE
274
- rb_iterative_val(VALUE self, VALUE n)
275
- {
276
- VALUE start = TWO;
277
- VALUE fib_n_1 = ONE;
278
- VALUE fib_n_2 = ZERO;
279
- VALUE fib_n = ZERO;
280
-
281
- if(TYPE(n) != T_FIXNUM)
282
- {
283
- rb_raise(rb_eArgError, "Invalid argument for type Fixnum");
284
- return Qnil;
285
- }
286
-
287
- if(RTEST(rb_funcall(n, id_lt, 1, ZERO)))
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
- 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))
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 a array with the first n terms of the series
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
- static VALUE
334
- terms(VALUE self, VALUE n)
335
- {
336
- long ary_len = NUM2LONG(n);
337
- long i;
338
- VALUE ary = Qnil;
339
-
340
- if(ary_len < 0)
341
- {
342
- rb_raise(rb_eArgError, "num terms cannot be negative");
343
- return ary;
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
- ary = rb_ary_new2(ary_len);
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
- static VALUE
390
- print(VALUE self, VALUE n)
391
- {
392
- VALUE start = ZERO;
393
- VALUE fib_n_1 = ONE;
394
- VALUE fib_n_2 = ZERO;
395
- VALUE fib_n = ZERO;
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
- static VALUE
431
- index_of(VALUE self, VALUE val)
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 term of the series
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
- static VALUE
451
- num_digits(VALUE self, VALUE n)
452
- {
453
- if(TYPE(n) != T_FIXNUM)
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
- if(RTEST(rb_funcall(n, id_lt, 1, ZERO)))
460
- {
461
- rb_raise(rb_eArgError, "n cannot be negative");
462
- return Qnil;
463
- }
352
+ if (fib_is_negative(n)) {
353
+ rb_raise(rb_eArgError, "Argument cannot be negative");
354
+ return Qnil;
355
+ }
464
356
 
465
- VALUE phi = ONE;
466
- VALUE num_digits = ZERO;
467
- VALUE log_sqrt_5 = ZERO;
468
- VALUE sqrt_5;
357
+ if (fib_is_zero(n)) {
358
+ return ZERO;
359
+ }
469
360
 
470
- if(rb_equal(n, ZERO))
471
- {
472
- return ZERO;
473
- }
361
+ if (rb_equal(n, ONE)) {
362
+ return ONE;
363
+ }
474
364
 
475
- /* work around since the value log(phi/sqrt(5)) + 1 = 0.8595026380819693
476
- * converting to integer would be zero */
477
- if(rb_equal(n, ONE))
478
- {
479
- return ONE;
480
- }
365
+ if (!RTEST(rb_funcall(n, id_gte, 1, TWO))) {
366
+ return Qnil;
367
+ }
481
368
 
482
- if(RTEST(rb_funcall(n, id_gte, 1, TWO)))
483
- {
484
- sqrt_5 = rb_funcall(rb_mMath, id_sqrt, 1, INT2NUM(5));
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
- phi = rb_funcall(phi, id_plus, 1, sqrt_5);
488
- phi = rb_funcall(phi, id_fdiv, 1, TWO);
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
- num_digits = rb_funcall(rb_mMath, id_log10, 1, phi);
491
- num_digits = rb_funcall(num_digits, id_mul, 1, n);
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
- num_digits = rb_funcall(num_digits, id_floor, 0);
495
- num_digits = rb_funcall(num_digits, id_plus, 1, ONE);
496
- num_digits = rb_funcall(num_digits, id_to_i, 0);
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
- return num_digits;
499
- }
386
+ return num_digits;
500
387
  }
501
388
 
502
- void
503
- Init_fibonacci_ext(void)
504
- {
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);
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
  }
@@ -1 +1 @@
1
- VERSION = "0.1.9"
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.9
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.10
79
+ rubygems_version: 4.0.13
80
80
  specification_version: 4
81
81
  summary: Fibonacci
82
82
  test_files: