This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate:
authorNicholas Clark <nick@ccl4.org>
Sun, 5 Sep 2004 19:50:28 +0000 (19:50 +0000)
committerNicholas Clark <nick@ccl4.org>
Sun, 5 Sep 2004 19:50:28 +0000 (19:50 +0000)
[ 23142]
Subject: [perl #30609] [PATCH] BigInt v1.71 - first try
From: Tels <perl_dummy@bloodgate.com>
Date: Sat, 17 Jul 2004 16:22:57 +0200
Message-Id: <200407171622.58443@bloodgate.com>

[ 23152]
Upgrade to Cwd 2.20

[ 23168]
Upgrade to File::Spec 0.88.

[ 23171]
Upgrade to Math::BigInt v1.71.

[ 23202]
Subject: [PATCH] DB_File 1.810
From: "Paul Marquess" <Paul.Marquess@btinternet.com>
Date: Sat, 7 Aug 2004 15:22:09 +0100
Message-Id: <20040807142059.CTQC10838.mta10-svc.ntlworld.com@MARQUESSPT21>
p4raw-link: @23202 on //depot/perl: 32babee08ee923133079392c9eae66cc543e1115
p4raw-link: @23171 on //depot/perl: ae161977d1005f6fda2476d87af33f49d164cb96
p4raw-link: @23168 on //depot/perl: 5b2874358a4501aa172a431fb19da878b608622f
p4raw-link: @23152 on //depot/perl: 275e8705031e539ec9999f68482039d1bcfb1608
p4raw-link: @23142 on //depot/perl: 03874afe4126e47a07c482418278c13f14c14597

p4raw-id: //depot/maint-5.8/perl@23265
p4raw-branched: from //depot/perl@23264 'branch in' ext/Cwd/t/win32.t
p4raw-integrated: from //depot/perl@23264 'copy in'
lib/File/Spec/Win32.pm (@21239..) lib/Math/BigInt/t/bare_mbi.t
lib/Math/BigInt/t/bigintpm.inc lib/Math/BigInt/t/bigintpm.t
lib/Math/BigInt/t/sub_mbi.t (@22344..) ext/DB_File/Changes
ext/DB_File/DB_File.pm ext/DB_File/DB_File.xs
ext/DB_File/t/db-hash.t (@22970..) ext/Cwd/Cwd.xs (@22988..)
p4raw-integrated: from //depot/perl@23171 'copy in'
lib/Math/BigFloat.pm lib/Math/BigInt/t/bare_mbf.t
lib/Math/BigInt/t/bigfltpm.inc (@23142..)
p4raw-integrated: from //depot/perl@23168 'copy in' lib/File/Spec.pm
lib/File/Spec/t/Spec.t (@21974..)
p4raw-integrated: from //depot/perl@23152 'copy in' ext/Cwd/Changes
ext/Cwd/t/cwd.t lib/Cwd.pm (@23118..) 'merge in' MANIFEST
(@23079..)
p4raw-edited: from //depot/perl@23142 'edit in' lib/Math/BigInt.pm
(@22741..)
p4raw-integrated: from //depot/perl@23142 'ignore'
lib/Math/BigInt/Calc.pm (@22344..) lib/Math/BigInt/t/bigfltpm.t
lib/Math/BigInt/t/sub_mbf.t lib/Math/BigInt/t/with_sub.t
(@22491..)

25 files changed:
MANIFEST
ext/Cwd/Changes
ext/Cwd/Cwd.xs
ext/Cwd/t/cwd.t
ext/Cwd/t/win32.t [new file with mode: 0644]
ext/DB_File/Changes
ext/DB_File/DB_File.pm
ext/DB_File/DB_File.xs
ext/DB_File/t/db-hash.t
lib/Cwd.pm
lib/File/Spec.pm
lib/File/Spec/Win32.pm
lib/File/Spec/t/Spec.t
lib/Math/BigFloat.pm
lib/Math/BigInt.pm
lib/Math/BigInt/Calc.pm
lib/Math/BigInt/t/bare_mbf.t
lib/Math/BigInt/t/bare_mbi.t
lib/Math/BigInt/t/bigfltpm.inc
lib/Math/BigInt/t/bigfltpm.t
lib/Math/BigInt/t/bigintpm.inc
lib/Math/BigInt/t/bigintpm.t
lib/Math/BigInt/t/sub_mbf.t
lib/Math/BigInt/t/sub_mbi.t
lib/Math/BigInt/t/with_sub.t

index 15b826b..c6926e8 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -138,6 +138,7 @@ ext/Cwd/Cwd.xs                      Cwd extension external subroutines
 ext/Cwd/Makefile.PL            Cwd extension makefile maker
 ext/Cwd/t/cwd.t                        See if Cwd works
 ext/Cwd/t/taint.t              See if Cwd works with taint
+ext/Cwd/t/win32.t              See if Cwd works on Win32
 ext/Data/Dumper/Changes                Data pretty printer, changelog
 ext/Data/Dumper/Dumper.pm      Data pretty printer, module
 ext/Data/Dumper/Dumper.xs      Data pretty printer, externals
index f6974b8..0b7dd1f 100644 (file)
@@ -1,5 +1,18 @@
 Revision history for Perl extension Cwd.
 
+2.20  Thu Jul 22 08:23:53 CDT 2004
+
+ - On some implementations of perl on Win32, a memory leak (or worse?)
+   occurred when calling getdcwd().  This has been fixed. [PodMaster]
+
+ - Added tests for getdcwd() on Win32.
+
+ - Fixed a problem in the pure-perl implementation _perl_abs_path()
+   that caused a fatal error when run on plain files. [Nicholas Clark]
+   To exercise the appropriate test code on platforms that wouldn't
+   otherwise use _perl_abs_path(), run the tests with $ENV{PERL_CORE}
+   or $ENV{TEST_PERL_CWD_CODE} set.
+
 2.19  Thu Jul 15 08:32:18 CDT 2004
 
  - The abs_path($arg) fix from 2.18 didn't work for VMS, now it's
index fae3ef9..273ab2d 100644 (file)
@@ -424,10 +424,10 @@ PPCODE:
     else
         croak("Usage: getdcwd(DRIVE)");
 
-    /* Pass a NULL pointer as the second argument to have space allocated. */
-    if (dir = _getdcwd(drive, NULL, MAXPATHLEN)) {
+    New(0,dir,MAXPATHLEN,char);
+    if (_getdcwd(drive, dir, MAXPATHLEN)) {
         sv_setpvn(TARG, dir, strlen(dir));
-        free(dir);
+        Safefree(dir);
         SvPOK_only(TARG);
     }
     else
index 52427e6..2c7d6c5 100644 (file)
@@ -14,7 +14,12 @@ use warnings;
 use File::Spec;
 use File::Path;
 
-use Test::More tests => 24;
+use Test::More;
+
+my $tests = 24;
+my $EXTRA_ABSPATH_TESTS = $ENV{PERL_CORE} || $ENV{TEST_PERL_CWD_CODE};
+$tests += 3 if $EXTRA_ABSPATH_TESTS;
+plan tests => $tests;
 
 my $IsVMS = $^O eq 'VMS';
 my $IsMacOS = $^O eq 'MacOS';
@@ -129,7 +134,7 @@ rmtree($test_dirs[0], 0, 0);
 }
 
 SKIP: {
-    skip "no symlinks on this platform", 2 unless $Config{d_symlink};
+    skip "no symlinks on this platform", 2+$EXTRA_ABSPATH_TESTS unless $Config{d_symlink};
 
     mkpath([$Test_Dir], 0, 0777);
     symlink $Test_Dir, "linktest";
@@ -140,6 +145,7 @@ SKIP: {
 
     like($abs_path,      qr|$want$|);
     like($fast_abs_path, qr|$want$|);
+    like(Cwd::_perl_abs_path("linktest"), qr|$want$|) if $EXTRA_ABSPATH_TESTS;
 
     rmtree($test_dirs[0], 0, 0);
     unlink "linktest";
@@ -154,10 +160,14 @@ if ($ENV{PERL_CORE}) {
 my $path = 'cwd.t';
 path_ends_with(Cwd::abs_path($path), 'cwd.t', 'abs_path() can be invoked on a file');
 path_ends_with(Cwd::fast_abs_path($path), 'cwd.t', 'fast_abs_path() can be invoked on a file');
+path_ends_with(Cwd::_perl_abs_path($path), 'cwd.t', '_perl_abs_path() can be invoked on a file')
+  if $EXTRA_ABSPATH_TESTS;
 
 $path = File::Spec->catfile(File::Spec->updir, 't', $path);
 path_ends_with(Cwd::abs_path($path), 'cwd.t', 'abs_path() can be invoked on a file');
 path_ends_with(Cwd::fast_abs_path($path), 'cwd.t', 'fast_abs_path() can be invoked on a file');
+path_ends_with(Cwd::_perl_abs_path($path), 'cwd.t', '_perl_abs_path() can be invoked on a file')
+  if $EXTRA_ABSPATH_TESTS;
 
 
 #############################################
diff --git a/ext/Cwd/t/win32.t b/ext/Cwd/t/win32.t
new file mode 100644 (file)
index 0000000..f5fa20e
--- /dev/null
@@ -0,0 +1,29 @@
+#!./perl
+
+BEGIN {
+    chdir 't' if -d 't';
+    if ($ENV{PERL_CORE}) {
+        @INC = '../lib';
+    }
+}
+
+use Test::More;
+if( $^O eq 'MSWin32' ) {
+  plan tests => 3;
+} else {
+  plan skip_all => 'this is not win32';
+}
+
+use Cwd;
+ok 1;
+
+my $cdir = getdcwd('C:');
+like $cdir, qr{^C:};
+
+my $ddir = getdcwd('D:');
+if (defined $ddir) {
+  like $ddir, qr{^D:};
+} else {
+  # May not have a D: drive mounted
+  ok 1;
+}
index e74c3e2..89027d1 100644 (file)
@@ -1,5 +1,11 @@
 
 
+1.810 7th August 2004
+
+   * Fixed db-hash.t for Cygwin
+
+   * Added substr tests to db-hast.t
+
 1.809 20th June 2004
 
    * Merged core patch 22258
index 3f53d46..5ddac46 100644 (file)
@@ -1,8 +1,8 @@
 # DB_File.pm -- Perl 5 interface to Berkeley DB 
 #
 # written by Paul Marquess (pmqs@cpan.org)
-# last modified 20th June 2004
-# version 1.809
+# last modified 7th August 2004
+# version 1.810
 #
 #     Copyright (c) 1995-2004 Paul Marquess. All rights reserved.
 #     This program is free software; you can redistribute it and/or
@@ -165,7 +165,7 @@ our ($db_version, $use_XSLoader, $splice_end_array);
 use Carp;
 
 
-$VERSION = "1.809" ;
+$VERSION = "1.810" ;
 
 {
     local $SIG{__WARN__} = sub {$splice_end_array = "@_";};
index eb83670..8f6cec1 100644 (file)
@@ -3,8 +3,8 @@
  DB_File.xs -- Perl 5 interface to Berkeley DB 
 
  written by Paul Marquess <pmqs@cpan.org>
- last modified 20th June 2004
- version 1.809
+ last modified 7th August 2004
+ version 1.810
 
  All comments/suggestions/problems are welcome
 
         1.807 - no change
         1.808 - leak fixed in ParseOpenInfo
         1.809 - no change
+        1.810 - no change
 
 */
 
@@ -397,8 +398,9 @@ typedef DBT DBTKEY ;
 
 #define OutputValue(arg, name)                                         \
        { if (RETVAL == 0) {                                            \
+             SvGETMAGIC(arg) ;                                         \
              my_sv_setpvn(arg, name.data, name.size) ;                 \
-             TAINT;                                            \
+             TAINT;                                                    \
              SvTAINTED_on(arg);                                        \
              SvUTF8_off(arg);                                          \
              DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ;      \
@@ -408,12 +410,13 @@ typedef DBT DBTKEY ;
 #define OutputKey(arg, name)                                           \
        { if (RETVAL == 0)                                              \
          {                                                             \
+               SvGETMAGIC(arg) ;                                       \
                if (db->type != DB_RECNO) {                             \
                    my_sv_setpvn(arg, name.data, name.size);            \
                }                                                       \
                else                                                    \
                    sv_setiv(arg, (I32)*(I32*)name.data - 1);           \
-             TAINT;                                            \
+             TAINT;                                                    \
              SvTAINTED_on(arg);                                        \
              SvUTF8_off(arg);                                          \
              DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ;  \
index 86a64ff..018952f 100755 (executable)
@@ -23,7 +23,7 @@ BEGIN {
 use DB_File; 
 use Fcntl;
 
-print "1..161\n";
+print "1..166\n";
 
 unlink glob "__db.*";
 
@@ -877,14 +877,14 @@ EOM
 #
 #    ok(128, $@ =~ /^DB_File hash callback: recursion detected/);
 #    {
-#        local ($^W) = 0; #no warnings;
+#        no warnings;
 #        untie %hash;
 #    }
 #    unlink $Dfile;
 #}
 
-#ok(127,1);
-#ok(128,1);
+#ok(127, 1);
+#ok(128, 1);
 
 {
     # Check that two hash's don't interact
@@ -934,9 +934,11 @@ EOM
     tie %hash1, 'DB_File',$Dfile, undef;
     ok(133, $warn_count == 0);
     $warn_count = 0;
+    untie %hash1;
     unlink $Dfile;
     tie %hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, undef;
     ok(134, $warn_count == 0);
+    untie %hash1;
     unlink $Dfile;
     tie %hash1, 'DB_File',$Dfile, undef, undef;
     ok(135, $warn_count == 0);
@@ -1113,9 +1115,9 @@ EOM
 
     my %bad = () ;
     $key = '';
-    for ($status = $db->seq($key, $value, R_FIRST ) ;
+    for ($status = $db->seq(substr($key,0), substr($value,0), R_FIRST ) ;
          $status == 0 ;
-         $status = $db->seq($key, $value, R_NEXT ) ) {
+         $status = $db->seq(substr($key,0), substr($value,0), R_NEXT ) ) {
 
         #print "# key [$key] value [$value]\n" ;
         if (defined $remember{$key} && defined $value && 
@@ -1130,11 +1132,11 @@ EOM
     ok 157, keys %bad == 0 ;
     ok 158, keys %remember == 0 ;
 
-    print "# missing -- $key $value\n" while ($key, $value) = each %remember;
-    print "# bad     -- $key $value\n" while ($key, $value) = each %bad;
+    print "# missing -- $key=>$value\n" while ($key, $value) = each %remember;
+    print "# bad     -- $key=>$value\n" while ($key, $value) = each %bad;
 
     # Make sure this fix does not break code to handle an undef key
-    # Berkeley DB undef key is bron between versions 2.3.16 and 
+    # Berkeley DB undef key is broken between versions 2.3.16 and 3.1
     my $value = 'fred';
     $warned = '';
     $db->put(undef, $value) ;
@@ -1156,4 +1158,74 @@ EOM
     unlink $Dfile;
 }
 
+{
+   # Check filter + substr
+
+   use warnings ;
+   use strict ;
+   my (%h, $db) ;
+   my $Dfile = "xxy.db";
+   unlink $Dfile;
+
+   ok(162, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) );
+
+
+   {
+       $db->filter_fetch_key   (sub { lc $_ } );
+       $db->filter_store_key   (sub { uc $_ } );
+       $db->filter_fetch_value (sub { lc $_ } );
+       $db->filter_store_value (sub { uc $_ } );
+   }
+
+   $_ = 'fred';
+
+    # db-put with substr of key
+    my %remember = () ;
+    my $status = 0 ;
+    for my $ix ( 1 .. 2 )
+    {
+        my $key = $ix . "data" ;
+        my $value = "value$ix" ;
+        $remember{$key} = $value ;
+        $status += $db->put(substr($key,0), substr($value,0)) ;
+    }
+
+    ok 163, $status == 0 or print "# Status $status\n" ;
+
+    if (1)
+    {
+       $db->filter_fetch_key   (undef);
+       $db->filter_store_key   (undef);
+       $db->filter_fetch_value (undef);
+       $db->filter_store_value (undef);
+    }
+
+    my %bad = () ;
+    my $key = '';
+    my $value = '';
+    for ($status = $db->seq($key, $value, R_FIRST ) ;
+         $status == 0 ;
+         $status = $db->seq($key, $value, R_NEXT ) ) {
+
+        #print "# key [$key] value [$value]\n" ;
+        if (defined $remember{$key} && defined $value && 
+             $remember{$key} eq $value) {
+            delete $remember{$key} ;
+        }
+        else {
+            $bad{$key} = $value ;
+        }
+    }
+    
+    ok 164, $_ eq 'fred';
+    ok 165, keys %bad == 0 ;
+    ok 166, keys %remember == 0 ;
+
+    print "# missing -- $key $value\n" while ($key, $value) = each %remember;
+    print "# bad     -- $key $value\n" while ($key, $value) = each %bad;
+   undef $db ;
+   untie %h;
+   unlink $Dfile;
+}
+
 exit ;
index b0dad20..dc52b72 100644 (file)
@@ -1,5 +1,5 @@
 package Cwd;
-$VERSION = $VERSION = '2.19';
+$VERSION = $VERSION = '2.20';
 
 =head1 NAME
 
@@ -469,7 +469,8 @@ sub _perl_abs_path(;$)
         my ($dir, $file) = $start =~ m{^(.*)/(.+)$}
            or return cwd() . '/' . $start;
        
-       if (-l _) {
+       # Can't use "-l _" here, because the previous stat was a stat(), not an lstat().
+       if (-l $start) {
            my $link_target = readlink($start);
            die "Can't resolve link $start: $!" unless defined $link_target;
            
index b5f56d0..1e28205 100644 (file)
@@ -3,7 +3,8 @@ package File::Spec;
 use strict;
 use vars qw(@ISA $VERSION);
 
-$VERSION = '0.87';
+$VERSION = '0.88';
+$VERSION = eval $VERSION;
 
 my %module = (MacOS   => 'Mac',
              MSWin32 => 'Win32',
@@ -92,7 +93,7 @@ path.
 Concatenate two or more directory names to form a complete path ending
 with a directory. But remove the trailing slash from the resulting
 string, because it doesn't look good, isn't necessary and confuses
-OS2. Of course, if this is the root directory, don't cut off the
+OS/2. Of course, if this is the root directory, don't cut off the
 trailing slash :-)
 
     $path = File::Spec->catdir( @directories );
@@ -127,8 +128,8 @@ Returns a string representation of the root directory.
 Returns a string representation of the first writable directory from a
 list of possible temporary directories.  Returns the current directory
 if no writable temporary directories are found.  The list of directories
-checked depends on the platform; e.g. File::Spec::Unix checks $ENV{TMPDIR}
-(unless taint is on) and /tmp.
+checked depends on the platform; e.g. File::Spec::Unix checks C<$ENV{TMPDIR}>
+(unless taint is on) and F</tmp>.
 
     $tmpdir = File::Spec->tmpdir();
 
@@ -148,13 +149,13 @@ directory. (Does not strip symlinks, only '.', '..', and equivalents.)
 =item case_tolerant
 
 Returns a true or false value indicating, respectively, that alphabetic
-is not or is significant when comparing file specifications.
+case is not or is significant when comparing file specifications.
 
     $is_case_tolerant = File::Spec->case_tolerant();
 
 =item file_name_is_absolute
 
-Takes as argument a path and returns true if it is an absolute path.
+Takes as its argument a path, and returns true if it is an absolute path.
 
     $is_absolute = File::Spec->file_name_is_absolute( $path );
 
@@ -164,7 +165,7 @@ Mac OS (Classic).  It does consult the working environment for VMS
 
 =item path
 
-Takes no argument, returns the environment variable PATH (or the local
+Takes no argument.  Returns the environment variable C<PATH> (or the local
 platform's equivalent) as a list.
 
     @PATH = File::Spec->path();
@@ -182,8 +183,8 @@ with no concept of volume, returns '' for volume.
     ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
 
 For systems with no syntax differentiating filenames from directories, 
-assumes that the last file is a path unless $no_file is true or a 
-trailing separator or /. or /.. is present. On Unix this means that $no_file
+assumes that the last file is a path unless C<$no_file> is true or a
+trailing separator or F</.> or F</..> is present. On Unix, this means that C<$no_file>
 true makes this return ( '', $path, '' ).
 
 The directory portion may or may not be returned with a trailing '/'.
@@ -197,19 +198,19 @@ The opposite of L</catdir()>.
 
     @dirs = File::Spec->splitdir( $directories );
 
-$directories must be only the directory portion of the path on systems 
+C<$directories> must be only the directory portion of the path on systems 
 that have the concept of a volume or that have path syntax that differentiates
 files from directories.
 
 Unlike just splitting the directories on the separator, empty
 directory names (C<''>) can be returned, because these are significant
-on some OSs.
+on some OSes.
 
 =item catpath()
 
 Takes volume, directory and file portions and returns an entire path. Under
-Unix, $volume is ignored, and directory and file are concatenated.  A '/' is
-inserted if need be.  On other OSs, $volume is significant.
+Unix, C<$volume> is ignored, and directory and file are concatenated.  A '/' is
+inserted if need be.  On other OSes, C<$volume> is significant.
 
     $full_path = File::Spec->catpath( $volume, $directory, $file );
 
@@ -221,22 +222,22 @@ from the base path to the destination path:
     $rel_path = File::Spec->abs2rel( $path ) ;
     $rel_path = File::Spec->abs2rel( $path, $base ) ;
 
-If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
+If C<$base> is not present or '', then L<cwd()|Cwd> is used. If C<$base> is
 relative, then it is converted to absolute form using
 L</rel2abs()>. This means that it is taken to be relative to
 L<cwd()|Cwd>.
 
-On systems with the concept of volume, if $path and $base appear to be
+On systems with the concept of volume, if C<$path> and C<$base> appear to be
 on two different volumes, we will not attempt to resolve the two
-paths, and we will instead simply return $path.  Note that previous
-versions of this module ignored the volume of $base, which resulted in
+paths, and we will instead simply return C<$path>.  Note that previous
+versions of this module ignored the volume of C<$base>, which resulted in
 garbage results part of the time.
 
 On systems that have a grammar that indicates filenames, this ignores the 
-$base filename as well. Otherwise all path components are assumed to be
+C<$base> filename as well. Otherwise all path components are assumed to be
 directories.
 
-If $path is relative, it is converted to absolute form using L</rel2abs()>.
+If C<$path> is relative, it is converted to absolute form using L</rel2abs()>.
 This means that it is taken to be relative to L<cwd()|Cwd>.
 
 No checks against the filesystem are made.  On VMS, there is
@@ -252,21 +253,21 @@ Converts a relative path to an absolute path.
     $abs_path = File::Spec->rel2abs( $path ) ;
     $abs_path = File::Spec->rel2abs( $path, $base ) ;
 
-If $base is not present or '', then L<cwd()|Cwd> is used. If $base is relative, 
+If C<$base> is not present or '', then L<cwd()|Cwd> is used. If C<$base> is relative,
 then it is converted to absolute form using L</rel2abs()>. This means that it
 is taken to be relative to L<cwd()|Cwd>.
 
-On systems with the concept of volume, if $path and $base appear to be
+On systems with the concept of volume, if C<$path> and C<$base> appear to be
 on two different volumes, we will not attempt to resolve the two
-paths, and we will instead simply return $path.  Note that previous
-versions of this module ignored the volume of $base, which resulted in
+paths, and we will instead simply return C<$path>.  Note that previous
+versions of this module ignored the volume of C<$base>, which resulted in
 garbage results part of the time.
 
 On systems that have a grammar that indicates filenames, this ignores the 
-$base filename as well. Otherwise all path components are assumed to be
+C<$base> filename as well. Otherwise all path components are assumed to be
 directories.
 
-If $path is absolute, it is cleaned up and returned using L</canonpath()>.
+If C<$path> is absolute, it is cleaned up and returned using L</canonpath()>.
 
 No checks against the filesystem are made.  On VMS, there is
 interaction with the working environment, as logicals and
@@ -286,17 +287,21 @@ L<File::Spec::Unix>, L<File::Spec::Mac>, L<File::Spec::OS2>,
 L<File::Spec::Win32>, L<File::Spec::VMS>, L<File::Spec::Functions>,
 L<ExtUtils::MakeMaker>
 
-=head1 AUTHORS
-
-Kenneth Albanowski <kjahds@kjahds.com>, Andy Dougherty
-<doughera@lafayette.edu>, Andreas KE<ouml>nig
-<A.Koenig@franz.ww.TU-Berlin.DE>, Tim Bunce <Tim.Bunce@ig.co.uk.
-VMS support by Charles Bailey <bailey@newman.upenn.edu>.
-OS/2 support by Ilya Zakharevich <ilya@math.ohio-state.edu>.
-Mac support by Paul Schinder <schinder@pobox.com>, and Thomas Wegner
-<wegner_thomas@yahoo.com>.  abs2rel() and rel2abs() written by Shigio
-Yamaguchi <shigio@tamacom.com>, modified by Barrie Slaymaker
-<barries@slaysys.com>.  splitpath(), splitdir(), catpath() and
-catdir() by Barrie Slaymaker.
+=head1 AUTHOR
+
+Currently maintained by Ken Williams C<< <KWILLIAMS@cpan.org> >>.
+
+The vast majority of the code was written by
+Kenneth Albanowski C<< <kjahds@kjahds.com> >>,
+Andy Dougherty C<< <doughera@lafayette.edu> >>,
+Andreas KE<ouml>nig C<< <A.Koenig@franz.ww.TU-Berlin.DE> >>,
+Tim Bunce C<< <Tim.Bunce@ig.co.uk> >>.
+VMS support by Charles Bailey C<< <bailey@newman.upenn.edu> >>.
+OS/2 support by Ilya Zakharevich C<< <ilya@math.ohio-state.edu> >>.
+Mac support by Paul Schinder C<< <schinder@pobox.com> >>, and
+Thomas Wegner C<< <wegner_thomas@yahoo.com> >>.
+abs2rel() and rel2abs() written by Shigio Yamaguchi C<< <shigio@tamacom.com> >>,
+modified by Barrie Slaymaker C<< <barries@slaysys.com> >>.
+splitpath(), splitdir(), catpath() and catdir() by Barrie Slaymaker.
 
 =cut
index 1a91b95..0d60cfb 100644 (file)
@@ -5,7 +5,7 @@ use strict;
 use vars qw(@ISA $VERSION);
 require File::Spec::Unix;
 
-$VERSION = '1.4';
+$VERSION = '1.5';
 
 @ISA = qw(File::Spec::Unix);
 
@@ -201,7 +201,7 @@ sub splitpath {
                       (?:\\\\|//)[^\\/]+[\\/][^\\/]+
                   )?
                 )
-                ( (?:.*[\\\\/](?:\.\.?\Z(?!\n))?)? )
+                ( (?:.*[\\/](?:\.\.?\Z(?!\n))?)? )
                 (.*)
              }xs;
         $volume    = $1;
@@ -335,7 +335,9 @@ sub rel2abs {
     if ( ! $self->file_name_is_absolute( $path ) ) {
 
         if ( !defined( $base ) || $base eq '' ) {
-            $base = $self->_cwd() ;
+           require Cwd ;
+           $base = Cwd::getdcwd( ($self->splitpath( $path ))[0] ) if defined &Cwd::getdcwd ;
+           $base = $self->_cwd() unless defined $base ;
         }
         elsif ( ! $self->file_name_is_absolute( $base ) ) {
             $base = $self->rel2abs( $base ) ;
index 1c2dd6a..899d8dc 100644 (file)
@@ -7,6 +7,7 @@ use File::Spec @File::Spec::EXPORT_OK ;
 
 require File::Spec::Unix ;
 require File::Spec::Win32 ;
+require Cwd;
 
 eval {
    require VMS::Filespec ;
@@ -226,14 +227,14 @@ if ($^O eq 'MacOS') {
 [ "Win32->canonpath('/..\\')",          '\\'                  ],
 [ "Win32->can('_cwd')",                 '/CODE/'              ],
 
-# FakeWin32 subclass (see below) just sets CWD to C:\one\two
+# FakeWin32 subclass (see below) just sets CWD to C:\one\two and getdcwd('D') to D:\alpha\beta
 
 [ "FakeWin32->abs2rel('/t1/t2/t3','/t1/t2/t3')",     ''                       ],
 [ "FakeWin32->abs2rel('/t1/t2/t4','/t1/t2/t3')",     '..\\t4'                 ],
 [ "FakeWin32->abs2rel('/t1/t2','/t1/t2/t3')",        '..'                     ],
 [ "FakeWin32->abs2rel('/t1/t2/t3/t4','/t1/t2/t3')",  't4'                     ],
 [ "FakeWin32->abs2rel('/t4/t5/t6','/t1/t2/t3')",     '..\\..\\..\\t4\\t5\\t6' ],
-[ "FakeWin32->abs2rel('../t4','/t1/t2/t3')",         '..\\..\\..\\one\\t4'    ],
+[ "FakeWin32->abs2rel('../t4','/t1/t2/t3')",         '..\\..\\..\\one\\t4'    ],  # Uses _cwd()
 [ "FakeWin32->abs2rel('/','/t1/t2/t3')",             '..\\..\\..'             ],
 [ "FakeWin32->abs2rel('///','/t1/t2/t3')",           '..\\..\\..'             ],
 [ "FakeWin32->abs2rel('/.','/t1/t2/t3')",            '..\\..\\..'             ],
@@ -558,11 +559,37 @@ if ($^O eq 'MacOS') {
 
 ) ;
 
+if ($^O eq 'MSWin32') {
+  push @tests, [ "FakeWin32->rel2abs('D:foo.txt')", 'D:\\alpha\\beta\\foo.txt' ];
+}
+
+
 plan tests => scalar @tests;
 
 {
-    @File::Spec::FakeWin32::ISA = qw(File::Spec::Win32);
-    sub File::Spec::FakeWin32::_cwd { 'C:\\one\\two' }
+    package File::Spec::FakeWin32;
+    use vars qw(@ISA);
+    @ISA = qw(File::Spec::Win32);
+
+    sub _cwd { 'C:\\one\\two' }
+
+    # Some funky stuff to override Cwd::getdcwd() for testing purposes,
+    # in the limited scope of the rel2abs() method.
+    if ($Cwd::VERSION gt '2.17') {
+       local $^W;
+       *rel2abs = sub {
+           my $self = shift;
+           local $^W;
+           local *Cwd::getdcwd = sub {
+             return 'D:\alpha\beta' if $_[0] eq 'D:';
+             return 'C:\one\two'    if $_[0] eq 'C:';
+             return;
+           };
+           *Cwd::getdcwd = *Cwd::getdcwd; # Avoid a 'used only once' warning
+           return $self->SUPER::rel2abs(@_);
+       };
+       *rel2abs = *rel2abs; # Avoid a 'used only once' warning
+    }
 }
 
 
index f7008aa..dcd0d35 100644 (file)
@@ -12,14 +12,14 @@ package Math::BigFloat;
 #   _a : accuracy
 #   _p : precision
 
-$VERSION = '1.44';
+$VERSION = '1.45';
 require 5.005;
 
 require Exporter;
 @ISA =       qw(Exporter Math::BigInt);
 
 use strict;
-# $_trap_inf and $_trap_nan are internal and should never be accessed from the outside
+# $_trap_inf/$_trap_nan are internal and should never be accessed from outside
 use vars qw/$AUTOLOAD $accuracy $precision $div_scale $round_mode $rnd_mode
            $upgrade $downgrade $_trap_nan $_trap_inf/;
 my $class = "Math::BigFloat";
@@ -626,30 +626,7 @@ sub badd
   $x->bnorm()->round($a,$p,$r,$y);
   }
 
-sub bsub 
-  {
-  # (BigFloat or num_str, BigFloat or num_str) return BigFloat
-  # subtract second arg from first, modify first
-
-  # set up parameters
-  my ($self,$x,$y,$a,$p,$r) = (ref($_[0]),@_);
-  # objectify is costly, so avoid it
-  if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1])))
-    {
-    ($self,$x,$y,$a,$p,$r) = objectify(2,@_);
-    }
-
-  if ($y->is_zero())           # still round for not adding zero
-    {
-    return $x->round($a,$p,$r);
-    }
-  # $x - $y = -$x + $y 
-  $y->{sign} =~ tr/+-/-+/;     # does nothing for NaN
-  $x->badd($y,$a,$p,$r);       # badd does not leave internal zeros
-  $y->{sign} =~ tr/+-/-+/;     # refix $y (does nothing for NaN)
-  $x;                          # already rounded by badd()
-  }
+# sub bsub is inherited from Math::BigInt!
 
 sub binc
   {
@@ -1293,39 +1270,53 @@ sub bdiv
     # enough...
     $scale = abs($params[0] || $params[1]) + 4;        # take whatever is defined
     }
+
+  my $rem; $rem = $self->bzero() if wantarray;
+
+  $y = $self->new($y) unless $y->isa('Math::BigFloat');
+
   my $lx = $MBI->_len($x->{_m}); my $ly = $MBI->_len($y->{_m});
   $scale = $lx if $lx > $scale;
   $scale = $ly if $ly > $scale;
   my $diff = $ly - $lx;
   $scale += $diff if $diff > 0;                # if lx << ly, but not if ly << lx!
-    
-  # make copy of $x in case of list context for later reminder calculation
-  my $rem;
-  if (wantarray && !$y->is_one())
+  
+  # cases like $x /= $x (but not $x /= $y!) were wrong due to modifying $x
+  # twice below)
+  require Scalar::Util;
+  if (Scalar::Util::refaddr($x) == Scalar::Util::refaddr($y)) 
     {
-    $rem = $x->copy();
+    $x->bone();                                # x/x => 1, rem 0
     }
-
-  $x->{sign} = $x->{sign} ne $y->sign() ? '-' : '+'; 
-
-  # check for / +-1 ( +/- 1E0)
-  if (!$y->is_one())
+  else
     {
-    # promote BigInts and it's subclasses (except when already a BigFloat)
-    $y = $self->new($y) unless $y->isa('Math::BigFloat'); 
+    # make copy of $x in case of list context for later reminder calculation
+    if (wantarray && !$y->is_one())
+      {
+      $rem = $x->copy();
+      }
 
-    # calculate the result to $scale digits and then round it
-    # a * 10 ** b / c * 10 ** d => a/c * 10 ** (b-d)
-    $MBI->_lsft($x->{_m},$MBI->_new($scale),10);
-    $MBI->_div ($x->{_m},$y->{_m} );   # a/c
+    $x->{sign} = $x->{sign} ne $y->sign() ? '-' : '+'; 
 
-    ($x->{_e},$x->{_es}) = 
-     _e_sub($x->{_e}, $y->{_e}, $x->{_es}, $y->{_es});
-    # correct for 10**scale
-    ($x->{_e},$x->{_es}) = 
-      _e_sub($x->{_e}, $MBI->_new($scale), $x->{_es}, '+');
-    $x->bnorm();               # remove trailing 0's
-    }
+    # check for / +-1 ( +/- 1E0)
+    if (!$y->is_one())
+      {
+      # promote BigInts and it's subclasses (except when already a BigFloat)
+      $y = $self->new($y) unless $y->isa('Math::BigFloat'); 
+
+      # calculate the result to $scale digits and then round it
+      # a * 10 ** b / c * 10 ** d => a/c * 10 ** (b-d)
+      $MBI->_lsft($x->{_m},$MBI->_new($scale),10);
+      $MBI->_div ($x->{_m},$y->{_m});  # a/c
+
+      # correct exponent of $x
+      ($x->{_e},$x->{_es}) = _e_sub($x->{_e}, $y->{_e}, $x->{_es}, $y->{_es});
+      # correct for 10**scale
+      ($x->{_e},$x->{_es}) = _e_sub($x->{_e}, $MBI->_new($scale), $x->{_es}, '+');
+      $x->bnorm();             # remove trailing 0's
+      }
+    } # ende else $x != $y
 
   # shortcut to not run through _find_round_parameters again
   if (defined $params[0])
@@ -1343,17 +1334,13 @@ sub bdiv
     # clear a/p after round, since user did not request it
     delete $x->{_a}; delete $x->{_p};
     }
-  
+
   if (wantarray)
     {
     if (!$y->is_one())
       {
       $rem->bmod($y,@params);                  # copy already done
       }
-    else
-      {
-      $rem = $self->bzero();
-      }
     if ($fallback)
       {
       # clear a/p after round, since user did not request it
@@ -1839,7 +1826,7 @@ sub _pow
 
   $below = $v->copy();
   $over = $u->copy();
+
   $limit = $self->new("1E-". ($scale-1));
   #my $steps = 0;
   while (3 < 5)
@@ -1893,12 +1880,16 @@ sub bpow
 
   return $x if $x->{sign} =~ /^[+-]inf$/;
   return $x->bnan() if $x->{sign} eq $nan || $y->{sign} eq $nan;
-  return $x->bone() if $y->is_zero();
+
+  # cache the result of is_zero
+  my $y_is_zero = $y->is_zero();
+  return $x->bone() if $y_is_zero;
   return $x         if $x->is_one() || $y->is_one();
 
-  return $x->_pow($y,$a,$p,$r) if !$y->is_int();       # non-integer power
+  my $x_is_zero = $x->is_zero();
+  return $x->_pow($y,$a,$p,$r) if !$x_is_zero && !$y->is_int();        # non-integer power
 
-  my $y1 = $y->as_number()->{value};                   # make CALC
+  my $y1 = $y->as_number()->{value};                   # make MBI part
 
   # if ($x == -1)
   if ($x->{sign} eq '-' && $MBI->_is_one($x->{_m}) && $MBI->_is_zero($x->{_e}))
@@ -1906,27 +1897,27 @@ sub bpow
     # if $x == -1 and odd/even y => +1/-1  because +-1 ^ (+-1) => +-1
     return $MBI->_is_odd($y1) ? $x : $x->babs(1);
     }
-  if ($x->is_zero())
+  if ($x_is_zero)
     {
-    return $x->bone() if $y->is_zero();
+    return $x->bone() if $y_is_zero;
     return $x if $y->{sign} eq '+';    # 0**y => 0 (if not y <= 0)
     # 0 ** -y => 1 / (0 ** y) => 1 / 0! (1 / 0 => +inf)
     return $x->binf();
     }
 
   my $new_sign = '+';
-  $new_sign = $y->is_odd() ? '-' : '+' if ($x->{sign} ne '+');
+  $new_sign = $MBI->_is_odd($y1) ? '-' : '+' if $x->{sign} ne '+';
 
   # calculate $x->{_m} ** $y and $x->{_e} * $y separately (faster)
   $x->{_m} = $MBI->_pow( $x->{_m}, $y1);
-  $MBI->_mul ($x->{_e}, $y1);
+  $x->{_e} = $MBI->_mul ($x->{_e}, $y1);
 
   $x->{sign} = $new_sign;
   $x->bnorm();
   if ($y->{sign} eq '-')
     {
     # modify $x in place!
-    my $z = $x->copy(); $x->bzero()->binc();
+    my $z = $x->copy(); $x->bone();
     return $x->bdiv($z,$a,$p,$r);      # round in one go (might ignore y's A!)
     }
   $x->round($a,$p,$r,$y);
@@ -2039,7 +2030,7 @@ sub bfround
        }
     }
   # pass sign to bround for rounding modes '+inf' and '-inf'
-  my $m = Math::BigInt->new( $x->{sign} . $MBI->_str($x->{_m}));
+  my $m = bless { sign => $x->{sign}, value => $x->{_m} }, 'Math::BigInt';
   $m->bround($scale,$mode);
   $x->{_m} = $m->{value};                      # get our mantissa back
   $x->bnorm();
@@ -2080,7 +2071,7 @@ sub bround
     }
 
   # pass sign to bround for '+inf' and '-inf' rounding modes
-  my $m = Math::BigInt->new( $x->{sign} . $MBI->_str($x->{_m}));
+  my $m = bless { sign => $x->{sign}, value => $x->{_m} }, 'Math::BigInt';
 
   $m->bround($scale,$mode);            # round mantissa
   $x->{_m} = $m->{value};              # get our mantissa back
index 7393b12..25fb8f8 100644 (file)
@@ -18,7 +18,7 @@ package Math::BigInt;
 my $class = "Math::BigInt";
 require 5.005;
 
-$VERSION = '1.70';
+$VERSION = '1.71';
 use Exporter;
 @ISA =       qw( Exporter );
 @EXPORT_OK = qw( objectify bgcd blcm); 
@@ -1140,6 +1140,14 @@ sub bsub
     return $x;
     }
 
+  require Scalar::Util;
+  if (Scalar::Util::refaddr($x) == Scalar::Util::refaddr($y)) 
+    {
+    # if we get the same variable twice, the result must be zero (the code
+    # below fails in that case)
+    return $x->bzero(@r) if $x->{sign} =~ /^[+-]$/;
+    return $x->bnan();          # NaN, -inf, +inf
+    }
   $y->{sign} =~ tr/+\-/-+/;    # does nothing for NaN
   $x->badd($y,@r);             # badd does not leave internal zeros
   $y->{sign} =~ tr/+\-/-+/;    # refix $y (does nothing for NaN)
@@ -2027,17 +2035,15 @@ sub bfround
 
 sub _scan_for_nonzero
   {
-  # internal, used by bround()
-  my ($x,$pad,$xs) = @_;
+  # internal, used by bround() to scan for non-zeros after a '5'
+  my ($x,$pad,$xs,$len) = @_;
  
-  my $len = $x->length();
-  return 0 if $len == 1;               # '5' is trailed by invisible zeros
+  return 0 if $len == 1;               # "5" is trailed by invisible zeros
   my $follow = $pad - 1;
   return 0 if $follow > $len || $follow < 1;
 
-  # since we do not know underlying represention of $x, use decimal string
-  my $r = substr ("$x",-$follow);
-  $r =~ /[^0]/ ? 1 : 0;
+  # use the string form to check whether only '0's follow or not
+  substr ($xs,-$follow) =~ /[^0]/ ? 1 : 0;
   }
 
 sub fround
@@ -2087,8 +2093,8 @@ sub bround
   $pad = $len - $scale;
   $pad = abs($scale-1) if $scale < 0;
 
-  # do not use digit(), it is costly for binary => decimal
-
+  # do not use digit(), it is very costly for binary => decimal
+  # getting the entire string is also costly, but we need to do it only once
   my $xs = $CALC->_str($x->{value});
   my $pl = -$pad-1;
 
@@ -2106,7 +2112,7 @@ sub bround
     ($digit_after =~ /[01234]/)                        ||      # round down anyway,
                                                        # 6789 => round up
     ($digit_after eq '5')                      &&      # not 5000...0000
-    ($x->_scan_for_nonzero($pad,$xs) == 0)             &&
+    ($x->_scan_for_nonzero($pad,$xs,$len) == 0)                &&
     (
      ($mode eq 'even') && ($digit_round =~ /[24680]/) ||
      ($mode eq 'odd')  && ($digit_round =~ /[13579]/) ||
@@ -2118,8 +2124,8 @@ sub bround
        
   if (($pad > 0) && ($pad <= $len))
     {
-    substr($xs,-$pad,$pad) = '0' x $pad;
-    $put_back = 1;
+    substr($xs,-$pad,$pad) = '0' x $pad;               # replace with '00...'
+    $put_back = 1;                                     # need to put back
     }
   elsif ($pad > $len)
     {
@@ -2128,7 +2134,7 @@ sub bround
 
   if ($round_up)                                       # what gave test above?
     {
-    $put_back = 1;
+    $put_back = 1;                                     # need to put back
     $pad = $len, $xs = '0' x $pad if $scale < 0;       # tlr: whack 0.51=>1.0  
 
     # we modify directly the string variant instead of creating a number and
@@ -2143,7 +2149,7 @@ sub bround
     $xs = '1'.$xs if $c == 0;
 
     }
-  $x->{value} = $CALC->_new($xs) if $put_back == 1;    # put back in if needed
+  $x->{value} = $CALC->_new($xs) if $put_back == 1;    # put back, if needed
 
   $x->{_a} = $scale if $scale >= 0;
   if ($scale < 0)
index f2f0c87..f2bcc92 100644 (file)
@@ -6,7 +6,7 @@ use strict;
 
 use vars qw/$VERSION/;
 
-$VERSION = '0.40';
+$VERSION = '0.41';
 
 # Package to store unsigned big integers in decimal and do math with them
 
@@ -97,6 +97,21 @@ sub _base_len
   return ($BASE_LEN, $AND_BITS, $XOR_BITS, $OR_BITS, $BASE_LEN_SMALL, $MAX_VAL);
   }
 
+sub _new
+  {
+  # (ref to string) return ref to num_array
+  # Convert a number from string format (without sign) to internal base
+  # 1ex format. Assumes normalized value as input.
+  my $il = length($_[1])-1;
+
+  # < BASE_LEN due len-1 above
+  return [ int($_[1]) ] if $il < $BASE_LEN;    # shortcut for short numbers
+
+  # this leaves '00000' instead of int 0 and will be corrected after any op
+  [ reverse(unpack("a" . ($il % $BASE_LEN+1) 
+    . ("a$BASE_LEN" x ($il / $BASE_LEN)), $_[1])) ];
+  }                                                                             
+
 BEGIN
   {
   # from Daniel Pfeiffer: determine largest group of digits that is precisely
@@ -123,28 +138,7 @@ BEGIN
 
   use integer;
 
-  ############################################################################
-  # the next block is no longer important
-
-  ## this below detects 15 on a 64 bit system, because after that it becomes
-  ## 1e16  and not 1000000 :/ I can make it detect 18, but then I get a lot of
-  ## test failures. Ugh! (Tomake detect 18: uncomment lines marked with *)
-
-  #my $bi = 5;                 # approx. 16 bit
-  #$num = int('9' x $bi);
-  ## $num = 99999; # *
-  ## while ( ($num+$num+1) eq '1' . '9' x $bi) # *
-  #while ( int($num+$num+1) eq '1' . '9' x $bi)
-  #  {
-  #  $bi++; $num = int('9' x $bi);
-  #  # $bi++; $num *= 10; $num += 9;   # *
-  #  }
-  #$bi--;                              # back off one step
-  # by setting them equal, we ignore the findings and use the default
-  # one-size-fits-all approach from former versions
-  my $bi = $e;                         # XXX, this should work always
-
-  __PACKAGE__->_base_len($e,$bi);      # set and store
+  __PACKAGE__->_base_len($e);  # set and store
 
   # find out how many bits _and, _or and _xor can take (old default = 16)
   # I don't think anybody has yet 128 bit scalars, so let's play safe.
@@ -179,32 +173,13 @@ BEGIN
     } while ($OR_BITS < $max && $x == $z && $y == $x);
   $OR_BITS --;                                         # retreat one step
   
-  }
-
-###############################################################################
-
-sub _new
-  {
-  # (ref to string) return ref to num_array
-  # Convert a number from string format (without sign) to internal base
-  # 1ex format. Assumes normalized value as input.
-  my $il = length($_[1])-1;
-
-  # < BASE_LEN due len-1 above
-  return [ int($_[1]) ] if $il < $BASE_LEN;    # shortcut for short numbers
-
-  # this leaves '00000' instead of int 0 and will be corrected after any op
-  [ reverse(unpack("a" . ($il % $BASE_LEN+1) 
-    . ("a$BASE_LEN" x ($il / $BASE_LEN)), $_[1])) ];
-  }                                                                             
-  
-BEGIN
-  {
   $AND_MASK = __PACKAGE__->_new( ( 2 ** $AND_BITS ));
   $XOR_MASK = __PACKAGE__->_new( ( 2 ** $XOR_BITS ));
   $OR_MASK = __PACKAGE__->_new( ( 2 ** $OR_BITS ));
   }
 
+###############################################################################
+
 sub _zero
   {
   # create a zero
@@ -328,7 +303,7 @@ sub _inc
     return $x if (($i += 1) < $BASE);          # early out
     $i = 0;                                    # overflow, next
     }
-  push @$x,1 if ($x->[-1] == 0);               # last overflowed, so extend
+  push @$x,1 if (($x->[-1] || 0) == 0);                # last overflowed, so extend
   $x;
   }                                                                             
 
@@ -968,7 +943,7 @@ sub _digit
   
   my $elem = int($n / $BASE_LEN);      # which array element
   my $digit = $n % $BASE_LEN;          # which digit in this element
-  $elem = '0000'.@$x[$elem];           # get element padded with 0's
+  $elem = '0000000'.@$x[$elem];                # get element padded with 0's
   substr($elem,-$digit-1,1);
   }
 
@@ -1761,11 +1736,7 @@ sub _as_hex
   my ($c,$x) = @_;
 
   # fit's into one element (handle also 0x0 case)
-  if (@$x == 1)
-    {
-    my $t = sprintf("0x%x",$x->[0]);
-    return $t;
-    }
+  return sprintf("0x%x",$x->[0]) if @$x == 1;
 
   my $x1 = _copy($c,$x);
 
@@ -1779,7 +1750,6 @@ sub _as_hex
     {
     $x10000 = [ 0x1000 ]; $h = 'h3';
     }
-  # while (! _is_zero($c,$x1))
   while (@$x1 != 1 || $x1->[0] != 0)           # _is_zero()
     {
     ($x1, $xr) = _div($c,$x1,$x10000);
@@ -1787,8 +1757,7 @@ sub _as_hex
     }
   $es = reverse $es;
   $es =~ s/^[0]+//;   # strip leading zeros
-  $es = '0x' . $es;
-  $es;
+  '0x' . $es;                                  # return result prepended with 0x
   }
 
 sub _as_bin
@@ -1819,7 +1788,6 @@ sub _as_bin
     {
     $x10000 = [ 0x1000 ]; $b = 'b12';
     }
-  # while (! _is_zero($c,$x1))
   while (!(@$x1 == 1 && $x1->[0] == 0))                # _is_zero()
     {
     ($x1, $xr) = _div($c,$x1,$x10000);
@@ -1828,8 +1796,7 @@ sub _as_bin
     }
   $es = reverse $es;
   $es =~ s/^[0]+//;   # strip leading zeros
-  $es = '0b' . $es;
-  $es;
+  '0b' . $es;                                  # return result prepended with 0b
   }
 
 sub _from_hex
@@ -1837,19 +1804,26 @@ sub _from_hex
   # convert a hex number to decimal (ref to string, return ref to array)
   my ($c,$hs) = @_;
 
+  my $m = [ 0x10000000 ];                      # 28 bit at a time (<32 bit!)
+  my $d = 7;                                   # 7 digits at a time
+  if ($] <= 5.006)
+    {
+    # for older Perls, play safe
+    $m = [ 0x10000 ];                          # 16 bit at a time (<32 bit!)
+    $d = 4;                                    # 4 digits at a time
+    }
+
   my $mul = _one();
-  my $m = [ 0x10000 ];                         # 16 bit at a time
   my $x = _zero();
 
-  my $len = length($hs)-2;
-  $len = int($len/4);                          # 4-digit parts, w/o '0x'
-  my $val; my $i = -4;
+  my $len = int( (length($hs)-2)/$d );         # $d digit parts, w/o the '0x'
+  my $val; my $i = -$d;
   while ($len >= 0)
     {
-    $val = substr($hs,$i,4);
+    $val = substr($hs,$i,$d);                  # get hex digits
     $val =~ s/^[+-]?0x// if $len == 0;         # for last part only because
     $val = hex($val);                          # hex does not like wrong chars
-    $i -= 4; $len --;
+    $i -= $d; $len --;
     _add ($c, $x, _mul ($c, [ $val ], $mul ) ) if $val != 0;
     _mul ($c, $mul, $m ) if $len >= 0;                 # skip last mul
     }
@@ -1868,9 +1842,9 @@ sub _from_bin
   $hs =~ s/^[+-]?0b//;                                 # remove sign and 0b
   my $l = length($hs);                                 # bits
   $hs = '0' x (8-($l % 8)) . $hs if ($l % 8) != 0;     # padd left side w/ 0
-  my $h = unpack('H*', pack ('B*', $hs));              # repack as hex
+  my $h = '0x' . unpack('H*', pack ('B*', $hs));       # repack as hex
   
-  $c->_from_hex('0x'.$h);
+  $c->_from_hex($h);
   }
 
 ##############################################################################
@@ -1903,8 +1877,7 @@ sub _modinv
   # if the gcd is not 1, then return NaN
   return (undef,undef) unless _is_one($c,$a);
  
-  $sign = $sign == 1 ? '+' : '-';
-  ($u1,$sign);
+  ($u1, $sign == 1 ? '+' : '-');
   }
 
 sub _modpow
index cbca372..999604c 100644 (file)
@@ -27,7 +27,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 1815;
+  plan tests => 1837;
   }
 
 use Math::BigFloat lib => 'BareCalc';
index 6514e1e..4f8b0ae 100644 (file)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 2832;
+  plan tests => 2848;
   }
 
 use Math::BigInt lib => 'BareCalc';
index 5e1c19f..8a621f7 100644 (file)
@@ -257,6 +257,49 @@ ok ($class->new(-1)->is_one('-'),1);
 
 ok ($class->new(1)->fdiv('0.5')->bsstr(),'2e+0');
 
+###############################################################################
+# [perl #30609] bug with $x -= $x not beeing 0, but 2*$x
+
+$x = $class->new(3);  $x -= $x; ok ($x, 0);
+$x = $class->new(-3); $x -= $x; ok ($x, 0);
+$x = $class->new(3);  $x += $x; ok ($x, 6);
+$x = $class->new(-3); $x += $x; ok ($x, -6);
+
+$x = $class->new('NaN'); $x -= $x; ok ($x->is_nan(), 1);
+$x = $class->new('inf'); $x -= $x; ok ($x->is_nan(), 1);
+$x = $class->new('-inf'); $x -= $x; ok ($x->is_nan(), 1);
+
+$x = $class->new('NaN'); $x += $x; ok ($x->is_nan(), 1);
+$x = $class->new('inf'); $x += $x; ok ($x->is_inf(), 1);
+$x = $class->new('-inf'); $x += $x; ok ($x->is_inf('-'), 1);
+
+$x = $class->new('3.14');  $x -= $x; ok ($x, 0);
+$x = $class->new('-3.14'); $x -= $x; ok ($x, 0);
+$x = $class->new('3.14');  $x += $x; ok ($x, '6.28');
+$x = $class->new('-3.14'); $x += $x; ok ($x, '-6.28');
+
+$x = $class->new('3.14');  $x *= $x; ok ($x, '9.8596');
+$x = $class->new('-3.14'); $x *= $x; ok ($x, '9.8596');
+$x = $class->new('3.14');  $x /= $x; ok ($x, '1');
+$x = $class->new('-3.14'); $x /= $x; ok ($x, '1');
+$x = $class->new('3.14');  $x %= $x; ok ($x, '0');
+$x = $class->new('-3.14'); $x %= $x; ok ($x, '0');
+
+###############################################################################
+# the following two were reported by "kenny" via hotmail.com:
+
+#perl -MMath::BigFloat -wle 'print Math::BigFloat->new(0)->bpow(".1")'
+#Use of uninitialized value in numeric le (<=) at BigFloat.pm line 1851.
+
+$x = $class->new(0); $y = $class->new('0.1');
+ok ($x ** $y, 0, 'no warnings and zero result');
+
+#perl -MMath::BigFloat -lwe 'print Math::BigFloat->new(".222222222222222222222222222222222222222222")->bceil()'
+#Use of uninitialized value in numeric le (<=) at BigFloat.pm line 1851.
+
+$x = $class->new(".222222222222222222222222222222222222222222"); 
+ok ($x->bceil(), 1, 'no warnings and one as result');
+
 1; # all done
 
 ###############################################################################
index 9e50f5e..dbad294 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 1815
+  plan tests => 1837
        + 2;            # own tests
   }
 
index cdefea6..77b55b9 100644 (file)
@@ -624,6 +624,28 @@ ok ($class->new(1)->is_one(),1);
 ok ($class->new(-1)->is_one(),0);
 
 ###############################################################################
+# [perl #30609] bug with $x -= $x not beeing 0, but 2*$x
+
+$x = $class->new(3);  $x -= $x; ok ($x, 0);
+$x = $class->new(-3); $x -= $x; ok ($x, 0);
+$x = $class->new('NaN'); $x -= $x; ok ($x->is_nan(), 1);
+$x = $class->new('inf'); $x -= $x; ok ($x->is_nan(), 1);
+$x = $class->new('-inf'); $x -= $x; ok ($x->is_nan(), 1);
+
+$x = $class->new('NaN'); $x += $x; ok ($x->is_nan(), 1);
+$x = $class->new('inf'); $x += $x; ok ($x->is_inf(), 1);
+$x = $class->new('-inf'); $x += $x; ok ($x->is_inf('-'), 1);
+$x = $class->new(3);  $x += $x; ok ($x, 6);
+$x = $class->new(-3); $x += $x; ok ($x, -6);
+
+$x = $class->new(3);  $x *= $x; ok ($x, 9);
+$x = $class->new(-3); $x *= $x; ok ($x, 9);
+$x = $class->new(3);  $x /= $x; ok ($x, 1);
+$x = $class->new(-3); $x /= $x; ok ($x, 1);
+$x = $class->new(3);  $x %= $x; ok ($x, 0);
+$x = $class->new(-3); $x %= $x; ok ($x, 0);
+
+###############################################################################
 # all tests done
 
 1;
index 50fca1d..ba0b314 100755 (executable)
@@ -10,7 +10,7 @@ BEGIN
   my $location = $0; $location =~ s/bigintpm.t//;
   unshift @INC, $location; # to locate the testing files
   chdir 't' if -d 't';
-  plan tests => 2832;
+  plan tests => 2848;
   }
 
 use Math::BigInt;
index 8550a97..bdae6a5 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n"; 
   
-  plan tests => 1815
+  plan tests => 1837
     + 6;       # + our own tests
   }
 
index 3e831c5..69abaae 100755 (executable)
@@ -26,7 +26,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 2832
+  plan tests => 2848
     + 5;       # +5 own tests
   }
 
index 3d48030..af00563 100644 (file)
@@ -28,7 +28,7 @@ BEGIN
     }
   print "# INC = @INC\n";
 
-  plan tests => 1815
+  plan tests => 1837
        + 1;
   }