Giter VIP home page Giter VIP logo

math-gmp's People

Contributors

hvds avatar pghmcfc avatar polettix avatar shlomif avatar trizen avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

polettix pghmcfc

math-gmp's Issues

float-like operations for Math::GMP > 1.8e308

One of my long-running projects has recently reached new heights, dealing with integers greater than 1.8e308. That's fine in the core code where I deal with them as integers, but for some peripheral cases I need to do some float handling, and that code suddenly came crashing down.

I've now worked around that by injecting three extra Math::GMP methods, as below. I'm not sure whether some or all of these are appropriate to include in Math::GMP itself; if you think they would be, I'll put some effort into coming up with implementations that are more robust and efficient, and some tests. (And maybe a better name for bfdiv).

I've also implemented a hack to let me get a sprintf("%g", $gmp) that works for large values with string trickery, but I haven't come up with a way to do it more robustly. (I haven't yet tested it, but docs imply that gmp_sprintf would not support a "%Zg" format.)

Let me know what you think.

my $LONG = 300; # approximate

package Math::GMP {
    sub log10 {
        my($self) = @_;
        my $s = "$self";
        my $len = length($s);
        return log($s) / log(10) if $len < $LONG;
        $s =~ s/^(.)/$1./;
        return log($s) / log(10) + $len - 1;
    }
    sub log {
        my($self) = @_;
        return log10($self) * log(10);
    }
    sub bfdiv {
        my($self, $other) = @_;
        my $sself = "$self";
        # corrected from:
        # return $self / "$other" if length($sself) < $LONG;
        return $sself / "$other" if length($sself) < $LONG;
        my $lother = ref($other) ? $other->log : CORE::log($other);
        return exp($self->log - $lother);
    }
}

sub long_sprintf {
    # $format is expected to have a single %g or similar format specifier
    my($format, $large) = @_;
    my $s = sprintf $format, "$large";
    if ($s =~ /inf/i) {
        my $log = $large->log10;
        my $exp = int($log);
        my $rem = $log - $exp;
        $s = sprintf $format, 10 ** $rem;
        $s =~ s{e\d+|$}{e$exp};
    }
    return $s;
}

=head1 SYNOPSIS

  my $large = Math::GMP->new(10) ** 1000;
  my $smaller = $large * 2 / 3;
  say $large->log10;  # 1000
  say $large->log;    # 2302.58509299405
  say $large->bfdiv($smaller);  # 1.5-ish
  say long_sprintf("%.2g", $large);  # 1.00e1000

=head1 METHODS

=over 4

=head2 log10( )

Returns the base-10 logarithm of the invocant as a Perl float.

=head2 log( )

Returns the natural logarithm of the invocant as a Perl float.

=head2 bdfiv($n)

Returns the invocant divided by C<$n> as a Perl float. C<$n> may be a
C<Math::GMP> object or a standard Perl scalar value. Note that this
will use logarithms/exponentiation for large values, which will limit
its accuracy - use bigfloats instead if you need greater precision.

=back

=head1 FUNCTIONS

=over 4

=head2 long_sprintf($format, $value)

Given a sprintf-style format C<$format> with a single format specification
requesting a value in exponential notation, and a C<Math::GMP> object
C<$value>, returns a string displaying C<$value> in the requested manner.

=back

(edited to s/self/sself/ in bfdiv)

document handling of division by zero

Subsequent to Perl/perl5#19081, I suggest adding something like the following to the docs (probably only after 5.36 is released, though a reduced version could be added immediately).

--- a/lib/Math/GMP.pm 2020-02-09 19:08:42.000000000 +0000
+++ b/lib/Math/GMP.pm 2021-09-08 15:23:54.139606957 +0100
@@ -536,6 +536,31 @@
 
 For internal use. B<Do not use directly>.
 
+=head1 DIVISION BY ZERO
+
+Whereas perl normally catches division by zero to provide a standard
+perl-level error message, C<libgmp> does not; the result is usually
+a SIGFPE (floating point exception) giving a core dump if you ever
+attempt to divide a C<Math::GMP> object by anything that evaluates
+to zero. This can make it hard to diagnose where the error has occurred
+in your perl code.
+
+As of perl-5.36.0, SIGFPE is delivered in a way that can be caught
+by a C<%SIG> handler. So you can get a stack trace with code like:
+
+  use Carp;  # load it up front
+  local $SIG{FPE} = sub { confess(@_) };
+
+Before perl-5.36.0 this approach won't work: you'll need to use
+L<POSIX/sigaction> instead:
+
+  use Carp;
+  use POSIX qw{ sigaction SIGFPE };
+  sigaction(SIGFPE, POSIX::SigAction->new(sub { confess(@_) }));
+
+In either case, you should not attempt to return from the signal
+handler, since the signal will just be thrown again.
+
 =head1 BUGS
 
 As of version 1.0, Math::GMP is mostly compatible with the old

build from git

Hi, I am working with the git repo because I want to add some new functionality to Math::GMP, but there's no Makefile.PL and no info in README or in INSTALL how you might do that. I assume the dist.ini is something to do with it, but I'm also not seeing any clues there.

A link to an appropriate manpage would be welcome.

Intification is broken for integers between 2^63 and 2^64 - 1

Hello! As pointed out in danaj/Math-Prime-Util#20, the intification of Math::GMP seems to return incorrect values for integers between 2^63 and 2^64 - 1.

Example:

use 5.010;
use Math::GMP;

my $n = 9223372036854775828;     # 2^63 + 20
my $z = Math::GMP->new($n);

say $n;             #=> 9223372036854775828
say $z;             #=> 9223372036854775828

say int($n);        #=> 9223372036854775828
say int($z);        #=> 20 (incorrect)

Would be very nice if this can be fixed.

Thanks for your work,
Trizen

MALFORMED Signature file for 2.21

Hi,
I got ==> MALFORMED Signature file! <== from cpansign -v
This makes sense as the SIGNATURE's last line is
SHA256 dc5efc57dfb75d237226e738436163cf52c61d724e2dc595d97d7b95a1196352 xt/release/trailing-space.t
Would you regenerate the file please?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.