in reply to Re^21: supporting quads on 32 bit Perl
in thread supporting quads on 32 bit Perl
Removing the sign bit and the exponent and prepending the implicit 1., results in 1.1111111000000000000000000000000000000000000000000000. So the number is 0b1.1111111 * 2** (0b10000111110 - 1023) = 0b1.1111111 * 2 ** 63 = 0xff00_0000_0000_0000. The number can be represented precisely as an NV because its last bits are zero.
The problem seems related to the MS compiler not converting correctly between NVs and uint64.
Could you try the current GitHub version and post here the output from MSC.t?
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^23: supporting quads on 32 bit Perl
by bulk88 (Priest) on Jun 04, 2012 at 22:50 UTC | |
Fixed the missing import. Thanks for the lesson in binary math. The hex to binary converter I used, I think I highlighted wrong for the copy in in the converter, and the first 0 was chopped off. From what I read about floating points a couple days ago, exact powers of 2 floating points suffer no rounding/precision loss, and thats what you are testing here right? I might update this post soon if I discover anything interesting. update I rewrote mu64_eqn. which in C is When the test fails, copied from watch window in hex and decimal Hmmm, in SvU64 _fto12 is a static linked piece of code in the DLL tossed in by the compiler, its not part of the CRT/not imported from the CRT DLL, its asm is Will need a while to look through this asm. puts 8000000000000000 in esp+10h, 0x8000000000000000 is what winds up in the uint64 in ::Int64. not 0xFF*. From x86 manual, "Integer Indefinite value (0x80000000) will be returned." from FISTP docs, "If the invalid operation exception is masked, the integer indefinite value is stored in the destination operand." which generated the 0x80* value, right after it executed, FPU status register was 0x3921 according to VS debugger. I don't understand LE/BE and the diagrams online of the fpu status register to decode that 0x3921. Update, the error is fpu invalid operation, and it has to do with the sign bit on the future int64. Given If d1 *= 128.0;, exception thrown/crash. If d1 *= 127.0;, then int64 0x7f00* is created, and no exception thrown. Not sure whose bug this is or how to fix it. I think its simply, fistp creates a signed int64, if the floating point higher than the max signed (0xFF00* has sign bit on for signed), exception thrown. Update, MSVC bug! https://connect.microsoft.com/VisualStudio/feedback/details/106531/co | [reply] [d/l] [select] |
by salva (Canon) on Jun 05, 2012 at 09:40 UTC | |
From what I read about floating points a couple days ago, exact powers of 2 floating points suffer no rounding/precision lossWell, not exactly. IEEE 754 double-precision floats can represent precisely any number with 53 binary digits (and that covers all the integers up to 2**53 and all the powers of two). It is the same as using decimal scientific notation. For instance, with a number of the form XXXeXX you can represent precisely any integer between 0 an 999, but then you can also represent precisely 5670, 56700, 567000, 5670000, etc. The reason of the MSC.t is that at some point, one of the errors on the compilation logs from the ActiveState build server was: There were other places where NVs where converted to uint64 and back even if the compiler didn't spot them, so I added the MSC.t tests to ensure that they were correctly handled... but the thing is that they are not! (see also this). Now, as a work around, I have implemented my own NV->uint64 conversion that will be used instead of the default one when the module is compiled by any MS compiler. Could you test the git version again? | [reply] [d/l] |
by bulk88 (Priest) on Jun 05, 2012 at 16:33 UTC | |
not Typo i kno. After fixing that. I guess we are done then unless you can think of more tests or something you want to try. I embedded it into my module a couple days ago and wrote a *small* test suite for the Math::Int64 part and everything works fine so the build/module tests were the only problems. I decided to NOT use the C API of Math::Int64 and instead used the something_*native*_something Perl subs and called them from XS for stability reasons (although Math::In64 is 4-5 years old, so some will argue all of its API is stable) and also to avoid loading Math::Int64 unless the caller/user does it. Now time for my opinion. I see you versioned the C API, and the version numbers of the C API aren't the mainline module's numbers (good, otherwise a nightmare matching packager build version numbers), and you didn't go the DLL linking route (nightmareish if the dlls are renamed/PAR, or duplicate names exist in the path, someone will say using OS DLL linking is much more efficient than doing it through Perl packages and hashs). You did a better design than Perl TK's C function import/exporter. In Perl TK, an IV with a pointer to a C static struct of function pointers is saved in Perl TK's package as a global. There is poor versioning, the struct does have a length of the struct as the 1st member, and its checked in the client against what the client's Perl TK headers said the struct size was supposed to be. The problem is if the order of the function pointers is changed or they are renamed, but the total length wasn't changed, a crash results. With your system, order is irrelevant, and if a single C function name was removed or changed, an error is thrown. Thats good. I've also realize that most of the build problems were because you wrote ::Int64 in GNUC, not C jkjk. I assume ::Int64 has worked from day 1 on Strawberry Perl. I also tested the latest github (same as above with msc_ver mistake), with Strawberry Perl, nothing to note. Also I looked up how GCC does the double to unsigned int64, This is from SvU64 from " if (may_die_on_overflow && ( (nv < 0) || (nv >= NV_0x1p64)) ) overflow(aTHX_ out_of_bounds_error_u); return NV2U64(nv);" area. The DebugBreak is right before the return statement and after the overflow check. | [reply] [d/l] [select] |
by salva (Canon) on Jun 06, 2012 at 14:21 UTC | |
by bulk88 (Priest) on Jun 06, 2012 at 16:26 UTC | |
|