FAQ
-----BEGIN PGP SIGNED MESSAGE-----

Moin,

I got a bugreport from Dennis Boylan:

# perl -Mbigint -le 'print cos(4)'
Operation `cos': no method found, argument in overloaded package Math::BigInt
at -e line 1.

He reported that it works on some machine (older Perl, older BigInt, older GD
module) but no longer on the newer one. In my tests I think it never works
regardless of Perl or BigInt version, and it only worked for him because the
older GD (or GD::Piechart or something) didn't use cos() or used it
differently.

Now, there is an easy "fix", add the following lines to the overload section
of BigInt:

'cos' => sub { cos($_[0]->numify()) },
'sin' => sub { sin($_[0]->numify()) },

This would produce:

# perl -Ilib -Mbigint -le 'print sin(4)'
-0.756802495307928

However, to be consistent with the rest, it should really calculate:

* an integer result if in BigInt
* a float to arbitrary precision if in BigFloat
* a float if under "bignum" and a BigInt is passed

However, the catch is: BigInt/BigFloat don't know about cos()/sin(). The
module that can do this is Math::Big, not part of the core, and maybe not
even installed. Two options:

* include the code from Math::Big in BigInt/BigFloat (with suitable speedup
by putting it into Calc.pm)
* require Math::Big as in:

'cos' => sub {
require Math::Big;
return Math::Big::cos($_[0], ref($_[0])->accuracy());
},

The latter option produces:

# perl -Ilib -Mbigint -le 'print cos(2)'
-0.416146836547142386997568229500762189766001
# perl -Ilib -Mbigint=a,50 -le 'print cos(2)'
-0.41614683654714238699756822950076218976600077107554

Of course, that is not "right", because BigInt should return a truncated int()
as it does for sqrt() etc, and BigFloat should return the full result, and if
under bignum, BigInt should upgrade.

However, the critical question is:

Should BigInt duplicate/take ransom the code from Math::Big? Or should it
simple "require Math::Big" (with suitable error message if not found)?

Of course, this also poses the question of tan(), arctan(), and all the other
nastity stuff, along of the question of pi(), euler() etc. Ugh. Math::Big is
certainly not small (no pun intended).

Best wishes,

Tels

- --
Signed on Sat Oct 25 21:14:38 2003 with key 0x93B84C15.
Visit my photo gallery at http://bloodgate.com/photos/
PGP key on http://bloodgate.com/tels.asc or per email.

"We have problems like this all of the time," Kirk said, trying to
reassure me. "Sometimes its really hard to get things burning." --
http://tinyurl.com/qmg5

Search Discussions

  • Tels at Oct 26, 2003 at 11:22 am
    -----BEGIN PGP SIGNED MESSAGE-----

    Moin,
    On Sunday 26 October 2003 11:51, you wrote:
    Tels wrote:
    :I got a bugreport from Dennis Boylan:
    :
    : # perl -Mbigint -le 'print cos(4)'
    : Operation `cos': no method found, argument in overloaded package
    : Math::BigInt at -e line 1.

    [...]

    :However, the critical question is:
    :
    :Should BigInt duplicate/take ransom the code from Math::Big? Or should it
    :simple "require Math::Big" (with suitable error message if not found)?
    :
    :Of course, this also poses the question of tan(), arctan(), and all the
    : other nastity stuff, along of the question of pi(), euler() etc. Ugh.
    : Math::Big is certainly not small (no pun intended).

    Without looking at the code to check whether this is a suitable approach,
    my normal inclination would be to have an AUTOLOAD that tries to load the
    Math::Big module and dies on failure. If the list of relevant functions
    is short enough to include you can check for relevance beforehand, else
    you can check afterwards:
    AFAICS, the only methods in question are cos() and sin(), and they are only
    triggered via overload. (e.g., there is currently no bcos() routine in
    Big(Int|Float)).

    However, for completeness, bcos() and bsin() should be added - probably alone
    because the code for the overload section would get to big and clunky.

    Actually, sin() and cos() in Math::Big are selfcontained, so we would only
    need to copy/import these and the rest can stay happily in Math::Big. Which
    makes the "let's copy it over and have Math::Big::cos() just call
    Math::BigFLoat::bcos()" argument look even better.

    There is also another reason to copy the code over apart from beeing less
    hairy:

    Math::Big uses BigFloat to calculate the result. So Math::BigInt::bcos() would
    suddenly pull in Math::Big and Math::BigFloat. Ugh.

    I lean towards to include an all-integer method of calculating sin() and cos()
    in Calc, and then use it in BigInt and BigFloat, whith BigInt retunring 0 or
    1 alway (truncated to integer) or upgrading to BigFloat if wanted.

    However, thats some more work..

    Best wishes,

    Tels

    PS: Here is the code from Math::Big, cos() is very similiar:

    sub sin
    {
    # calculate sinus
    # first argument is x, so that result is sin(x)
    # Second argument is accuracy (number of significant digits), it
    # stops when at least so much plus one digits are 'stable' and then
    # rounds it. Default is 42.
    my $x = shift || 0;
    my $d = abs(shift || 42); $d = abs($d)+1;

    $x = Math::BigFloat->new($x) if ref($x) ne 'Math::BigFloat';
    my $diff = Math::BigFloat->new('1e-'.$d);

    # taylor: x^3 x^5 x^7 x^9
    # sin = x - --- + --- - --- + --- ...
    # 3! 5! 7! 9!

    # difference for each term is thus x^2 and 1,2

    my $sin = $x->copy(); my $last = 0;
    my $x2 = $x*$x;
    my $over = $x2 * $x; my $below = 6; my $factorial = Math::BigInt->new(4);
    my $sign = 1;
    while ($sin ne $last) # no $x-$last > $diff because bdiv() limit on accuracy
    {
    $last = $sin->copy();
    if ($sign == 0)
    {
    $sin += $over->copy()->bdiv($below,$d);
    }
    else
    {
    $sin -= $over->copy()->bdiv($below,$d);
    }
    $sign = 1-$sign; # alternate
    $over *= $x2; # $x*$x
    $below *= $factorial; $factorial++; # n*(n+1)
    $below *= $factorial; $factorial++;
    }
    return $sin->round($d-1);
    }

    - --
    Signed on Sun Oct 26 13:23:42 2003 with key 0x93B84C15.
    Visit my photo gallery at http://bloodgate.com/photos/
    PGP key on http://bloodgate.com/tels.asc or per email.

    "My glasses, my glasses. I cannot see without my glasses." - "My glasses,
    my glasses. I cannot be seen without my glasses."
  • Tels at Nov 1, 2003 at 3:29 pm
    -----BEGIN PGP SIGNED MESSAGE-----

    Moin,
    On Saturday 25 October 2003 21:23, Tels wrote:
    Moin,

    I got a bugreport from Dennis Boylan:

    # perl -Mbigint -le 'print cos(4)'
    Operation `cos': no method found, argument in overloaded package
    Math::BigInt at -e line 1.
    I opted no to the following plan:

    * Add an option ':fallback' to BigInt, which tricks overload to make
    cos(Math::BigInt->new(1)) equivalent to cos(1)
    * add option to Math::Big to overload cos(), sin(), atan2() and exp() so that
    they produce BigFloats.

    So:

    * default BigInt dies with "no method found.
    * use BigInt ':fallback'; is equivalent to no BigInt at all AFA
    cos/sin/atan/exp are concerned (e.g. cos(1) returns 0.54etc to 10 digits
    approcimately)
    * use BigInt ':fallback'; use Math::Big qw/:cos :sin :atan2 :exp/; will
    produce BigFloats (selectively)

    There is only one snag:

    te@null:~> cat cos.pl
    #!/usr/bin/perl -w

    package Test;

    # without the "''" nomethod is never called
    use overload
    '""' => sub { $$_[0]} ;

    sub new
    {
    my $a = $_[0];
    bless \$a, 'Test';
    }

    sub import
    {
    overload->import (
    nomethod => sub {
    &{'sCORE::' . $_[3]}( $_[0], $_[1], $_[2] );
    print "nomethod ", join(":", @_), "\n";
    },
    );
    }

    package main;

    use Test;

    print CORE::cos(1),"\n";
    print cos(Test->new(1)),"\n";

    te@null:~> perl cos.pl
    0.54030230586814
    Undefined subroutine &sCORE::cos called at cos.pl line 18.

    I tried UNIVERSAL::cos, main::cos etc, but they all come back as "undefined".
    However, a plain "CORE::cos" works just fine. What do I do wrong? *puzzled*

    Best wishes,

    Tels

    - --
    Signed on Sat Nov 1 17:31:45 2003 with key 0x93B84C15.
    Visit my photo gallery at http://bloodgate.com/photos/
    PGP key on http://bloodgate.com/tels.asc or per email.

    "Remember: If the game let's you do it, it's not cheating." -- Xarax
  • Tels at Nov 1, 2003 at 7:33 pm
    -----BEGIN PGP SIGNED MESSAGE-----

    Moin,
    On Saturday 01 November 2003 17:31, Tels wrote:
    Moin,
    sub import
    {
    overload->import (
    nomethod => sub {
    &{'sCORE::' . $_[3]}( $_[0], $_[1], $_[2] );
    print "nomethod ", join(":", @_), "\n";
    },
    );
    }
    FYI: Note the typo here ("sCORE"), but it still doesn't work if you fix it to
    "correct" 'CORE::' . $_[3]...

    Using somple $_[3] does also not work, since it then dies with "Undefined
    Test::cos called"...

    Best wishes,

    Tels

    - --
    Signed on Sat Nov 1 18:46:52 2003 with key 0x93B84C15.
    Visit my photo gallery at http://bloodgate.com/photos/
    PGP key on http://bloodgate.com/tels.asc or per email.

    "Für eine solche Bitratenreduktion muss ich den Transcoder so
    umkonfigurieren, dass er gröbere Quantisierungskoeffizienten für die
    MPEG-Matrizen verwendet, Captain" - "An die Arbeit, Mr. LaForge." -- Jens
    Baumeister in http://tinyurl.com/oomb

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupperl5-porters @
categoriesperl
postedOct 25, '03 at 7:21p
activeNov 1, '03 at 7:33p
posts4
users2
websiteperl.org

2 users in discussion

Tels: 3 posts Tels: 1 post

People

Translate

site design / logo © 2022 Grokbase