in reply to Supporting long long types in XS

I don't think a 32 bit perl has a direct equivalent of 64 bit integers. That probably means you can do 3 things:

1. Use a 32 bit int (i.e. T_IV or T_UV) which has the advantage that any numbers in the 32 bit range can be accurately be represented, but higher numbers cannot be represented at all.

2. Use a floating point number (i.e. T_NV, which is an 8-bitbyte double on my system) which is able to represent the whole range, but not 100% accurately.

3. Create your own type conversion from/to a perl object (i.e. an XS pointer to a long long, in which case you need to provide some mechanism for read/write access, or maybe you can convert from/to Math::BigInt). Probably the most hassle, but you can guarantee precision and range.

Update: I just thought of another way: you can convert from/to a string representation of the number. Should be easy to do, but the perl side of things has to be careful not to accidentally convert it back to a number (float or int). That means you won't be able to do normal arithmatics with it (you'll have to use Math::BigInt or something similar).

Replies are listed 'Best First'.
Re^2: Supporting long long types in XS (NV,PV)
by tye (Sage) on Nov 21, 2006 at 18:29 UTC
    Use a 32 bit int (i.e. T_IV or T_UV) which has the advantage that any numbers in the 32 bit range can be accurately be represented,

    Note that this is not an advantage over NV (floating point). A Perl NV can exactly represent any 52-bit integer (53 if you count the sign bit) on almost any platform (I think even Crays use standard IEEE 8-byte double-precision floating point numbers). 52-bit values often are quite sufficient for such situations (address 4 peta bytes or store 142 years in microseconds).

    But if you really want to allow for full 64-bit values, my first idea was also to use a string of digits for the representation. That is probably the best choice for an XS interface, as it will conveniently and silently allow the user to switch to NV or IV if they don't need values that won't fit in such a type (or don't need full precision for some values in the case of NV).

    But doing this right will be a little tricky. In particular, you'll need to pay attention to what value types the scalar passed to you has, and which of those value type(s) is/are primary. Perhaps use the scalar's NV if SvNOK() [not SvNOKp()] or not SvPOK(), otherwise use the scalar's PV [if SvPOK() but not SvNOK()].

    - tye        

        No, there's nothing to worry about ( when doing floating point operations on < 52 bit ints stored in doubles ). Floating point errors come from the inability to represent a number accurately within the available precision. No error is loss when the number can be accurately represented within the available precision.

        Update: Added the text in bold parens for clarity.

        Reach your own conclusions?

        $nv = 2**33;; printf "%.f\n", $nv;; 8589934592 printf "%d\n", $nv;; -1 print $nv;; 8589934592 print $nv & 1;; 1 print $nv;; 8589934592

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.