shell bypass 403
#!/usr/bin/perl
package Math::Base::Convert::CalcPP;
use strict;
use vars qw($VERSION);
$VERSION = do { my @r = (q$Revision: 0.03 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
# test number < 2^32 is NOT power of 2
#
sub isnotp2 {
my $ref = ref $_[0];
shift if ref $_[0] || $_[0] =~ /\D/; # class?
$_[0] & $_[0] -1;
}
# add a long n*32 bit number toa number < 65536
# add 'n' to array digits and propagate carry, return carry
#
sub addbaseno {
my($ap,$n) = @_;
foreach (@$ap) {
$_ += $n;
return 0 unless $_ > 0xffffffff;
$n = 1;
$_ -= 4294967296;
}
1; # carry is one on exit, else would have taken return 0 branch
}
# multiply a register of indeterminate length by a number < 65535
#
# ap pointer to multiplicand array
# multiplier
#
sub multiply {
my($ap,$m) = @_;
# $m is always 2..65535
# $m &= 0xffff; # max value 65535 already done by VETTING
#
# perl uses doubles for arithmetic, $m << 65536 will fit
my $carry = 0;
foreach ( @$ap) {
$_ *= $m;
$_ += $carry;
if ($_ > 0xffffffff) {
$carry = int($_ / 4294967296);
$_ %= 4294967296;
} else {
$carry = 0;
}
}
push @$ap, $carry if $carry;
}
sub dividebybase {
my($np,$divisor) = @_;
my @dividend = @$np; # 3% improvement
while ($#dividend) { # 3% improvement
last if $dividend[0];
shift @dividend;
}
my $remainder = 0;
my @quotient;
while (@dividend) {
my $work = ($dividend[0] += ($remainder * 4294967296));
push @quotient, int($work / $divisor);
$remainder = $work % $divisor;
shift @dividend;
}
return (\@quotient,$remainder);
}
# simple versions of conversion, works for N < ~2^49 or 10^16
#
#sub frombase {
# my($hsh,$base,$str) = @_;
# my $number = 0;
# for( $str =~ /./g ) {
# $number *= $base;
# $number += $hsh->{$_};
# }
# return $number;
#}
#sub tobase {
#sub to_base
# my($bp,$base,$num) = @_;
# my $base = shift;
# return $bp->[0] if $num == 0;
# my $str = '';
# while( $num > 0 ) {
# $str = $bp->[$num % $base] . $str;
# $num = int( $num / $base );
# }
# return $str;
#}
# convert a number from its base to 32*N bit representation
#
sub useFROMbaseto32wide {
my $bc = shift;
my($ary,$hsh,$base,$str) = @{$bc}{qw(from fhsh fbase nstr)};
# check if decimal and interger from within perl's 32bit double representation
# cutoff is 999,999,999,999,999 -- a bit less than 2^50
#
# convert directly to base 2^32 arrays
#
my @result = (0);
if ($base == 10 && length($str) < 16) {
# unless ($str > 999999999999999) { # maximum 32 bit double float integer representation
$result[0] = $str % 4294967296;
my $quotient = int($str / 4294967296);
$result[1] = $quotient if $quotient;
$bc->{b32str} = \@result;
}
else {
for ($str =~ /./g) {
multiply(\@result,$base);
push @result, 1 if addbaseno(\@result,$hsh->{$_}); # propagate carry
}
# my @rv = reverse @result;
$bc->{b32str} = \@result;
}
$bc;
}
#my %used = map {$_,0}(0..255);
# convert 32*N bit representation to any base < 65536
#
sub use32wideTObase {
my $bc = shift;
my($ary,$base,$rquot) = @{$bc}{qw(to tbase b32str)};
my @quotient = reverse(@$rquot);
my $quotient = \@quotient;
my @answer;
my $remainder;
do {
($quotient,$remainder) = dividebybase($quotient,$base);
# these commented out print statements are for convert.t DO NOT REMOVE!
#$used{$remainder} = 1;
#print $remainder;
#print " *" if $remainder > 86;
#print "\n";
unshift @answer, $ary->[$remainder];
} while grep {$_} @$quotient;
#foreach (sort {$b <=> $a} keys %used) {
#print " $_,\n" if $used{$_} && $_ > 85;
#print "\t$_\t=> \n" if !$used{$_} && $_ < 86;
#}
join '', @answer;
}
1;
__END__
=head1 NAME
Math::Base::Convert::CalcPP - standard methods used by Math::Base::Convert
=head1 DESCRIPTION
This module contains the standard methods used by B<Math::Base::Convert> to
convert from one base number to another base number.
=over 4
=item * $carry = addbaseno($reg32ptr,$int)
This function adds an integer < 65536 to a long n*32 bit register and
returns the carry.
=item * multiply($reg32ptr,$int)
This function multiplies a long n*32 bit register by an integer < 65536
=item * ($qptr,$remainder) = dividebybase($reg32ptr,$int)
this function divides a long n*32 bit register by an integer < 65536 and
returns a pointer to a long n*32 bit quotient and an integer remainder.
=item * $bc->useFROMbaseto32wide
This method converts FROM an input base string to a long n*32 bit register using
an algorithim like:
$longnum = 0;
for $char ( $in_str =~ /./g ) {
$longnum *= $base;
$longnum += $value{$char)
}
return $number;
=item * $output = $bc->use32wideTObase
This method converts a long n*32 bit register TO a base number using an
algorithim like:
$output = '';
while( $longnum > 0 ) {
$output = ( $longnum % $base ) . $output;
$num = int( $longnum / $base );
}
return $output;
=back
=head1 AUTHOR
Michael Robinton, michael@bizsystems.com
=head1 COPYRIGHT
Copyright 2012-15, Michael Robinton
This program is free software; you may redistribute it and/or modify it
under the same terms as Perl itself.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
=cut
1;