http://www.perlmonks.org?node_id=973616

bulk88 has asked for the wisdom of the Perl Monks concerning the following question:

This is related to supporting SSE 128 bit data in Perl. 32 bit Perl doesn't come with quads/Q/q pack letter. I have a C library that uses 64 bit ints. I use perl on windows. My C compiler also has no problems with 64 bit ints. Perl NVs don't loose integer precision until 2^53. 53 is not 64. What should my XS wrapper around this C library return the 64 bit ints as in 32 bit perl? There seems to be alot negativity over Math::BigInt's bloatedness. Also how to do you load packed little endian numbers into Math::BigInt, it seems bigint only knows what big endian ASCII hex is for importing numbers. The solution should be CPAN grade. Quads are very rarely used by this C library but they need to be exposed somehow for the rare case someone wants to call that function. The simplest thing is, on 32 bits, a 64 bit int is a 8 byte packed LE PV string, conversion routines warn() and pads if under 8 bytes long. On 64 bits its a IV/UV. Is this last solution the best solution?

Replies are listed 'Best First'.
Re: supporting quads on 32 bit Perl
by BrowserUk (Patriarch) on May 31, 2012 at 21:42 UTC

    See Math::Int64


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

        I was thinking more along the lines of you could steal the initialisation code from it to add to your XS wrapper of the C library you are trying to access.

        However, you should also be able to compile it with CPAN or manually without difficulty.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        The start of some sanity?

        Its not available on 32 bit Windows through packagers

        For the record, both bribes and sisyphusion repos provide ppm packages for Math::Int64.

        Cheers,
        Rob
Re: supporting quads on 32 bit Perl (0.23)
by ikegami (Patriarch) on Jun 04, 2012 at 17:35 UTC

    [ The thread was getting too deep. ]

    The third test of MSC.t is failing for me.

    • Math-Int64-0.23
    • ActivePerl build 1402
    • Perl 5.14.2, 32 bit, threaded.
    • Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    t/MSC.t ................. 1/3 # Failed test 'uint64 to NV conversion 3' # at t/MSC.t line 15. # Looks like you failed 1 test of 3. t/MSC.t ................. Dubious, test returned 1 (wstat 256, 0x100) Failed 1/3 subtests t/MSC.t (Wstat: 256 Tests: 3 Failed: 1) Failed test: 3 Non-zero exit status: 1

    I changed the test from ok to is tests to get more info:

    t/MSC.t ................. 1/3 # Failed test 'uint64 to NV conversion 3' # at t/MSC.t line 15. # got: '1.83746864796716e+019' # expected: '18374686479671623680' # Looks like you failed 1 test of 3.

    The thing is I can't see any different between the two by looking at them using sprintf or pack 'd'.

    nv: 1.837468647967162400000000000000e+019 u: 1.837468647967162400000000000000e+019 nv: 43efe00000000000 u: 43efe00000000000

    The warnings I get:

    Int64.xs(256) : warning C4244: 'return' : conversion from 'NV' to 'int +64_t', possible loss of data Int64.xs(335) : warning C4244: 'return' : conversion from 'NV' to 'uin +t64_t', possible loss of data Int64.xs(345) : warning C4244: 'initializing' : conversion from 'int64 +_t' to 'IV', possible loss of data Int64.xs(350) : warning C4244: 'initializing' : conversion from 'int64 +_t' to 'UV', possible loss of data Int64.xs(354) : warning C4244: 'function' : conversion from 'int64_t' +to 'const NV', possible loss of data Int64.xs(360) : warning C4244: 'initializing' : conversion from 'uint6 +4_t' to 'UV', possible loss of data Int64.xs(363) : warning C4244: 'function' : conversion from 'uint64_t' + to 'const NV', possible loss of data Int64.xs(375) : warning C4244: 'initializing' : conversion from 'uint6 +4_t' to 'char', possible loss of data Int64.xs(492) : warning C4244: 'function' : conversion from 'int64_t' +to 'const IV', possible loss of data Int64.xs(516) : warning C4244: 'function' : conversion from 'uint64_t' + to 'const UV', possible loss of data Int64.xs(535) : warning C4244: '=' : conversion from 'int64_t' to 'cha +r', possible loss of data Int64.xs(553) : warning C4244: '=' : conversion from 'uint64_t' to 'ch +ar', possible loss of data Int64.xs(669) : warning C4244: 'function' : conversion from 'uint64_t' + to 'const IV', possible loss of data Int64.xs(680) : warning C4244: 'function' : conversion from 'uint64_t' + to 'const UV', possible loss of data Int64.xs(690) : warning C4244: 'function' : conversion from 'uint64_t' + to 'const IV', possible loss of data Int64.xs(700) : warning C4244: 'function' : conversion from 'uint64_t' + to 'const UV', possible loss of data Int64.xs(712) : warning C4244: 'function' : conversion from 'int64_t' +to 'const IV', possible loss of data Int64.xs(723) : warning C4244: 'function' : conversion from 'uint64_t' + to 'const IV', possible loss of data Int64.c(1288) : warning C4101: 'rev' : unreferenced local variable Int64.c(1287) : warning C4101: 'other' : unreferenced local variable Int64.c(1317) : warning C4101: 'rev' : unreferenced local variable Int64.c(1316) : warning C4101: 'other' : unreferenced local variable Int64.c(1782) : warning C4101: 'rev' : unreferenced local variable Int64.c(1811) : warning C4101: 'rev' : unreferenced local variable Int64.c(2107) : warning C4101: 'rev' : unreferenced local variable Int64.c(2106) : warning C4101: 'other' : unreferenced local variable Int64.c(2133) : warning C4101: 'rev' : unreferenced local variable Int64.c(2132) : warning C4101: 'other' : unreferenced local variable Int64.c(2159) : warning C4101: 'rev' : unreferenced local variable Int64.c(2158) : warning C4101: 'other' : unreferenced local variable Int64.c(2185) : warning C4101: 'rev' : unreferenced local variable Int64.c(2184) : warning C4101: 'other' : unreferenced local variable Int64.c(2211) : warning C4101: 'rev' : unreferenced local variable Int64.c(2210) : warning C4101: 'other' : unreferenced local variable Int64.c(2237) : warning C4101: 'rev' : unreferenced local variable Int64.c(2236) : warning C4101: 'other' : unreferenced local variable Int64.c(2263) : warning C4101: 'rev' : unreferenced local variable Int64.c(2262) : warning C4101: 'other' : unreferenced local variable Int64.c(2289) : warning C4101: 'rev' : unreferenced local variable Int64.c(2288) : warning C4101: 'other' : unreferenced local variable Int64.c(2317) : warning C4101: 'rev' : unreferenced local variable Int64.c(2316) : warning C4101: 'other' : unreferenced local variable Int64.c(2763) : warning C4101: 'rev' : unreferenced local variable Int64.c(2792) : warning C4101: 'rev' : unreferenced local variable Int64.c(3088) : warning C4101: 'rev' : unreferenced local variable Int64.c(3087) : warning C4101: 'other' : unreferenced local variable Int64.c(3114) : warning C4101: 'rev' : unreferenced local variable Int64.c(3113) : warning C4101: 'other' : unreferenced local variable Int64.c(3140) : warning C4101: 'rev' : unreferenced local variable Int64.c(3139) : warning C4101: 'other' : unreferenced local variable Int64.c(3166) : warning C4101: 'rev' : unreferenced local variable Int64.c(3165) : warning C4101: 'other' : unreferenced local variable Int64.c(3192) : warning C4101: 'rev' : unreferenced local variable Int64.c(3191) : warning C4101: 'other' : unreferenced local variable Int64.c(3218) : warning C4101: 'rev' : unreferenced local variable Int64.c(3217) : warning C4101: 'other' : unreferenced local variable Int64.c(3244) : warning C4101: 'rev' : unreferenced local variable Int64.c(3243) : warning C4101: 'other' : unreferenced local variable ...\int64.xs(170) : warning C4715: 'SvSI64' : not all control paths re +turn a value ...\int64.xs(180) : warning C4715: 'SvSU64' : not all control paths re +turn a value
      The thing is I can't see any different between the two by looking at them using sprintf or pack 'd'.

      That's because sprintf and pack first convert the uint64 into an NV implicitly.

      On the other hand, is converts its operands into strings and compares them. The NV is represented in scientific notation and the uint64 in decimal and so they differ.

Re: supporting quads on 32 bit Perl
by sundialsvc4 (Abbot) on May 31, 2012 at 23:22 UTC

    Frankly, I would say that before you do anything else you should use that “C compiler that has no problems with 64-bit ints” to compile a version of Perl.   In other words, sidestep completely the issue of providing a 64-bit quantity to a Perl that can’t handle it.   You will gain absolutely nothing by solving that curious technical problem ...   In whatever form of XS-magic that you ultimately do, require a 64-bit Perl and ignore the rest.   These days you can run 64-bit ints just as easily as you can run 32-bit; therefore, do so.

      The solution should be CPAN grade.
      Frankly, I would say that before you do anything else you should use that “C compiler that has no problems with 64-bit ints” to compile a version of Perl.   In other words, sidestep completely the issue of providing a 64-bit quantity to a Perl that can’t handle it.
      ........................
      These days you can run 64-bit ints just as easily as you can run 32-bit; therefore, do so.
      I understand you're being frank. 64 bit Windows users are currently a minority, http://www.itsnyc.com/index.php/blog/item/windows-7s-64-bit-adoption. I think you know the status and support of Perl 32 bit pointers with 64 bit ints on Windows.