Subject: | Feature contribution proposal: from_base() [for base64, trinary, and any other arbitrary formats] |
There is no handling for base64-encoded numbers.
There is also no handling for arbitrary other bases, nor is there an easy-to-use handler for variables bases.
I propose to submit a patch to you which will implement the following:-
$x = Math::BigInt->from_base($base,$string,$optional_collation_sequence);
e.g.
$x = Math::BigInt->from_base(64,"Hello_World","0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/"); # 20333681053883128807
$x = Math::BigInt->from_base(3,"12000110202101022210102000112010020100121"); # 20333681053883128807
Find attached a stand-alone solution containing my proposed patch implementation code.
Please let me know if you will include this proposed submission or not (and if so - any changes or extra features (corresponding to_base?) you want): I prefer not to waste anyone's time writing and testing and submitting a patch if nobody is going to use it!
Chris.
Subject: | base-anything.pl |
#!/usr/bin/perl -w
our $VERSION='0.20110825';
=head1 NAME
base-anything.pl - Converts "numbers" to and from arbitrary bases
=head1 SYNOPSIS
base-anything.pl [options] number
Options:
-from the base of the incoming number
-to the base of the number to output
-seq use alternative collation sequence besides: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"#$%&'()*+,-./:;<=>?@[\]^_`{|}?
-iseq like -seq - but for the input base only
-oseq like -seq - but for the output base only
-pad Length to use for fixed-width output
-help brief help message
-man full documentation
=head1 SUBROUTINES
The following information is for maintenance programmer reference.
nb: perl -e 'use integer; $a=2**63-1; print $a' => 9223372036854775807
=cut
######################################################################
use strict;
no utf8; # Source code contains no unusual characters
use warnings; # same as -w switch above
use bytes; # Needed to prevent mixups when exchanging unicode data with Oracle
use Getopt::Long; # Commandline argument parsing
use Pod::Usage; # Inbuilt documentation helper
use Math::BigInt lib => 'GMP'; # Warning - must use GMP, or else RSA ops each take over a minute to complete
my %arg; # We store copies of commandline arguments in here
my($norm,$red,$grn,$yel,$nav,$blu,$save,$rest,$clr)=("\033[0m","\033[31;1m","\033[32;1m","\033[33;1m","\033[34;1m","\033[36;1m","\033[s","\033[u","\033[K");
my @collseq=(0..9,'A'..'Z','a'..'z',split('',q{!"#$%&'()*+,-./:;<=>?@[\\]^_`\{|\}~? }."\007\007\007"));
# Parse options, and print help/manual if requested.
&GetOptions('help|?' => \$arg{'help'},
'man' => \$arg{'man'},
'from|f=i' => \$arg{'from'},
'to|t=i' => \$arg{'to'},
'seq|s=s' => \$arg{'seq'},
'iseq|i=s' => \$arg{'iseq'},
'oseq|o=s' => \$arg{'oseq'},
'pad=i' => \$arg{'pad'},
) or &pod2usage(2);
&pod2usage(1) if ($arg{'help'}||($arg{'from'}<1)||($arg{'to'}<1)||($ARGV[0] eq ''));
&pod2usage(-exitstatus => 0, -verbose => 2) if $arg{'man'};
@collseq=split('',$arg{'seq'}) if(defined $arg{'seq'});
my @ocollseq=@collseq;
@collseq=split('',$arg{'iseq'}) if(defined $arg{'iseq'});
@ocollseq=split('',$arg{'oseq'}) if(defined $arg{'oseq'});
my %collseq;foreach my $i (0..$#collseq){$collseq{$collseq[$i]}=$i}; # Build Fast lookup table
print &base_anything(from=>$arg{'from'},to=>$arg{'to'},in=>$ARGV[0],pad=>$arg{'pad'});
######################################################################
=head2 base_anything
Convert a base-anything input number/string into any other output base
(within the max integer size contraints of the running architecture!)
eg: &base_anything(from=>10,to=>39,in=>999999999999) = '7B7JL0a0';
=cut
######################################################################
sub base_anything {
my(%c)=@_;
my $res=Math::BigInt->new(0);
my $base=Math::BigInt->new(1);
my $a='';
my %collseq;foreach my $i (0..$#collseq){$collseq{$collseq[$i]}=$i}; # Build Fast base_anything lookup table
# Convert the input to internal representation
while((my $c=chop($c{'in'})) ne '') {
my $add=$base->copy();
$add->bmul($collseq{$c});
$res->badd($add);
$base->bmul($c{'from'});
}
# Convert internal representation to the output
while($res->is_pos()) { # >0
my($quo,$rem)=$res->bdiv($c{'to'});
$a=$ocollseq[$rem] . $a;
$res=$quo; # ($res-$r) / $c{'to'};
}
if(defined($c{'pad'})) {
$a=$ocollseq[0] . $a while(length($a)<$c{'pad'});
}
return $a;
} # base_anything
__END__
=head1 AUTHOR
Chris Drake <christopher@pobox.com>
=head1 BUGS
=over 3
=item *
Revision 0.20110825; no known problems as yet.
=back
=head1 CHANGE HISTORY
=over 3
=item *
0.20110825 Introduced change history into POD
=back
=head1 SEE ALSO
http://perldoc.perl.org/integer.html
=head1 COPYRIGHT
E<32>This file Copyright (C) 2011 Chris Drake. All Rights Reserved.E<10> Portions Copyright (C) 1989 through 2011 Chris Drake. All Rights Reserved.E<10> B<This program is NOT free software.>E<10> B<It must not be distributed without prior written consent.>
=cut