line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Math::Base::Convert; |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#use diagnostics; |
6
|
20
|
|
|
20
|
|
250582
|
use Carp; |
|
20
|
|
|
|
|
37
|
|
|
20
|
|
|
|
|
1701
|
|
7
|
20
|
|
|
20
|
|
96
|
use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS @BASES $signedBase); |
|
20
|
|
|
|
|
28
|
|
|
20
|
|
|
|
|
4863
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# @Bases, $signedBase imported from Math::Base::Convert::Bases |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
require Exporter; |
12
|
|
|
|
|
|
|
require Math::Base::Convert::Shortcuts; |
13
|
|
|
|
|
|
|
require Math::Base::Convert::CalcPP; |
14
|
|
|
|
|
|
|
require Math::Base::Convert::Bases; # drag in BASES |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
@ISA = qw( |
17
|
|
|
|
|
|
|
Math::Base::Convert::Shortcuts |
18
|
|
|
|
|
|
|
Math::Base::Convert::CalcPP |
19
|
|
|
|
|
|
|
Exporter |
20
|
|
|
|
|
|
|
); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
$VERSION = do { my @r = (q$Revision: 0.11 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
@EXPORT_OK = ( qw( cnv cnvpre cnvabs basemap ), @BASES ); |
25
|
|
|
|
|
|
|
%EXPORT_TAGS = ( |
26
|
|
|
|
|
|
|
all => [@EXPORT_OK], |
27
|
|
|
|
|
|
|
base => [ 'basemap', @BASES ] |
28
|
|
|
|
|
|
|
); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
my $functions = join '', keys %{__PACKAGE__ .'::'}; # before 'strict' |
31
|
|
|
|
|
|
|
|
32
|
20
|
|
|
20
|
|
100
|
use strict; |
|
20
|
|
|
|
|
42
|
|
|
20
|
|
|
|
|
4235
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
my $package = __PACKAGE__; |
35
|
|
|
|
|
|
|
my $packageLen = length __PACKAGE__; |
36
|
|
|
|
|
|
|
my $bs = $package .'::_bs::'; # indentify 'base sub' |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my %num2sub = ( |
39
|
|
|
|
|
|
|
2 => &bin, |
40
|
|
|
|
|
|
|
4 => &DNA, |
41
|
|
|
|
|
|
|
8 => &ocT, |
42
|
|
|
|
|
|
|
10 => &dec, |
43
|
|
|
|
|
|
|
16 => &HEX, |
44
|
|
|
|
|
|
|
64 => &m64 |
45
|
|
|
|
|
|
|
); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# return a hash map of the base array, including upper/lower case variants |
48
|
|
|
|
|
|
|
# |
49
|
|
|
|
|
|
|
sub basemap { |
50
|
2463
|
50
|
|
2463
|
1
|
6678
|
shift if ref $_[0] eq $package; # waste if method call |
51
|
2463
|
|
|
|
|
4617
|
my $base = validbase($_[0]); # return array pointer |
52
|
2463
|
|
|
|
|
10835
|
ref($base) =~ /$bs(.+)/; # sub name is $1 |
53
|
2463
|
100
|
|
|
|
6860
|
if ($1 eq 'user') { # if user array |
54
|
252
|
|
|
|
|
398
|
my $aryhsh = {}; |
55
|
252
|
|
|
|
|
707
|
@{$aryhsh}{@$base} = (0..$#$base); |
|
252
|
|
|
|
|
2459
|
|
56
|
252
|
|
|
|
|
2019
|
return $aryhsh; |
57
|
|
|
|
|
|
|
} |
58
|
2211
|
|
|
|
|
14858
|
my @all = $functions =~ /$1/gi; # get all matching sub names regardless of case |
59
|
|
|
|
|
|
|
# names are strings |
60
|
20
|
|
|
20
|
|
114
|
no strict; |
|
20
|
|
|
|
|
32
|
|
|
20
|
|
|
|
|
32509
|
|
61
|
2211
|
|
|
|
|
3169
|
my %aryhsh; |
62
|
2211
|
|
|
|
|
4670
|
foreach (@all) { |
63
|
3692
|
|
|
|
|
13609
|
$_ = $package->can($_); # return sub ref |
64
|
3692
|
|
|
|
|
9519
|
$_ = &$_; # array pointer |
65
|
3692
|
|
|
|
|
8856
|
foreach my $i (0..$#$_) { |
66
|
72966
|
|
|
|
|
140635
|
$aryhsh{$_->[$i]} = $i; # map keys to index |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
} |
69
|
2211
|
|
|
|
|
15572
|
return \%aryhsh; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# check for internal base |
73
|
|
|
|
|
|
|
sub validbase { |
74
|
7396
|
|
|
7396
|
0
|
13336
|
my $base = shift; |
75
|
7396
|
|
|
|
|
7963
|
my $ref; |
76
|
7396
|
100
|
|
|
|
22874
|
if (($ref = ref $base)) { |
|
|
100
|
|
|
|
|
|
77
|
3191
|
100
|
|
|
|
15024
|
if ($ref eq 'ARRAY') { # user supplied |
|
|
100
|
|
|
|
|
|
78
|
526
|
|
|
|
|
767
|
my @base = @{$base}; |
|
526
|
|
|
|
|
3649
|
|
79
|
526
|
|
|
|
|
858
|
my $len = @base; |
80
|
526
|
50
|
|
|
|
1324
|
Carp::croak "base to short, < 2" unless $len > 1; |
81
|
526
|
50
|
|
|
|
1143
|
Carp::croak "base to long, > 65535" unless $len < 65536; |
82
|
526
|
|
|
|
|
1283
|
$base = bless \@base, $bs .'user'; |
83
|
526
|
|
|
|
|
1631
|
return bless $base, $bs . 'user'; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
elsif ($ref =~ /^$bs/) { # internal base |
86
|
2664
|
|
|
|
|
6519
|
return $base; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
else { |
89
|
1
|
|
|
|
|
3
|
$base = 'reference'; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
elsif ($base =~ /\D/) { # is a string |
93
|
4195
|
|
|
|
|
15197
|
my $rv = $package->can($base); |
94
|
4195
|
100
|
|
|
|
15222
|
return &$rv if $rv; |
95
|
|
|
|
|
|
|
} else { |
96
|
10
|
100
|
|
|
|
52
|
return $num2sub{$base} if exists $num2sub{$base}; |
97
|
|
|
|
|
|
|
} |
98
|
3
|
|
|
|
|
501
|
Carp::croak "not a valid base: $base"; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub vet { |
102
|
2458
|
|
|
2458
|
0
|
3321
|
my $class = shift; |
103
|
2458
|
|
100
|
|
|
5208
|
my $from = shift || ''; |
104
|
2458
|
|
100
|
|
|
5142
|
my $to = shift || ''; |
105
|
|
|
|
|
|
|
|
106
|
2458
|
100
|
100
|
|
|
11993
|
$to =~ s/\s+//g if $to && ! ref $to; # strip white space |
107
|
2458
|
100
|
100
|
|
|
12559
|
$from =~ s/\s+//g if $from && ! ref $from; |
108
|
|
|
|
|
|
|
|
109
|
2458
|
100
|
|
|
|
4771
|
unless ($from) { # defaults if not defined |
110
|
3
|
|
|
|
|
18
|
$to = &HEX; |
111
|
3
|
|
|
|
|
14
|
$from = &dec; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
else { |
114
|
2455
|
|
|
|
|
4573
|
$from = validbase($from); |
115
|
2455
|
100
|
|
|
|
5159
|
unless ($to) { |
116
|
2
|
|
|
|
|
7
|
$to = &HEX; |
117
|
|
|
|
|
|
|
} else { |
118
|
2453
|
|
|
|
|
4561
|
$to = validbase($to); |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# convert sub ref's to variables |
123
|
|
|
|
|
|
|
# $to = &$to; |
124
|
|
|
|
|
|
|
# ($from, my $fhsh) = &$from; |
125
|
|
|
|
|
|
|
|
126
|
2458
|
|
|
|
|
4193
|
my $prefix = ref $to; |
127
|
2458
|
100
|
|
|
|
10724
|
if ($prefix =~ /HEX$/i) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
128
|
412
|
|
|
|
|
626
|
$prefix = '0x'; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
elsif ($prefix =~ /OCT$/i) { |
131
|
214
|
|
|
|
|
355
|
$prefix = '0'; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
elsif ($prefix =~ /bin$/) { |
134
|
212
|
|
|
|
|
326
|
$prefix = '0b'; |
135
|
|
|
|
|
|
|
} else { |
136
|
1620
|
|
|
|
|
2430
|
$prefix = ''; |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
2458
|
|
|
|
|
5506
|
bless { |
140
|
|
|
|
|
|
|
to => $to, |
141
|
|
|
|
|
|
|
tbase => scalar @$to, |
142
|
|
|
|
|
|
|
from => $from, |
143
|
|
|
|
|
|
|
fhsh => basemap($from), |
144
|
|
|
|
|
|
|
fbase => scalar @$from, |
145
|
|
|
|
|
|
|
prefix => $prefix |
146
|
|
|
|
|
|
|
}, $class; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub new { |
150
|
2451
|
|
|
2451
|
1
|
9941
|
my $proto = shift; |
151
|
2451
|
|
33
|
|
|
10916
|
my $class = ref $proto || $proto || $package; |
152
|
2451
|
|
|
|
|
4931
|
vet($class,@_); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub _cnv { |
156
|
2527
|
|
|
2527
|
|
6409
|
my $bc = shift; |
157
|
2527
|
|
|
|
|
2864
|
my $nstr; |
158
|
2527
|
100
|
66
|
|
|
7598
|
if (ref $bc && ref($bc) eq $package) { # method call? |
159
|
348
|
|
|
|
|
541
|
$nstr = shift; # yes, number to convert is next arg |
160
|
|
|
|
|
|
|
} else { |
161
|
2179
|
|
|
|
|
2923
|
$nstr = $bc; # no, first arg is number to convert |
162
|
2179
|
|
|
|
|
5557
|
$bc = $package->new(@_); |
163
|
|
|
|
|
|
|
} |
164
|
2527
|
50
|
|
|
|
7262
|
return $nstr unless keys %$bc; # if there really is no conversion |
165
|
2527
|
50
|
|
|
|
5161
|
$nstr = '' unless defined $nstr; |
166
|
|
|
|
|
|
|
|
167
|
2527
|
|
|
|
|
3604
|
my($from,$fbase,$fhsh) = @{$bc}{qw( from fbase fhsh )}; |
|
2527
|
|
|
|
|
6118
|
|
168
|
|
|
|
|
|
|
|
169
|
2527
|
|
|
|
|
4455
|
my $ref = ref $from; |
170
|
2527
|
100
|
66
|
|
|
10560
|
if ($ref eq 'user' || $fbase > $signedBase) { # known, signed character sets? |
171
|
660
|
|
|
|
|
1360
|
$bc->{sign} = ''; # no |
172
|
|
|
|
|
|
|
} else { # yes |
173
|
1867
|
|
|
|
|
3842
|
$nstr =~ s/^([+-])//; # strip sign |
174
|
1867
|
50
|
33
|
|
|
7676
|
$bc->{sign} = $1 && $1 eq '-' ? '-' : ''; # and save for possible restoration |
175
|
|
|
|
|
|
|
|
176
|
1867
|
100
|
|
|
|
7009
|
if ($ref =~ /(HEX)$/i) { |
|
|
100
|
|
|
|
|
|
177
|
548
|
|
|
|
|
1420
|
$nstr =~ s/^0x//i; # snip prefix, including typo's |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
elsif ($ref =~ /bin/i) { |
180
|
205
|
|
|
|
|
577
|
$nstr =~ s/^0b//i; # snip prefix, including typo's |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
1867
|
|
|
|
|
9196
|
$nstr =~ s/^[$from->[0]]+//; # snip leading zeros |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
2527
|
|
|
|
|
15862
|
my $fclass = join '', keys %$fhsh; |
187
|
2527
|
50
|
|
|
|
63701
|
if ($nstr =~ /[^\Q$fclass\E]/) { # quote metacharacters |
188
|
0
|
|
|
|
|
0
|
$ref =~ /([^:]+)$/; |
189
|
0
|
|
|
|
|
0
|
Carp::croak "input character not in '$1'\nstring:\t$nstr\nbase:\t$fclass\n"; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
2527
|
|
|
|
|
7717
|
$bc->{nstr} = $nstr; |
193
|
2527
|
|
|
|
|
6610
|
$bc; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
# |
197
|
|
|
|
|
|
|
# Our internal multiply & divide = base 32 |
198
|
|
|
|
|
|
|
# Maximum digit length for a binary base = 32*ln(2)/ln(base) |
199
|
|
|
|
|
|
|
# 0bnnnnnnnnnnn |
200
|
|
|
|
|
|
|
# 0nnnnnnnnnnnn |
201
|
|
|
|
|
|
|
# 0xnnnnnnnnnnn |
202
|
|
|
|
|
|
|
# |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
my %maxdlen = (# digits, key is base |
205
|
|
|
|
|
|
|
2 => 31, # 2^1 |
206
|
|
|
|
|
|
|
4 => 16, # 2^2 |
207
|
|
|
|
|
|
|
8 => 10, # 2^3 |
208
|
|
|
|
|
|
|
16 => 8, # 2^4 |
209
|
|
|
|
|
|
|
32 => 6, # 2^5 |
210
|
|
|
|
|
|
|
64 => 5, # 2^6 |
211
|
|
|
|
|
|
|
128 => 4, # 2^7 |
212
|
|
|
|
|
|
|
256 => 4 # 2^8 |
213
|
|
|
|
|
|
|
); |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub cnv { |
216
|
799
|
|
|
799
|
1
|
7838
|
my @rv = &cnvpre; |
217
|
799
|
100
|
|
|
|
2761
|
return @rv if wantarray; |
218
|
436
|
|
|
|
|
1400
|
return ($rv[0] . $rv[2]); # sign and string only |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub cnvabs { |
222
|
727
|
|
|
727
|
1
|
8710
|
my @rv = &cnvpre; |
223
|
727
|
100
|
|
|
|
2871
|
return @rv if wantarray; |
224
|
364
|
|
|
|
|
1085
|
return $rv[2] # string only |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub cnvpre { |
228
|
2252
|
|
|
2252
|
1
|
13791
|
my $bc = &_cnv; |
229
|
2252
|
50
|
|
|
|
5480
|
return $bc unless ref $bc; |
230
|
2252
|
|
|
|
|
3464
|
my($from,$fbase,$to,$tbase,$sign,$prefix,$nstr) = @{$bc}{qw( from fbase to tbase sign prefix nstr)}; |
|
2252
|
|
|
|
|
6605
|
|
231
|
|
|
|
|
|
|
|
232
|
2252
|
|
|
|
|
3335
|
my $slen = length($nstr); |
233
|
2252
|
|
|
|
|
3324
|
my $tref = ref($to); |
234
|
2252
|
100
|
|
|
|
5364
|
unless ($slen) { # zero length input |
|
|
100
|
|
|
|
|
|
235
|
1584
|
|
|
|
|
2711
|
$nstr = $to->[0]; # return zero |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
elsif (lc $tref eq lc ref($from)) {# no base conversion |
238
|
54
|
50
|
|
|
|
127
|
if ($tref ne ref($from)) { # convert case? |
239
|
0
|
0
|
|
|
|
0
|
if ($tref =~ /(?:DNA|HEX)/) { |
240
|
0
|
|
|
|
|
0
|
$nstr = uc $nstr; # force upper case |
241
|
|
|
|
|
|
|
} else { |
242
|
0
|
|
|
|
|
0
|
$nstr = lc $nstr; # or force lower case |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
else { # convert |
247
|
|
|
|
|
|
|
|
248
|
614
|
|
|
|
|
948
|
my $fblen = length($fbase); |
249
|
614
|
100
|
66
|
|
|
2900
|
if ($fbase & $fbase -1 || # from base is not power of 2 |
|
|
50
|
33
|
|
|
|
|
250
|
|
|
|
|
|
|
$fblen > 256 ) { # no shortcuts,... |
251
|
220
|
|
|
|
|
840
|
$bc->useFROMbaseto32wide; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# if a large base and digit string will fit in a single 32 bit register |
255
|
|
|
|
|
|
|
elsif ( $fblen > 32 && # big base |
256
|
|
|
|
|
|
|
# exists $maxdlen{$fbase} && # has to exist |
257
|
|
|
|
|
|
|
! $slen > $maxdlen{$fbase}) { |
258
|
0
|
|
|
|
|
0
|
$bc->useFROMbaseto32wide; # CalcPP is faster |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
else { # shortcuts faster for big numbers |
261
|
394
|
|
|
|
|
1221
|
$bc->useFROMbaseShortcuts; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
################################ |
265
|
|
|
|
|
|
|
# input converted to base 2^32 # |
266
|
|
|
|
|
|
|
################################ |
267
|
|
|
|
|
|
|
|
268
|
614
|
100
|
66
|
|
|
3185
|
if ($tbase & $tbase -1 || # from base is not power of 2 |
|
|
100
|
100
|
|
|
|
|
269
|
|
|
|
|
|
|
$tbase > 256 ) { # no shortcuts,... |
270
|
130
|
|
|
|
|
395
|
$nstr = $bc->use32wideTObase; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
# if big base and digit string fits in a single 32 bit register |
273
|
86
|
|
|
|
|
319
|
elsif ( $tbase > 32 && @{$bc->{b32str}} == 1) { |
274
|
75
|
|
|
|
|
225
|
$nstr = $bc->use32wideTObase; # CalcPP is faster |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
else { |
277
|
409
|
|
|
|
|
1235
|
$nstr = $bc->useTObaseShortcuts; # shortcuts faster for big numbers |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
} # end convert |
280
|
|
|
|
|
|
|
|
281
|
2252
|
100
|
|
|
|
4980
|
$nstr = $to->[0] unless length($nstr); |
282
|
2252
|
100
|
|
|
|
18362
|
return ($sign,$prefix,$nstr) if wantarray; |
283
|
363
|
100
|
66
|
|
|
1514
|
if (#$prefix ne '' && # 0, 0x, 0b |
284
|
|
|
|
|
|
|
$tbase <= $signedBase && # base in signed set |
285
|
|
|
|
|
|
|
$tref ne 'user' ) { # base standard |
286
|
264
|
|
|
|
|
2371
|
return ($sign . $prefix . $nstr); |
287
|
|
|
|
|
|
|
} |
288
|
99
|
|
|
|
|
846
|
return ($prefix . $nstr); |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
sub _cnvtst { |
292
|
204
|
|
|
204
|
|
1513
|
my $bc = &_cnv; |
293
|
204
|
50
|
|
|
|
494
|
return $bc unless ref $bc; |
294
|
204
|
|
|
|
|
666
|
$bc->useFROMbaseto32wide; |
295
|
204
|
50
|
|
|
|
838
|
return $bc->use32wideTObase unless wantarray; |
296
|
0
|
|
|
|
|
|
return (@{$bc}{qw( sign prefix )},$bc->use32wideTObase); |
|
0
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head1 NAME |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
Math::Base::Convert - very fast base to base conversion |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=head1 SYNOPSIS |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=head2 As a function |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
use Math::Base::Convert qw( :all ) |
308
|
|
|
|
|
|
|
use Math::Base::Convert qw( |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
cnv |
311
|
|
|
|
|
|
|
cnvabs |
312
|
|
|
|
|
|
|
cnvpre |
313
|
|
|
|
|
|
|
basemap |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# comments |
316
|
|
|
|
|
|
|
bin base 2 0,1 |
317
|
|
|
|
|
|
|
dna base 4 lower case dna |
318
|
|
|
|
|
|
|
DNA base 4 upper case DNA |
319
|
|
|
|
|
|
|
oct base 8 octal |
320
|
|
|
|
|
|
|
dec base 10 decimal |
321
|
|
|
|
|
|
|
hex base 16 lower case hex |
322
|
|
|
|
|
|
|
HEX base 16 upper case HEX |
323
|
|
|
|
|
|
|
b62 base 62 |
324
|
|
|
|
|
|
|
b64 base 64 month:C:12 day:V:31 |
325
|
|
|
|
|
|
|
m64 base 64 0-63 from MIME::Base64 |
326
|
|
|
|
|
|
|
iru base 64 P10 protocol - IRCu daemon |
327
|
|
|
|
|
|
|
url base 64 url with no %2B %2F expansion of + - / |
328
|
|
|
|
|
|
|
rex base 64 regular expression variant |
329
|
|
|
|
|
|
|
id0 base 64 IDentifier style 0 |
330
|
|
|
|
|
|
|
id1 base 64 IDentifier style 1 |
331
|
|
|
|
|
|
|
xnt base 64 XML Name Tokens (Nmtoken) |
332
|
|
|
|
|
|
|
xid base 64 XML identifiers (Name) |
333
|
|
|
|
|
|
|
b85 base 85 RFC 1924 for IPv6 addresses |
334
|
|
|
|
|
|
|
ascii base 96 7 bit printible 0x20 - 0x7F |
335
|
|
|
|
|
|
|
); |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
my $converted = cnv($number,optionalFROM,optionalTO); |
338
|
|
|
|
|
|
|
my $basemap = basmap(base); |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=head2 As a method: |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
use Math::Base::Convert; |
343
|
|
|
|
|
|
|
use Math::Base::Convert qw(:base); |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
my $bc = new Math::Base::Convert(optionalFROM,optionalTO); |
346
|
|
|
|
|
|
|
my $converted = $bc->cnv($number); |
347
|
|
|
|
|
|
|
my $basemap = $bc->basemap(base); |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head1 DESCRIPTION |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
This module provides fast functions and methods to convert between arbitrary number bases |
352
|
|
|
|
|
|
|
from 2 (binary) thru 65535. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
This module is pure Perl, has no external dependencies, and is backward compatible |
355
|
|
|
|
|
|
|
with old versions of Perl 5. |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=head1 PREFERRED USE |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
Setting up the conversion parameters, context and error checking consume a significant portion of the execution time of a |
360
|
|
|
|
|
|
|
B base conversion. These operations are performed each time B is called as a function. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
Using method calls eliminates a large portion of this overhead and will improve performance for |
363
|
|
|
|
|
|
|
repetitive conversions. See the benchmarks sub-directory in this distribution. |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head1 BUILT IN NUMBER SETS |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
Number set variants courtesy of the authors of Math::Base:Cnv and |
368
|
|
|
|
|
|
|
Math::BaseConvert. |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
The functions below return a reference to an array |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
$arrayref = function; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
bin => ['0', '1'] # binary |
375
|
|
|
|
|
|
|
dna => ['a','t','c','g'] # lc dna |
376
|
|
|
|
|
|
|
DNA => ['A','T','C','G'], {default} # uc DNA |
377
|
|
|
|
|
|
|
oct => ['0'..'7'] # octal |
378
|
|
|
|
|
|
|
dec => ['0'..'9'] # decimal |
379
|
|
|
|
|
|
|
hex => ['0'..'9', 'a'..'f'] # lc hex |
380
|
|
|
|
|
|
|
HEX => ['0'..'9', 'A'..'F'] {default} # uc HEX |
381
|
|
|
|
|
|
|
b62 => ['0'..'9', 'a'..'z', 'A'..'Z'] # base 62 |
382
|
|
|
|
|
|
|
b64 => ['0'..'9', 'A'..'Z', 'a'..'z', '.', '_'] # m:C:12 d:V:31 |
383
|
|
|
|
|
|
|
m64 => ['A'..'Z', 'a'..'z', '0'..'9', '+', '/'] # MIMI::Base64 |
384
|
|
|
|
|
|
|
iru => ['A'..'Z', 'a'..'z', '0'..'9', '[', ']'] # P10 - IRCu |
385
|
|
|
|
|
|
|
url => ['A'..'Z', 'a'..'z', '0'..'9', '*', '-'] # url no %2B %2F |
386
|
|
|
|
|
|
|
rex => ['A'..'Z', 'a'..'z', '0'..'9', '!', '-'] # regex variant |
387
|
|
|
|
|
|
|
id0 => ['A'..'Z', 'a'..'z', '0'..'9', '_', '-'] # ID 0 |
388
|
|
|
|
|
|
|
id1 => ['A'..'Z', 'a'..'z', '0'..'9', '.', '_'] # ID 1 |
389
|
|
|
|
|
|
|
xnt => ['A'..'Z', 'a'..'z', '0'..'9', '.', '-'] # XML (Nmtoken) |
390
|
|
|
|
|
|
|
xid => ['A'..'Z', 'a'..'z', '0'..'9', '_', ':'] # XML (Name) |
391
|
|
|
|
|
|
|
b85 => ['0'..'9', 'A'..'Z', 'a'..'z', '!', '#', # RFC 1924 |
392
|
|
|
|
|
|
|
'$', '%', '&', '(', ')', '*', '+', '-', |
393
|
|
|
|
|
|
|
';', '<', '=', '>', '?', '@', '^', '_', |
394
|
|
|
|
|
|
|
'', '{', '|', '}', '~'] |
395
|
|
|
|
|
|
|
An arbitrary base 96 composed of printable 7 bit ascii |
396
|
|
|
|
|
|
|
from 0x20 (space) through 0x7F (tilde ~) |
397
|
|
|
|
|
|
|
ascii => [ |
398
|
|
|
|
|
|
|
' ','!','"','#','$','%','&',"'",'(',')', |
399
|
|
|
|
|
|
|
'*','+',',','-','.','/', |
400
|
|
|
|
|
|
|
'0','1','2','3','4','5','6','7','8','9', |
401
|
|
|
|
|
|
|
':',';','<','=','>','?','@', |
402
|
|
|
|
|
|
|
'A','B','C','D','E','F','G','H','I','J','K','L','M', |
403
|
|
|
|
|
|
|
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', |
404
|
|
|
|
|
|
|
'[','\',']','^','_','`', |
405
|
|
|
|
|
|
|
'a','b','c','d','e','f','g','h','i','j','k','l','m', |
406
|
|
|
|
|
|
|
'n','o','p','q','r','s','t','u','v','w','x','y','z', |
407
|
|
|
|
|
|
|
'{','|','}','~'] |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
NOTE: Clean text with =~ s/\s+/ /; before applying to ascii |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=head1 USAGE |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=over 4 |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=item * $converted = cnv($number,[from],[to]) |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
SCALAR context: array context covered later in this document. |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
To preserve similarity to other similar base conversion modules, B |
420
|
|
|
|
|
|
|
returns the converted number string with SIGN if both the input and output |
421
|
|
|
|
|
|
|
base strings are in known signed set of bases in this module. |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
In the case of binary, octal, hex, all leading base designator strings such as |
424
|
|
|
|
|
|
|
'0b','0', '0x' are automatically stripped from the input. Base designator |
425
|
|
|
|
|
|
|
strings are NOT applied to the output. |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
The context of base FROM and TO is optional and flexible. |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
Unconditional conversion from decimal to HEX [upper case] |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
$converted = cnv($number); |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
Example conversion from octal to default HEX [upper case] with different |
434
|
|
|
|
|
|
|
context for the 'octal' designator. |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
base as a number |
437
|
|
|
|
|
|
|
$converted = cnv($number,8); |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
base as a function (imported) |
440
|
|
|
|
|
|
|
$converted = cnv($number,oct); |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
base as text |
443
|
|
|
|
|
|
|
$converted = convbase($number,'oct'); |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
Conversion to/from arbitrary bases i.e. |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
$converted = cnv($number); # dec -> hex (default) |
448
|
|
|
|
|
|
|
$converted = cnv($number,oct); # oct to HEX |
449
|
|
|
|
|
|
|
$converted = cnv($number,10,HEX); # dec to uc HEX |
450
|
|
|
|
|
|
|
$converted = cnv($number,10,hex); # dec to lc hex |
451
|
|
|
|
|
|
|
$converted = cnv($number,dec,hex);# same |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
pointer notation |
454
|
|
|
|
|
|
|
$converted = cnv($number, oct => dec); |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
$converted = cnv($number,10 => 23); # dec to base23 |
457
|
|
|
|
|
|
|
$converted = cnv($number,23 => 5); # b23 to base5 |
458
|
|
|
|
|
|
|
etc... |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=item * $bc = new Math::Base::Convert([from],[to]); |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
This method has the same usage and syntax for FROM and TO as B above. |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
Setup for unconditional conversion from HEX to decimal |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
$bc = new Math::Base::Convert(); |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
Example conversion from octal to decimal |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
base number |
471
|
|
|
|
|
|
|
$bc = new Math::Base::Convert(8); |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
base function (imported) |
474
|
|
|
|
|
|
|
$bc = new Math::Base::Convert(oct); |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
base text |
477
|
|
|
|
|
|
|
$bc = new Math::Base::Convert('oct') |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
The number conversion for any of the above: |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
NOTE: iterative conversions using a method pointer are ALWAYS faster than |
482
|
|
|
|
|
|
|
calling B as a function. |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
$converted = $bc->cnv($number); |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
=item * $converted = cnvpre($number,[from],[to]) |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
Same as B except that base descriptor PREfixes are applied to B, |
489
|
|
|
|
|
|
|
B, and B output strings. |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
=item * $converted = cnvabs($number,[from],[to]) |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
Same as B except that the ABSolute value of the number string is |
494
|
|
|
|
|
|
|
returned without SIGN is returned. i.e. just the raw string. |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=item * ($sign,$prefix,$string) = cnv($number,[$from,[$to]]) |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=item * ($sign,$prefix,$string) = cnv($number,[$from,[$to]]) |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=item * ($sign,$prefix,$string) = cnv($number,[$from,[$to]]) |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
ARRAY context: |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
All three functions return the same items in array context. |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
sign the sign of the input number string |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
prefix the prefix which would be applied to output |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
string the raw output string |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
=item * $basemap = basemap(base); |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=item * $basemap = $bc->basemap(base); |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
This function / method returns a pointer to a hash that maps the keys of a base to its |
517
|
|
|
|
|
|
|
numeric value for base conversion. It accepts B in any of the forms |
518
|
|
|
|
|
|
|
described for B. |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
The return basemap includes upper and lower case variants of the the number |
521
|
|
|
|
|
|
|
base in cases such as B where upper and lower case a..f, A..F map to |
522
|
|
|
|
|
|
|
the same numeric value for base conversion. |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
i.e. $hex_ptr = { |
525
|
|
|
|
|
|
|
0 => 0, |
526
|
|
|
|
|
|
|
1 => 1, |
527
|
|
|
|
|
|
|
2 => 2, |
528
|
|
|
|
|
|
|
3 => 3, |
529
|
|
|
|
|
|
|
4 => 4, |
530
|
|
|
|
|
|
|
5 => 5, |
531
|
|
|
|
|
|
|
6 => 6, |
532
|
|
|
|
|
|
|
7 => 7, |
533
|
|
|
|
|
|
|
8 => 8, |
534
|
|
|
|
|
|
|
9 => 9, |
535
|
|
|
|
|
|
|
A => 10, |
536
|
|
|
|
|
|
|
B => 11, |
537
|
|
|
|
|
|
|
C => 12, |
538
|
|
|
|
|
|
|
D => 13, |
539
|
|
|
|
|
|
|
E => 14, |
540
|
|
|
|
|
|
|
F => 15, |
541
|
|
|
|
|
|
|
a => 10, |
542
|
|
|
|
|
|
|
b => 11, |
543
|
|
|
|
|
|
|
c => 12, |
544
|
|
|
|
|
|
|
d => 13, |
545
|
|
|
|
|
|
|
e => 14, |
546
|
|
|
|
|
|
|
f => 15 |
547
|
|
|
|
|
|
|
}; |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=back |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
=head1 BENCHMARKS |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
Math::Base::Convert includes 2 development and one real world benchmark |
554
|
|
|
|
|
|
|
sequences included in the test suite. Benchmark results for a 500mhz system |
555
|
|
|
|
|
|
|
can be found in the 'benchmarks' source directory. |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
make test BENCHMARK=1 |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
Provides comparison data for bi-directional conversion of an ascending |
560
|
|
|
|
|
|
|
series of number strings in all base powers. The test sequence contains |
561
|
|
|
|
|
|
|
number strings that go from a a single 32 bit register to several. Tested |
562
|
|
|
|
|
|
|
bases are: (note: b32, b128, b256 not useful and are for testing only) |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
base 2 4 8 16 32 64 85 128 256 |
565
|
|
|
|
|
|
|
bin, dna, oct, hex, b32, b64, b85, b128, b256 |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
Conversions are performed FROM all bases TO decimal and are repeated in the |
568
|
|
|
|
|
|
|
opposing direction FROM decimal TO all bases. |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
Benchmark 1 results indicate the Math::Base::Convert typically runs |
571
|
|
|
|
|
|
|
significantly faster ( 10x to 100x) than Math::BigInt based |
572
|
|
|
|
|
|
|
implementations used in similar modules. |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
make test BENCHMARK=2 |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
Provides comparison data for the frontend and backend converters in |
577
|
|
|
|
|
|
|
Math::Base::Convert's CalcPP and Shortcuts packages, and Math::Bigint |
578
|
|
|
|
|
|
|
conversions if it is present on the system under test. |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
make test BENCHMARK=3 |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
Checks the relative timing of short and long number string conversions. FROM |
583
|
|
|
|
|
|
|
a base number to n*32 bit register and TO a base number from an n*32 bit |
584
|
|
|
|
|
|
|
register set. |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
i.e. strings that convert to and from 1, 2, 3... etc.. 32 bit registers |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
none |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
Math::BigInt is conditionally used in |
593
|
|
|
|
|
|
|
the test suite but is not a requirement |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
=head1 EXPORT_OK |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
Conditional EXPORT functions |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
cnv |
600
|
|
|
|
|
|
|
cnvabs |
601
|
|
|
|
|
|
|
cnvpre |
602
|
|
|
|
|
|
|
basemap |
603
|
|
|
|
|
|
|
bin |
604
|
|
|
|
|
|
|
oct |
605
|
|
|
|
|
|
|
dec |
606
|
|
|
|
|
|
|
heX |
607
|
|
|
|
|
|
|
HEX |
608
|
|
|
|
|
|
|
b62 |
609
|
|
|
|
|
|
|
b64 |
610
|
|
|
|
|
|
|
m64 |
611
|
|
|
|
|
|
|
iru |
612
|
|
|
|
|
|
|
url |
613
|
|
|
|
|
|
|
rex |
614
|
|
|
|
|
|
|
id0 |
615
|
|
|
|
|
|
|
id1 |
616
|
|
|
|
|
|
|
xnt |
617
|
|
|
|
|
|
|
xid |
618
|
|
|
|
|
|
|
b85 |
619
|
|
|
|
|
|
|
ascii |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
=head1 EXPORT_TAGS |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
Conditional EXPORT function groups |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
:all => all of above |
626
|
|
|
|
|
|
|
:base => all except 'cnv,cnvabs,cnvpre' |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
This module was inspired by Math::BaseConvert maintained by Shane Warden |
631
|
|
|
|
|
|
|
and forked from Math::BaseCnv, both authored by Pip |
632
|
|
|
|
|
|
|
Stuart |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
=head1 AUTHOR |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
Michael Robinton, |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
=head1 COPYRIGHT |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
Copyright 2012-2015, Michael Robinton |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
This program is free software; you may redistribute it and/or modify it |
644
|
|
|
|
|
|
|
under the same terms as Perl itself. |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
647
|
|
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
648
|
|
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
=cut |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
1; |