Math::BigInt::FastCalc v0.15
Tels [Sun, 27 May 2007 14:43:15 +0000 (14:43 +0000)]
Message-Id: <200705271443.16138@bloodgate.com>

p4raw-id: //depot/perl@31284

ext/Math/BigInt/FastCalc/FastCalc.pm
ext/Math/BigInt/FastCalc/FastCalc.xs
ext/Math/BigInt/FastCalc/Makefile.PL
ext/Math/BigInt/FastCalc/t/leak.t

index 3797def..af464f1 100644 (file)
@@ -11,7 +11,7 @@ use vars qw/@ISA $VERSION $BASE $BASE_LEN/;
 
 @ISA = qw(DynaLoader);
 
-$VERSION = '0.14';
+$VERSION = '0.15';
 
 bootstrap Math::BigInt::FastCalc $VERSION;
 
@@ -26,12 +26,12 @@ BEGIN
   # use Calc to override the methods that we do not provide in XS
 
   for my $method (qw/
-    new str
+    str
     add sub mul div
     rsft lsft
     mod modpow modinv
     gcd
-    pow root sqrt log_int fac
+    pow root sqrt log_int fac nok
     digit check
     from_hex from_bin from_oct as_hex as_bin as_oct
     zeros length base_len
index b00ed05..cd2ca4b 100644 (file)
@@ -20,6 +20,8 @@ MODULE = Math::BigInt::FastCalc               PACKAGE = Math::BigInt::FastCalc
  #  * added _is_two(), _is_ten(), _ten()
  # 2007-04-02 0.08 Tels
  #  * plug leaks by creating mortals
+ # 2007-05-27 0.09 Tels
+ #  * add _new()
 
 #define RETURN_MORTAL_INT(value)               \
       ST(0) = sv_2mortal(newSViv(value));      \
@@ -43,6 +45,58 @@ _set_XS_BASE(BASE, BASE_LEN)
     XS_BASE_LEN = SvIV(BASE_LEN); 
 
 ##############################################################################
+# _new
+
+AV *
+_new(class, x)
+  SV*  x
+  INIT:
+    STRLEN len;
+    char* cur;
+    int part_len;
+
+  CODE:
+    /* create the array */
+    RETVAL = newAV();
+    sv_2mortal((SV*)RETVAL);
+    /*  cur = SvPV(x, len); printf ("input '%s'\n", cur); */ 
+    if (SvIOK(x) && SvIV(x) < XS_BASE)
+      {
+      /* shortcut for integer arguments */
+      av_push (RETVAL, newSViv( SvIV(x) ));
+      }
+    else
+      {
+      /* split the input (as string) into XS_BASE_LEN long parts */
+      /* in perl:
+               [ reverse(unpack("a" . ($il % $BASE_LEN+1)
+               . ("a$BASE_LEN" x ($il / $BASE_LEN)), $_[1])) ];
+      */
+      cur = SvPV(x, len);                      /* convert to string & store length */
+      cur += len;                              /* doing "cur = SvEND(x)" does not work! */
+      # process the string from the back
+      while (len > 0)
+        {
+        /* use either BASE_LEN or the amount of remaining digits */
+        part_len = XS_BASE_LEN;
+        if (part_len > len)
+          {
+          part_len = len;
+          }
+        /* processed so many digits */
+        cur -= part_len;
+        len -= part_len;
+        /* printf ("part '%s' (part_len: %i, len: %i, BASE_LEN: %i)\n", cur, part_len, len, XS_BASE_LEN); */
+        if (part_len > 0)
+         {
+         av_push (RETVAL, newSVpvn(cur, part_len) );
+         }
+        }
+      }
+  OUTPUT:
+    RETVAL
+
+##############################################################################
 # _copy
 
 void
index b63213b..6307098 100644 (file)
@@ -6,7 +6,7 @@ WriteMakefile(
     'NAME'             => 'Math::BigInt::FastCalc',
     'VERSION_FROM'     => 'FastCalc.pm',
     'PREREQ_PM'                => {
-       'Math::BigInt' => 1.83,
+       'Math::BigInt' => 1.86,
     },
     INSTALLDIRS                => 'perl',
     PREREQ_FATAL       => 1,
index b9cc596..7de331a 100644 (file)
@@ -13,9 +13,11 @@ BEGIN
   $| = 1;
   chdir 't' if -d 't';
   unshift @INC, ('../lib', '../blib/arch');    # for running manually
-  plan tests => 20;
+  plan tests => 22;
   }
 
+use Math::BigInt::FastCalc;
+
 #############################################################################
 package Math::BigInt::FastCalc::LeakCheck;
 use base qw(Math::BigInt::FastCalc);
@@ -53,6 +55,9 @@ my $num_2 = Math::BigInt::FastCalc->_two();
 my $num_long   = Math::BigInt::FastCalc->_new("1234567890");
 my $num_long_2 = Math::BigInt::FastCalc->_new("12345678900987654321");
 
+is (Math::BigInt::FastCalc->_str($num_long), "1234567890");
+is (Math::BigInt::FastCalc->_str($num_long_2), "12345678900987654321");
+
 # to hit all possible code branches
 _test_acmp($num, $num);
 _test_acmp($num_10, $num_10);