Skip Menu |

This queue is for tickets about the Math-BigInt CPAN distribution.

Report information
The Basics
Id: 113943
Status: resolved
Priority: 0/
Queue: Math-BigInt

People
Owner: Nobody in particular
Requestors: ZDM [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 1.999719



Subject: Possibly new bug in the Math::BigFloat
Hi. We found, that CBOR::XS has stpped building after latest Math::* update. After the short investigation we found, that this is, possibly, new bug in Math::BigFloat. use Math::BigFloat; $x = Math::BigFloat->new (3); $x = $x->blsft (-1, 2); warn "$x"; This should give 1.5, but results in NaN. With older versions, this works correctly.
Show quoted text
> use Math::BigFloat; > > $x = Math::BigFloat->new (3); > $x = $x->blsft (-1, 2); > warn "$x"; > > This should give 1.5, but results in NaN. With older versions, > this works correctly.
Shifting floats make no sense, because the internal representation is not just a sequence of bits that can be shifted left and right. If you search the net for bit-shifting floats you will find explanations for this. Since shifting floats make no sense, core Perl truncates floats to integers when you apply bit operations to floats. In the Math::Big* modules, shifting left by -1 is equivalent to shifting right by 1. Doing this with Perl gives you 1, not 1.5: $ perl -Mstrict -wle 'print 3 >> 1' 1 Note that bits that "fall off the end" to the right are dropped, so the result of a bit-shift operation in Perl is always an integer. The intention in the latest version of Math::BigFloat (and Math::BigRat) is to behave like core Perl in this manner. I.e., bit-shifting operations on a float truncates the float to an integer, applies the bit-shifting (dropping bits that "fall of the end" to the right). So I expected the answer to be 1. I won't agree that it is a bug that you don't get 1.5, but it is certainly a bug that the result is a NaN.
I was wrong, when I wrote "In the Math::Big* modules, shifting left by -1 is equivalent to shifting right by 1. This was true only for Math::BigFloat, and it was not according to the documentation. The documentation says blsft() and brsft() shifts left and right, and refers to the documentation in Math::BigInt, which says "Right shifting usually amounts to dividing $x by $n ** $y and truncating the result". So, the fact that you got 1.5 rather than 1, was not according to the documentation. With Math::BigInt, shifting left by a negative amount results in a NaN, and since Math::BigFloat now lets Math::BigInt do the actual shifting, that's why you got the NaN. In Perl, shifting left by a negative amount causes the bits to wrap, so while 3 >> 2 gives 0, 3 << -2 gives 13835058055282163712 (with 64 bit integer support). The equivalent in Math::BigInt is to return inf, I believe. By the way, if what you actually want to do is to multiply by a number (base) raised to some power, replace $x -> blsft($n, $b) with $x -> bmul($b -> copy() -> bpow($n))
Subject: Re: [rt.cpan.org #113943] Possibly new bug in the Math::BigFloat
Date: Mon, 25 Apr 2016 11:51:52 +0300
To: bug-Math-BigInt [...] rt.cpan.org
From: "dzagashev [...] gmail.com" <dzagashev [...] gmail.com>
Please, read this analysis report. http://blog.schmorp.de/2016-04-23-mathbigfloat-maintainer-fail.html On 25.04.2016 11:37, Peter John Acklam via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=113943 > > > I was wrong, when I wrote "In the Math::Big* modules, shifting > left by -1 is equivalent to shifting right by 1. This was true > only for Math::BigFloat, and it was not according to the > documentation. The documentation says blsft() and brsft() shifts > left and right, and refers to the documentation in Math::BigInt, > which says "Right shifting usually amounts to dividing $x by > $n ** $y and truncating the result". So, the fact that you got 1.5 > rather than 1, was not according to the documentation. > > With Math::BigInt, shifting left by a negative amount results in a > NaN, and since Math::BigFloat now lets Math::BigInt do the actual > shifting, that's why you got the NaN. > > In Perl, shifting left by a negative amount causes the bits to > wrap, so while 3 >> 2 gives 0, 3 << -2 gives 13835058055282163712 > (with 64 bit integer support). The equivalent in Math::BigInt is > to return inf, I believe. > > By the way, if what you actually want to do is to multiply by a > number (base) raised to some power, replace > > $x -> blsft($n, $b) > > with > > $x -> bmul($b -> copy() -> bpow($n))
On Mon Apr 25 04:52:14 2016, dzagashev@gmail.com wrote: Show quoted text
I have read the "analysis", and I have to admit it would be easier to take it more seriously if it weren't for all the ranting, straw man arguments, and false assumtions made there. I am more than willing to discuss my change, including how blsft() and brsft() ought to behave, but I am not going to spend time wading through a lot of ranting. I have a few replies to the "analysis". - Just because some piece of code has behaved in a certain way over many years, doesn't make that behaviour correct. Hence, changing a certain old behaviour isn't necessarily a bug. - blsft() and brsft() are so poorly documented that it is not obvious what is the correct behaviour. The documentation provided in the "analysis" is just one of several fragments. The actual documentation in the modules contain other pieces of documentation that can be interpreted differently than the one provided in the "analysis". - Considering Math::Big(Int|Float|Rat) toy modules that are too unreliable for serious use is nothing new. They have been toy modues ever since TELS redesigned these modules more than 10 years ago. Initially, my intention was to use these modules for numerical analysis of special functions, but I didn't dare, because I quickly realized that these modules contain a staggering amount of bugs, inconsistencies and a fundamentally flawed design. This has also been commented by some of the most well-known people in the Perl community. - Am I the best maintainer for these modules? Maybe not, but at least I am maintaining them. I took over as maintainer because no one else gave these modules the priority they deserved. I believe I have both reported and fixed more bugs in these modules than anyone else. And when someone has pointed out that I have, unfortunately, introduced a bug, I have fixed it quickly. - I have not claimed that Perl core has a blsft() method. However, since others have referred to << and >> as bitwise operators, and since Math::Big* overloads << and >> to directly call blsft() and brsft() I was under the impression that blsft() and brsft() were bitwise operators. - I have not claimed that << and >> in Math::Big* should emulate Perl core << and >> in every aspect. - I have not claimed that I will keep the current behaviour of blsft() and brsft().
I see now that when blsft() is tested in the test suite file t/bigfltpm.inc, it actually runs <<, not blsft(), again indicating that << and blsft() should be equivalent.
I have reverted the changes to blsft() and brsft() in Math::BigFloat and uploaded v1.999719 of the Math-BigInt distro to CPAN.
Subject: Re: [rt.cpan.org #113943] Resolved: Possibly new bug in the Math::BigFloat
Date: Tue, 26 Apr 2016 17:31:05 +0300
To: bug-Math-BigInt [...] rt.cpan.org
From: "dzagashev [...] gmail.com" <dzagashev [...] gmail.com>
Peter, you are the best maintainer for this modules. I am sorry, if that article was too critical and thank you for your work. On 26.04.2016 12:38, Peter John Acklam via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=113943 > > > According to our records, your request has been resolved. If you have any > further questions or concerns, please respond to this message.
Subject: Re: [rt.cpan.org #113943] Resolved: Possibly new bug in the Math::BigFloat
Date: Thu, 28 Apr 2016 15:07:28 -0400
To: bug-Math-BigInt [...] rt.cpan.org
From: "Tels" <nospam-abuse [...] bloodgate.com>
On Tue, April 26, 2016 10:31 am, dzagashev@gmail.com via RT wrote: Show quoted text
> Queue: Math-BigInt > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=113943 > > > Peter, you are the best maintainer for this modules. I am sorry, if that > article was too critical and thank you for your work. > > > On 26.04.2016 12:38, Peter John Acklam via RT wrote:
>> <URL: https://rt.cpan.org/Ticket/Display.html?id=113943 > >> >> According to our records, your request has been resolved. If you have >> any >> further questions or concerns, please respond to this message.
Hello together, sorry for the late reply, I seldom check my emails these days. Thank you, Peter for mainting my pileofcrap^Wmodules! This is much appeciated, and a lot of work you probably get not thanks for :) According to the bugreport, the changes have already been reverted. I'd still like to add a bit of reasoning and history here, just for the record. Maybe this helps in the future with such decisions. There was some reasoning along the lines of "<< uses blsft() so they must be equivalent.". That's not what was intended. First: the "bigfloat" etc modules where invented to get better math into Perl without having to rewrite scripts. Even after much work, that never really works except in special cases. However, to get them even to work, we need overloaded operators. And to avoid reinventing the wheel, "<<" simply uses blsft(). That does not mean, however, that blsft() should work only on or return integers, or that the "<<" operator should actually be exactly the same as blsft()! (Yes, I know, I should have added a lot more documentation. My bad.) And second: Math::BigRat should be a superset of Math::BigFloat and this should be a superset of Math::BigInt. So a method in BigRat should return (if possible) a BigRat, in BigFloat a BigFloat - and not just truncate to BigInt. I think the confusion might come from the fact that the modules share a lot of code, design and are interwined a lot. In theory, however, you should be able to use Math::BigFloat and compute with BigFloats w/o even knowing about Math::BigInt. Anyway, the Math::Big modules have indeed not had the best history - and while my rewrite back then took staggering amounts of work it still left way too many loose ends for my taste. I probably also added a few bad design choices and bugs - sorry for that, but my (Perl) knowledge was limited back then. The rewritten modules are still, IMHO, light-years ahead than what we had before. If anyone thinks they are still insufficient for real work - well, you can always roll your own :) Thanx for reading, tels -- http://bloodgate.com/galleries/
On Thu Apr 28 15:07:42 2016, nospam-abuse@bloodgate.com wrote: Show quoted text
> > (Yes, I know, I should have added a lot more documentation. My bad.)
The lack of documentation makes it more difficult to determine what is a big. Without the documentation there is no reference stating how it should actually work. But lack of documentation is just one part of the problem -- equally bad is all the documentation that is wrong. Here are some cases extracted from just a few lines in Math::BigFloat: - Output values are BigFloat objects (normalized), except for bstr() and bsstr(). Wrong. The parts() method returns BigInt objects, not BigFloats. - The string output will always have leading and trailing zeros stripped and drop a plus sign. Wrong. Zeros are padded to the current accuracy or precision. E.g., the number 2 with accuracy 3 prints "2.00". - The input ' -123 123 123' will cause bsstr() to print '-123123123E0'. Wrong. Firstly, the input ' -123 123 123' is invalid and will produce a NaN. Secondly, if the input was valid, the output would be '-123123123e+0', with a lower-case 'e' and a sign in the exponent. - bsstr() returns a string in scientific notation. Questionable. The value of "3141592e-6" is correct, but standard scientific notation is "3.141592e+0" or ".3141592e+1", the latter possibly with a leading zero. Show quoted text
> And second: Math::BigRat should be a superset of Math::BigFloat and this > should be a superset of Math::BigInt.
That hardly makes sense, since rational numbers is not a superset of floating point numbers. However, both rational numbers and floating point numbers are supersets of integers. In any case, I can not make sens of the way it is implemented. Currently, a Math::BigInt object is a sign and an integer. And it would make sense if a Math::BigFloat object was a Math::BigInt with an added fraction part, but that isn't at all how it is implemented. The only thing a Math::BigInt, a Math::BigFloat and a Math::BigRat have in common is the sign. And with that implementation, it doesn't make sense that they are subclasses of each other. If this wasn't enough, Math::BigFloat->isa() tells that Math::BigFloat isn't a Math::BigInt after all. There is no end to the mess. Show quoted text
> If anyone thinks they are still insufficient for real work - well, you > can always roll your own :)
That is just arrogant. Math::BigInt, Math::BigFloat, and Math::BigRat are in the Perl distribution, so people expect them to work properly.