Software implementation of 48-bit double

Discussion in 'C Programming' started by Philipp Klaus Krause, Mar 28, 2012.

  1. Are there any free implementations of C11-compliant (though AFAIK this
    is the same as older standard here) 48 bit double?

    Philipp
     
    Philipp Klaus Krause, Mar 28, 2012
    #1
    1. Advertising

  2. On 28.03.2012 22:05, Philipp Klaus Krause wrote:
    > Are there any free implementations of C11-compliant (though AFAIK this
    > is the same as older standard here) 48 bit double?
    >
    > Philipp


    Less than 48 bits, if that is possible, would be interesting, too.

    Philipp
     
    Philipp Klaus Krause, Mar 28, 2012
    #2
    1. Advertising

  3. Philipp Klaus Krause

    jacob navia Guest

    Le 28/03/12 22:05, Philipp Klaus Krause a écrit :
    > Are there any free implementations of C11-compliant (though AFAIK this
    > is the same as older standard here) 48 bit double?
    >
    > Philipp


    Yes. Google after "CEPHES Mathematical library" By S. L. Moshier
     
    jacob navia, Mar 28, 2012
    #3
  4. Philipp Klaus Krause

    BGB Guest

    On 3/28/2012 1:05 PM, Philipp Klaus Krause wrote:
    > Are there any free implementations of C11-compliant (though AFAIK this
    > is the same as older standard here) 48 bit double?
    >


    if relevant, I use a shaved-down 64-bit double as a 48-bit double
    (mostly related to stuffing floating-point values into pointers on
    64-bit targets, although a person can technically go the other direction
    as well and encode a pointer into a double on both 32 and 64-bit targets).

    the conversion then was to simply discard the low 16 bits.

    the main merit though was that this allows reasonably efficient
    conversions to/from the format.


    although not strictly portable, a conversion like this can be made to
    work on many common targets:

    uint64_t DoubleToDouble48(double v)
    { return((*(uint64_t *)(&v))>>16); }

    double Double48ToDouble(uint64_t v)
    {
    uint64_t v2=v<<16;
    return(*(double *)(&v2));
    }

    and, for the pointer case (assumes a target with 64-bit pointers):
    byte *double48_ptrbase; //base address

    void *DoubleToPtrDouble48(double v)
    {
    return(double48_ptrbase+((*(uint64_t *)(&v))>>16));
    }

    double PtrDouble48ToDouble(void *v)
    {
    uint64_t v2=(v-double48_ptrbase)<<16;
    return(*(double *)(&v2));
    }

    acknowledged in advance that this is non-portable / undefined / ...


    other conversions are possible, but are generally considerably longer
    and more expensive.

    generally, it is faster (with the shift trick) to perform arithmetic by
    converting back to normal doubles and doing arithmetic this way (doing
    the arithmetic via integer operations tends to be fairly expensive).


    or such...
     
    BGB, Mar 28, 2012
    #4
  5. Philipp Klaus Krause

    Kaz Kylheku Guest

    On 2012-03-28, BGB <> wrote:
    > On 3/28/2012 1:05 PM, Philipp Klaus Krause wrote:
    >> Are there any free implementations of C11-compliant (though AFAIK this
    >> is the same as older standard here) 48 bit double?
    >>

    >
    > if relevant, I use a shaved-down 64-bit double as a 48-bit double
    > (mostly related to stuffing floating-point values into pointers on
    > 64-bit targets


    Ouch, that's a lot of precision bits to give up just for this kind of stuffing
    trick. I would not be willing to sacrifice more than, say, 3. That's enough
    for a type tag with 8 values.

    > and, for the pointer case (assumes a target with 64-bit pointers):
    > byte *double48_ptrbase; //base address
    >
    > void *DoubleToPtrDouble48(double v)
    > {
    > return(double48_ptrbase+((*(uint64_t *)(&v))>>16));
    > }


    Instead of shifting and using an offset, you could put a couple of tag bits
    into the low order bits of the pointer which indicate "this is a double". Then
    mask them to zero to retrieve the float.
     
    Kaz Kylheku, Mar 29, 2012
    #5
  6. Philipp Klaus Krause

    BGB Guest

    On 3/28/2012 4:12 PM, Kaz Kylheku wrote:
    > On 2012-03-28, BGB<> wrote:
    >> On 3/28/2012 1:05 PM, Philipp Klaus Krause wrote:
    >>> Are there any free implementations of C11-compliant (though AFAIK this
    >>> is the same as older standard here) 48 bit double?
    >>>

    >>
    >> if relevant, I use a shaved-down 64-bit double as a 48-bit double
    >> (mostly related to stuffing floating-point values into pointers on
    >> 64-bit targets

    >
    > Ouch, that's a lot of precision bits to give up just for this kind of stuffing
    > trick. I would not be willing to sacrifice more than, say, 3. That's enough
    > for a type tag with 8 values.
    >


    I had considered before giving it a dedicated 56-bit range, but never
    really got around it, and found it good enough.

    it is still considerably more accurate than the 28-bit flonum used on
    32-bit targets.


    >> and, for the pointer case (assumes a target with 64-bit pointers):
    >> byte *double48_ptrbase; //base address
    >>
    >> void *DoubleToPtrDouble48(double v)
    >> {
    >> return(double48_ptrbase+((*(uint64_t *)(&v))>>16));
    >> }

    >
    > Instead of shifting and using an offset, you could put a couple of tag bits
    > into the low order bits of the pointer which indicate "this is a double". Then
    > mask them to zero to retrieve the float.


    this is possible, except that low-order tag bits are really annoying as
    they require constraining that every pointer be aligned, say, on 8 bytes
    (and a random byte-aligned character pointer can make a mess of things).


    in my case, I had used a different strategy:
    unusable parts of the address space are used for tagged values.

    on x86, this basically means the range from 0xC0000000 to 0xFFFFFFFF,
    since this is space is (generally) reserved for the OS on both Windows
    and Linux.

    both "fixnum" and "flonum" are 28 bits in this case, with the rest of
    the space being used for other smaller type ranges.


    on x86-64, a 56-bit glob of address space was used for tagged values
    (IIRC, starting at something like 0x7F000000_00000000), which was
    in-turn divided into around 256 48-bit regions.

    on current HW though, a person could probably get by with a larger 60 or
    62-bit region though.

    say, a 60 bit region starting at 0x70000000_00000000, probably using the
    next 4 bits as a tag, giving 16 regions each being 56 bits.

    or, more extreme:
    0x40000000_00000000 to 0xBFFFFFFF_FFFFFFFF is used as a single giant
    63-bit region, with 3 more bits as tags, allowing for up to 8 60-bit
    regions.


    but, even with 16 bits shaved off, a double is still plenty accurate for
    most things IME.


    note that this stuff is not used for addressable memory objects though,
    which use a different strategy for identifying types:
    namely, identifying type either by memory region (ex: cons cells or
    interned strings) or by tags within the memory-object headers (most
    other allocated memory). granted, technically, these are themselves
    based on address regions (for example, the MM/GC will check against
    relevant "heap chunks" or similar, when relevant).

    note that the MM/GC does not require pointers to point at the start of
    memory objects (it can find the start of the memory object by itself),
    as well as determine when address is outside of areas it knows about.

    pretty much all types are (canonically) identified by "type names" (as
    strings), rather than by tag bits or similar (although tag values are
    used internally).


    or such...
     
    BGB, Mar 29, 2012
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sydex
    Replies:
    12
    Views:
    6,505
    Victor Bazarov
    Feb 17, 2005
  2. Replies:
    3
    Views:
    1,765
    Timothy Bendfelt
    Jan 19, 2007
  3. Replies:
    9
    Views:
    981
    Juha Nieminen
    Aug 22, 2007
  4. Jeff.M
    Replies:
    6
    Views:
    179
    Lasse Reichstein Nielsen
    May 4, 2009
  5. James Harris
    Replies:
    37
    Views:
    556
    Tim Rentsch
    Aug 8, 2013
Loading...

Share This Page