Software implementation of 48-bit double

  • Thread starter Philipp Klaus Krause
  • Start date
P

Philipp Klaus Krause

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

Philipp
 
P

Philipp Klaus Krause

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
 
J

jacob navia

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
 
B

BGB

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...
 
K

Kaz Kylheku

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.
 
B

BGB

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.

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...
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,539
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top