summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Math/Int64.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Math/Int64.pm')
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Math/Int64.pm559
1 files changed, 559 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/Math/Int64.pm b/Master/tlpkg/tlperl/lib/Math/Int64.pm
new file mode 100755
index 00000000000..21be450ebfb
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Math/Int64.pm
@@ -0,0 +1,559 @@
+package Math::Int64;
+
+use strict;
+use warnings;
+
+BEGIN {
+ our $VERSION = '0.30';
+
+ require XSLoader;
+ XSLoader::load('Math::Int64', $VERSION);
+}
+
+use constant MAX_INT64 => string_to_int64 ( '0x7fff_ffff_ffff_ffff');
+use constant MIN_INT64 => string_to_int64 ('-0x8000_0000_0000_0000');
+use constant MAX_UINT64 => string_to_uint64( '0xffff_ffff_ffff_ffff');
+
+require Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT_OK = qw(int64
+ int64_to_number
+ net_to_int64 int64_to_net
+ native_to_int64 int64_to_native
+ string_to_int64 hex_to_int64
+ BER_to_int64 int64_to_BER
+ int64_to_string int64_to_hex
+ int64_rand
+ int64_srand
+ uint64
+ uint64_to_number
+ net_to_uint64 uint64_to_net
+ native_to_uint64 uint64_to_native
+ string_to_uint64 hex_to_uint64
+ BER_to_uint64 uint64_to_BER
+ uint64_to_string uint64_to_hex
+ uint64_rand
+ BER_length
+ MAX_INT64 MIN_INT64 MAX_UINT64
+ );
+
+my %available_pragmas = map { $_ => 1 } qw(native_if_available
+ die_on_overflow);
+
+sub import {
+ my $pkg = shift;
+ my (%pragmas, @subs, %native);
+ for (@_) {
+ if ($_ =~ /^:(.*)/ and $available_pragmas{$1}) {
+ $pragmas{$1} = 1
+ }
+ else {
+ push @subs, $_;
+ }
+ }
+
+ if ($pragmas{die_on_overflow}) {
+ require Math::Int64::die_on_overflow;
+ Math::Int64::die_on_overflow->import;
+ }
+
+ if ($pragmas{native_if_available}) {
+ require Math::Int64::native_if_available;
+ Math::Int64::native_if_available->import;
+ }
+
+ Math::Int64->export_to_level(1, $pkg, @subs);
+}
+
+use overload ( '+' => \&_add,
+ '+=' => \&_add,
+ '-' => \&_sub,
+ '-=' => \&_sub,
+ '*' => \&_mul,
+ '*=' => \&_mul,
+ '**' => \&_pow,
+ '**=' => \&_pow,
+ '/' => \&_div,
+ '/=' => \&_div,
+ '%' => \&_rest,
+ '%=' => \&_rest,
+ 'neg' => \&_neg,
+ '++' => \&_inc,
+ '--' => \&_dec,
+ '!' => \&_not,
+ '~' => \&_bnot,
+ '&' => \&_and,
+ '|' => \&_or,
+ '^' => \&_xor,
+ '<<' => \&_left,
+ '>>' => \&_right,
+ '<=>' => \&_spaceship,
+ '>' => \&_gtn,
+ '<' => \&_ltn,
+ '>=' => \&_gen,
+ '<=' => \&_len,
+ '==' => \&_eqn,
+ '!=' => \&_nen,
+ 'bool' => \&_bool,
+ '0+' => \&_number,
+ '""' => \&_string,
+ '=' => \&_clone,
+ fallback => 1 );
+
+package Math::UInt64;
+use overload ( '+' => \&_add,
+ '+=' => \&_add,
+ '-' => \&_sub,
+ '-=' => \&_sub,
+ '*' => \&_mul,
+ '*=' => \&_mul,
+ '**' => \&_pow,
+ '**=' => \&_pow,
+ '/' => \&_div,
+ '/=' => \&_div,
+ '%' => \&_rest,
+ '%=' => \&_rest,
+ 'neg' => \&_neg,
+ '++' => \&_inc,
+ '--' => \&_dec,
+ '!' => \&_not,
+ '~' => \&_bnot,
+ '&' => \&_and,
+ '|' => \&_or,
+ '^' => \&_xor,
+ '<<' => \&_left,
+ '>>' => \&_right,
+ '<=>' => \&_spaceship,
+ '>' => \&_gtn,
+ '<' => \&_ltn,
+ '>=' => \&_gen,
+ '<=' => \&_len,
+ '==' => \&_eqn,
+ '!=' => \&_nen,
+ 'bool' => \&_bool,
+ '0+' => \&_number,
+ '""' => \&_string,
+ '=' => \&_clone,
+ fallback => 1 );
+
+1;
+
+__END__
+
+=head1 NAME
+
+Math::Int64 - Manipulate 64 bits integers in Perl
+
+=head1 SYNOPSIS
+
+ use Math::Int64 qw(int64 uint64);
+
+ my $i = int64(1);
+ my $j = $i << 40;
+ print($i + $j * 1000000);
+
+ my $k = uint64("12345678901234567890");
+
+=head1 DESCRIPTION
+
+This module adds support for 64 bit integers, signed and unsigned, to
+Perl.
+
+=head2 Exportable functions
+
+=over 4
+
+=item int64()
+
+=item int64($value)
+
+Creates a new int64 value and initializes it to C<$value>, where
+$value can be a Perl number or a string containing a number.
+
+For instance:
+
+ $i = int64(34);
+ $j = int64("-123454321234543212345");
+
+ $k = int64(1234567698478483938988988); # wrong!!!
+ # the unquoted number would
+ # be converted first to a
+ # real number causing it to
+ # loose some precision.
+
+Once the int64 number is created it can be manipulated as any other
+Perl value supporting all the standard operations (addition, negation,
+multiplication, postincrement, etc.).
+
+
+=item net_to_int64($str)
+
+Converts an 8 bytes string containing an int64 in network order to the
+internal representation used by this module.
+
+=item int64_to_net($int64)
+
+Returns an 8 bytes string with the representation of the int64 value
+in network order.
+
+=item native_to_int64($str)
+
+=item int64_to_native($int64)
+
+similar to net_to_int64 and int64_to_net, but using the native CPU
+order.
+
+=item int64_to_number($int64)
+
+returns the optimum representation of the int64 value using Perl
+internal types (IV, UV or NV). Precision may be lost.
+
+For instance:
+
+ for my $l (10, 20, 30, 40, 50, 60) {
+ my $i = int64(1) << $l;
+ my $n = int64_to_number($i);
+ print "int64:$i => perl:$n\n";
+ }
+
+=item string_to_int64($str, $base)
+
+Converts the string to a int64 value. The conversion is done according
+to the given base, which must be a number between 2 and 36 inclusive
+or the special value 0. C<$base> defaults to 0.
+
+The string may begin with an arbitrary amount of white space followed
+by a single optional C<+> or C<-> sign. If base is zero or 16, the
+string may then include a "0x" prefix, and the number will be read in
+base 16; otherwise, a zero base is taken as 10 (decimal) unless the
+next character is '0', in which case it is taken as 8 (octal).
+
+Underscore characters (C<_>) between the digits are ignored.
+
+No overflow checks are performed by this function unless the
+C<die_on_overflow> pragma is used (see L</Die on overflow> below).
+
+See also L<strtoll(3)>.
+
+=item hex_to_int64($i64)
+
+Shortcut for string_to_int64($str, 16)
+
+=item int64_to_string($i64, $base)
+
+Converts the int64 value to its string representation in the given
+base (defaults to 10).
+
+=item int64_to_hex($i64)
+
+Shortcut for C<int64_to_string($i64, 16)>.
+
+=item int64_to_BER($i64)
+
+Converts the int64 value to its BER representation (see
+L<perlfunc/pack> for a description of the BER format).
+
+In the case of signed numbers, they are transformed into unsigned
+numbers before encoding them in the BER format with the following
+rule:
+
+ $neg = ($i64 < 0 ? 1 : 0);
+ $u64 = (($neg ? ~$i64 : $i64) << 1) | $neg;
+
+That way, positive and negative integers are interleaved as 0, -1, 1,
+2, -2, .... The format is similar to that used by Google protocol
+buffers to encode signed varints but with the most significant groups
+first (protocol buffers uses the least significant groups first
+variant).
+
+If you don't want that preprocessing for signed numbers, just use the
+C<uint64_to_BER> function instead.
+
+=item BER_to_int64($str)
+
+Decodes the int64 number in BER format from the given string.
+
+There must not be any extra bytes on the string after the encoded number.
+
+=item BER_length($str)
+
+Given a string with a BER encoded number at the beginning, this
+function returns the number of bytes it uses.
+
+The rigth way to shift a BER encoded number from the beginning of some
+string is as follows:
+
+ $i64 = BER_to_int64(substr($str, 0, BER_length($str), ''));
+
+=item int64_rand
+
+Generates a 64 bit random number using ISAAC-64 algorithm.
+
+=item int64_srand($seed)
+
+=item int64_srand()
+
+Sets the seed for the random number generator.
+
+C<$seed>, if given, should be a 2KB long string.
+
+=item uint64
+
+=item uint64_to_number
+
+=item net_to_uint64
+
+=item uint64_to_net
+
+=item native_to_uint64
+
+=item uint64_to_native
+
+=item string_to_uint64
+
+=item hex_to_uint64
+
+=item uint64_to_string
+
+=item uint64_to_hex
+
+These functions are similar to their int64 counterparts, but
+manipulate 64 bit unsigned integers.
+
+=item uint64_to_BER($u64)
+
+Encodes the given unsigned integer in BER format (see L<perlfunc/pack>).
+
+=item BER_to_uint64($str)
+
+Decodes from the given string an unsigned number in BER format.
+
+=back
+
+=head2 Die on overflow
+
+The lexical pragma C<Math::Int64::die_on_overflow> configures the
+module to throw an error when some operation results in integer
+overflow.
+
+For instance:
+
+ use Math::Int64 qw(uint64);
+ use Math::Int64::die_on_overflow;
+
+ my $zero = uint64(0);
+ say ($zero - 1); # dies as -1 falls outside
+ # the uint64_t range
+
+ no Math::Int64::die_on_overflow; # deactivates lexical pragma
+ say ($zero - 1); # no error is detected here!
+
+The pragma can also be activated as follows:
+
+ use Math::Int64 ':die_on_overflow';
+
+Once this pragma is used, several Math::Int64 operations may become
+slower. Deactivating the pragma will not make them fast again.
+
+On Perl 5.8.x, as lexical pragmas support is not available, the pragma
+C<die_on_overflow> pragma is global and can not be deactivated.
+
+=head2 Fallback to native 64bit support if available
+
+If the lexical pragma C<Math::Int64::native_if_available> is used in
+your program and the version of perl in use has native support for
+64bit intgers, the functions imported from the module that create
+64bit integers (i.e. C<uint64>, C<int64>, C<string_to_int64>,
+C<native_to_int64>, etc.) will return regular perl scalars.
+
+For instance:
+
+ use Math::Int64 qw(int64);
+
+ $a = int64(34); # always returns an object of the class Math::Int64
+
+ use Math::Int64::native_if_available;
+ $a = int64(34); # returns a regular scalar on perls compiled with
+ # 64bit support
+
+This feature is not enabled by default because the semantics for perl
+scalars and for 64 bit integers as implemented in this module are not
+identical.
+
+Perl is prone to coerze integers into floats while this module keeps
+then always as 64bit integers. Specifically, the division operation
+and overflows are the most problematic cases.
+
+Besides that, in most situations it is safe to use the native fallback.
+
+As happens with the C<die_on_overflow> pragma, on Perl 5.8.x it is
+global.
+
+The pragma can also be activated as follows:
+
+ use Math::Int64 ':native_if_available';
+
+=head2 Transparent conversion of objects to int64/uint64
+
+When in some operation involving int64/uint64 numbers, a blessed
+object is passed as an operand, the module would try to coerce the
+object into an int64/uint64 number calling the methods
+C<as_int64>/C<as_uint64> respectively.
+
+If the corresponding method is not implemented, the object will be
+stringified and then parsed as a base 10 number.
+
+=head2 Storable integration
+
+Objects of classes Math::Int64 and Math::UInt64 implement the
+STORABLE_freeze and STORABLE_thaw methods for a transparent
+integration with L<Storable>.
+
+=head2 C API
+
+This module provides a native C API that can be used to create and
+read Math::Int64 int64 and uint64 SVs from your own XS modules.
+
+In order to use it you need to follow these steps:
+
+=over 4
+
+=item *
+
+Import the files C<perl_math_int64.c>, C<perl_math_int64.h> and
+optionally C<typemaps> from Math::Int64 C<c_api_client> directory into
+your project directory.
+
+=item *
+
+Include the file C<perl_math_int64.h> in the C or XS source files
+where you want to convert 64bit integers to/from Perl SVs.
+
+Note that this header file requires the types int64_t and uint64_t to
+be defined beforehand.
+
+=item *
+
+Add the file C<perl_math_int64.c> to your compilation targets (see the
+sample Makefile.PL below).
+
+=item *
+
+Add a call to the macro C<PERL_MATH_INT64_LOAD_OR_CROAK> into the
+C<BOOT> section of your XS file.
+
+=back
+
+For instance:
+
+ --- Foo64.xs ---------
+
+ #include "EXTERN.h"
+ #include "perl.h"
+ #include "XSUB.h"
+ #include "ppport.h"
+
+ /* #define MATH_INT64_NATIVE_IF_AVAILABLE */
+ #include "math_int64.h"
+
+ MODULE = Foo64 PACKAGE = Foo64
+ BOOT:
+ PERL_MATH_INT64_LOAD_OR_CROAK;
+
+ int64_t
+ some_int64()
+ CODE:
+ RETVAL = -42;
+ OUTPUT:
+ RETVAL
+
+
+ --- Makefile.PL -----
+
+ use ExtUtils::MakeMaker;
+ WriteMakefile( NAME => 'Foo64',
+ VERSION_FROM => 'lib/Foo64.pm',
+ OBJECT => '$(O_FILES)' );
+
+
+If the macro C<MATH_INT64_NATIVE_IF_AVAILABLE> is defined before
+including C<perl_math_int64.h> and the perl interpreter is compiled
+with native 64bit integer support, IVs will be used to represent 64bit
+integers instead of the object representation provided by Math::Int64.
+
+These are the C macros available from Math::Int64 C API:
+
+=over 4
+
+=item SV *newSVi64(int64_t i64)
+
+Returns an SV representing the given int64_t value.
+
+=item SV *newSVu64(uint64_t 64)
+
+Returns an SV representing the given uint64_t value.
+
+=item int64_t SvI64(SV *sv)
+
+Extracts the int64_t value from the given SV.
+
+=item uint64_t SvU64(SV *sv)
+
+Extracts the uint64_t value from the given SV.
+
+=item int SvI64OK(SV *sv)
+
+Returns true is the given SV contains a valid int64_t value.
+
+=item int SvU64OK(SV *sv)
+
+Returns true is the given SV contains a valid uint64_t value.
+
+=item uint64_t randU64(void)
+
+Returns a random 64 bits unsigned integer.
+
+=back
+
+If you require any other function available through the C API don't
+hesitate to ask for it!
+
+=head1 BUGS AND SUPPORT
+
+The Storable integration feature is experimental.
+
+The C API feature is experimental.
+
+This module requires int64 support from the C compiler.
+
+In order to report bugs you can send me and email to the address that
+appears below or use the CPAN RT bugtracking system available at
+L<http://rt.cpan.org>.
+
+The source for the development version of the module is hosted at
+GitHub: L<https://github.com/salva/p5-Math-Int64>.
+
+=head2 My wishlist
+
+If you like this module and you're feeling generous, take a look at my
+Amazon Wish List: L<http://amzn.com/w/1WU1P6IR5QZ42>
+
+=head1 SEE ALSO
+
+The C API usage sample module L<Math::Int64::C_API::Sample>.
+
+Other modules providing support for larger integers or numbers are
+L<Math::BigInt>, L<Math::BigRat> and L<Math::Big>,
+L<Math::BigInt::BitVect>, L<Math::BigInt::Pari> and
+L<Math::BigInt::GMP>.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright E<copy> 2007, 2009, 2011-2013 by Salvador FandiE<ntilde>o
+(sfandino@yahoo.com)
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.8 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut