6 double XS_BASE_LEN = 0;
8 MODULE = Math::BigInt::FastCalc PACKAGE = Math::BigInt::FastCalc
10 #############################################################################
11 # 2002-08-12 0.03 Tels unreleased
12 # * is_zero/is_one/is_odd/is_even/len work now (pass v1.61 tests)
13 # 2002-08-13 0.04 Tels unreleased
14 # * returns no/yes for is_foo() methods to be faster
15 # 2002-08-18 0.06alpha
16 # * added _num(), _inc() and _dec()
17 # 2002-08-25 0.06 Tels
18 # * added __strip_zeros(), _copy()
19 # 2004-08-13 0.07 Tels
20 # * added _is_two(), _is_ten(), _ten()
23 _set_XS_BASE(BASE, BASE_LEN)
29 XS_BASE_LEN = SvIV(BASE_LEN);
31 ##############################################################################
43 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
44 elems = av_len(a); /* number of elems in array */
45 a2 = (AV*)sv_2mortal((SV*)newAV());
46 av_extend (a2, elems); /* prepadd */
49 /* av_store( a2, elems, newSVsv( (SV*)*av_fetch(a, elems, 0) ) ); */
51 /* looking and trying to preserve IV is actually slower when copying */
52 /* temp = (SV*)*av_fetch(a, elems, 0);
55 av_store( a2, elems, newSViv( SvIV( (SV*)*av_fetch(a, elems, 0) )));
59 av_store( a2, elems, newSVnv( SvNV( (SV*)*av_fetch(a, elems, 0) )));
62 av_store( a2, elems, newSVnv( SvNV( (SV*)*av_fetch(a, elems, 0) )));
65 ST(0) = sv_2mortal( newRV_inc((SV*) a2) );
67 ##############################################################################
68 # __strip_zeros (also check for empty arrays from div)
80 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
81 elems = av_len(a); /* number of elems in array */
82 ST(0) = x; /* we return x */
85 av_push (a, newSViv(0)); /* correct empty arrays */
90 XSRETURN(1); /* nothing to do since only one elem */
95 temp = *av_fetch(a, index, 0); /* fetch ptr to current element */
104 index = elems - index;
112 ##############################################################################
113 # decrement (subtract one)
126 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
127 elems = av_len(a); /* number of elems in array */
128 ST(0) = x; /* we return x */
132 while (index <= elems)
134 temp = *av_fetch(a, index, 0); /* fetch ptr to current element */
135 sv_setnv (temp, SvNV(temp)-1);
138 break; /* early out */
140 sv_setnv (temp, MAX); /* overflow, so set this to $MAX */
143 /* do have more than one element? */
144 /* (more than one because [0] should be kept as single-element) */
147 temp = *av_fetch(a, elems, 0); /* fetch last element */
148 if (SvIV(temp) == 0) /* did last elem overflow? */
150 av_pop(a); /* yes, so shrink array */
151 /* aka remove leading zeros */
154 XSRETURN(1); /* return x */
156 ##############################################################################
157 # increment (add one)
170 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
171 elems = av_len(a); /* number of elems in array */
172 ST(0) = x; /* we return x */
176 while (index <= elems)
178 temp = *av_fetch(a, index, 0); /* fetch ptr to current element */
179 sv_setnv (temp, SvNV(temp)+1);
180 if (SvNV(temp) < BASE)
182 XSRETURN(1); /* return (early out) */
184 sv_setiv (temp, 0); /* overflow, so set this elem to 0 */
187 temp = *av_fetch(a, elems, 0); /* fetch last element */
188 if (SvIV(temp) == 0) /* did last elem overflow? */
190 av_push(a, newSViv(1)); /* yes, so extend array by 1 */
192 XSRETURN(1); /* return x */
194 ##############################################################################
195 # Make a number (scalar int/float) from a BigInt object
210 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
211 elems = av_len(a); /* number of elems in array */
213 if (elems == 0) /* only one element? */
215 ST(0) = *av_fetch(a, 0, 0); /* fetch first (only) element */
216 XSRETURN(1); /* return it */
218 fac = 1.0; /* factor */
222 while (index <= elems)
224 temp = *av_fetch(a, index, 0); /* fetch current element */
225 num += fac * SvNV(temp);
229 ST(0) = newSVnv(num);
231 ##############################################################################
240 av_push (a, newSViv( 0 )); /* zero */
241 ST(0) = newRV_noinc((SV*) a);
243 ##############################################################################
252 av_push (a, newSViv( 1 )); /* one */
253 ST(0) = newRV_noinc((SV*) a);
255 ##############################################################################
264 av_push (a, newSViv( 2 )); /* two */
265 ST(0) = newRV_noinc((SV*) a);
267 ##############################################################################
276 av_push (a, newSViv( 10 )); /* ten */
277 ST(0) = newRV_noinc((SV*) a);
279 ##############################################################################
289 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
290 temp = *av_fetch(a, 0, 0); /* fetch first element */
291 ST(0) = boolSV((SvIV(temp) & 1) == 0);
293 ##############################################################################
303 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
304 temp = *av_fetch(a, 0, 0); /* fetch first element */
305 ST(0) = boolSV((SvIV(temp) & 1) != 0);
307 ##############################################################################
317 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
321 XSRETURN(1); /* len != 1, can't be '1' */
323 temp = *av_fetch(a, 0, 0); /* fetch first element */
324 ST(0) = boolSV((SvIV(temp) == 1));
326 ##############################################################################
336 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
340 XSRETURN(1); /* len != 1, can't be '2' */
342 temp = *av_fetch(a, 0, 0); /* fetch first element */
343 ST(0) = boolSV((SvIV(temp) == 2));
345 ##############################################################################
355 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
359 XSRETURN(1); /* len != 1, can't be '10' */
361 temp = *av_fetch(a, 0, 0); /* fetch first element */
362 ST(0) = boolSV((SvIV(temp) == 10));
364 ##############################################################################
374 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
378 XSRETURN(1); /* len != 1, can't be '0' */
380 temp = *av_fetch(a, 0, 0); /* fetch first element */
381 ST(0) = boolSV((SvIV(temp) == 0));
383 ##############################################################################
395 a = (AV*)SvRV(x); /* ref to aray, don't check ref */
396 elems = av_len(a); /* number of elems in array */
397 temp = *av_fetch(a, elems, 0); /* fetch last element */
398 SvPV(temp, len); /* convert to string & store length */
399 len += (IV) XS_BASE_LEN * elems;
400 ST(0) = newSViv(len);
402 ##############################################################################
405 _acmp(class, cx, cy);
411 I32 elemsx, elemsy, diff;
420 array_x = (AV*)SvRV(cx); /* ref to aray, don't check ref */
421 array_y = (AV*)SvRV(cy); /* ref to aray, don't check ref */
422 elemsx = av_len(array_x);
423 elemsy = av_len(array_y);
424 diff = elemsx - elemsy; /* difference */
428 ST(0) = newSViv(1); /* len differs: X > Y */
433 ST(0) = newSViv(-1); /* len differs: X < Y */
436 /* both have same number of elements, so check length of last element
437 and see if it differes */
438 tempx = *av_fetch(array_x, elemsx, 0); /* fetch last element */
439 tempy = *av_fetch(array_y, elemsx, 0); /* fetch last element */
440 SvPV(tempx, lenx); /* convert to string & store length */
441 SvPV(tempy, leny); /* convert to string & store length */
442 diff_str = (I32)lenx - (I32)leny;
445 ST(0) = newSViv(1); /* same len, but first elems differs in len */
450 ST(0) = newSViv(-1); /* same len, but first elems differs in len */
453 /* same number of digits, so need to make a full compare */
457 tempx = *av_fetch(array_x, elemsx, 0); /* fetch curr x element */
458 tempy = *av_fetch(array_y, elemsx, 0); /* fetch curr y element */
459 diff_nv = SvNV(tempx) - SvNV(tempy);
476 ST(0) = newSViv(0); /* equal */