[semi OT] - Lack of long double implementation in VS

B

Bubba

Greetings to all!

I will begin with a humble apology for posting such "impure" article, but
I was wandering - shouldn't data types be defined by architecture, and not
by compiler? I trust the answer is yes, but having such "by design" flaw
by Microsoft just escapes me.

To my surprise, I found out today (on harder way) that even in VS 2010

{
long double x;
size_t s = sizeof(x):
}

gives '8', while gcc returns '16' (as expected).

Did some homework and read articles but could not find a sane reason for
such implementation (due to more than 20 years of 80 bit FPU in x86
CPU's).

Is anyone acquainted more detailed about this issue?

Furthermore, I was shocked to find out that Windows calculator couldn't
calculate properly subtraction sqrt(x) and real square root of that number
(sqrt(4) - 2, sqrt(16) - 4...).

Yes, I am aware of IEEE 754, but I couldn't implement that one even in
GMP:

bubba@korea:~$ cat b.c
#include <gmp.h>

int main (int argc, char *argv[]) {
mpf_t sq_me, sq_out, test, sub;
mpf_set_default_prec (1024);
mpf_init(sq_me);
mpf_init(sq_out);
mpf_init(test);
mpf_init(sub);
mpf_set_str (sq_me, argv[1], 10);
mpf_set_str (sub, "2", 10);

mpf_sqrt(sq_out, sq_me);
mpf_sub(test,sq_out,sub);

gmp_printf ("Input: %Ff\n\n", sq_me);
gmp_printf ("Square root: %.1000Ff\n\n", sq_out);
gmp_printf ("Subtraction: %.1000Ff\n\n", test);

return 0;
}

bubba@korea:~$ gcc -g -Wall -pedantic -ansi -O3 b.c -lgmp
bubba@korea:~$ ./a.out 4
Input: 4.000000

Square root:
2.000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000

Subtraction:
0.000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000

I tried to produce similar error in gcc but failed. Does anyone know who
is it implemented to make such errors? I guess it is C, but can't figure
out how come they haven't fixed it since Windows XP...
 
K

Keith Thompson

Bubba said:
I will begin with a humble apology for posting such "impure" article, but
I was wandering - shouldn't data types be defined by architecture, and not
by compiler? I trust the answer is yes, but having such "by design" flaw
by Microsoft just escapes me.

Data types are defined by the compiler. The characteristics of the
underlying architecture are certainly an important factor for the
compiler authors to consider, but not the only one.
To my surprise, I found out today (on harder way) that even in VS 2010

{
long double x;
size_t s = sizeof(x):
}

gives '8', while gcc returns '16' (as expected).

Why did you expect 16?

The standard requires float to support at least 6 decimal digits, double
to support at least 10, and long double to support at least 10. In
fact, *all* the minimal requirements for long double are the same as
those for double. The set of values of type double must be a subset of
the set of values of type long double, but they're allowed to be
identical. (Even so, they're distinct types.)
Did some homework and read articles but could not find a sane reason for
such implementation (due to more than 20 years of 80 bit FPU in x86
CPU's).

Is anyone acquainted more detailed about this issue?

Microsoft's decision to make long double the same size as double is
permitted by the C standard.

Whether they *should* have made it bigger is another question, and why
they didn't is yet another. I don't have an answer to that last one.
Furthermore, I was shocked to find out that Windows calculator couldn't
calculate properly subtraction sqrt(x) and real square root of that number
(sqrt(4) - 2, sqrt(16) - 4...).

I have no idea how the Windows calculator is implemented; questions
about it are likely not about C.

[...]
 
E

Eric Sosman

Greetings to all!

I will begin with a humble apology for posting such "impure" article, but
I was wandering - shouldn't data types be defined by architecture, and not
by compiler? I trust the answer is yes, but having such "by design" flaw
by Microsoft just escapes me.

C's data types are defined by the language Standard, but the
definitions are purposely loose to permit adaptability to a range
of hardware. The C implementation is expected to choose "something
suitable" for each data type, as long as it meets the requirements
of the Standard.

On a particular system, some of the mappings between C types and
native types will be fairly obvious. Others, though, will be less
than obvious, and different C implementations may choose differently.
For example, consider 64-bit machines, which (commonly) provide four
native integer widths of 8, 16, 32, and 64 bits. There's an obvious
way to map these to the four integer widths offered by C90: Just call
them char, short, int, and long, in that order. Digital Equipment
Corporation did exactly that -- see how successful they've been? ;)

(It would be something of a stretch to blame DEC's demise on their
C implementation, but my point is that the "obvious" mapping between
language types and native types is not necessarily the "right" one.)
To my surprise, I found out today (on harder way) that even in VS 2010

{
long double x;
size_t s = sizeof(x):
}

gives '8', while gcc returns '16' (as expected).

Did some homework and read articles but could not find a sane reason for
such implementation (due to more than 20 years of 80 bit FPU in x86
CPU's).

Is anyone acquainted more detailed about this issue?

It appears Microsoft chose to map both long double and double to
the same underlying native type, just as they map both long and int
to a single underlying type. Why? Dunno; you'll have to ask Redmond.
Pure speculation: Maybe there were interoperability issues with other
languages, or maybe deadline pressure was too fierce to allow time
for writing a third suite of math library functions. Ask Redmond.
Furthermore, I was shocked to find out that Windows calculator couldn't
calculate properly subtraction sqrt(x) and real square root of that number
(sqrt(4) - 2, sqrt(16) - 4...).

Is the calculator implemented in C, and does it use C's arithmetic
types? It's own Help suggests not: It claims 32-digit precision (which
would be more than 106 bits), and mentions that rational numbers are
stored as fractions rather than as floating-point. For me, sqrt(4)-2
gives about -8.2e-39, suggesting that even when floating-point is used
(assuming sqrt delivers an F-P result), the precision is nearly 128
bits. It seems unlikely that the calculator uses an unaided native
format.
 
K

Kaz Kylheku

Greetings to all!

I will begin with a humble apology for posting such "impure" article, but
I was wandering - shouldn't data types be defined by architecture, and not
by compiler? I trust the answer is yes, but having such "by design" flaw
by Microsoft just escapes me.

Note that the Microsoft toolchain is free (as in beer).

They have no incentive for improving it because they pretty much wiped out the
non-free, non-open-source competitors, and probably don't care about earning a
bigger slice of zero.
gives '8', while gcc returns '16' (as expected).

If you think that GCC has better numeric support, then use it.

You can use gcc for compiling Windows programs, such that they
do not depend on any special run-time libraries or any Unix-like
environment: www.mingw.org.
 
K

Keith Thompson

Kaz Kylheku said:
If you think that GCC has better numeric support, then use it.

You can use gcc for compiling Windows programs, such that they
do not depend on any special run-time libraries or any Unix-like
environment: www.mingw.org.

Yes, but MinGW's compiler (gcc) has 12-byte long double, but uses
Microsoft's runtime library, which assumes 8-byte long double.
 
N

Nick Keighley

[...] shouldn't data types be defined by architecture, and not
by compiler?
no.


I trust the answer is yes,

but why? It would seem sane to have architecture have an influence on
data type definitions but i don't see why it would dictate it. Who
gets to decide what the "correct" data type implementation is for each
architecture? Intel?

Furthermore, I was shocked to find out that Windows calculator couldn't
calculate properly subtraction sqrt(x) and real square root of that number
(sqrt(4) - 2, sqrt(16) - 4...).

sqrt(16) - 4 is about -5e-38.
Seems pretty good to me!


<snip>
 
J

jacob navia

Le 24/10/11 19:15, christian.bau a écrit :
I have no idea where this decision that 80 bit long double = 10 byte
came from. The hardware implementation on a modern Intel processor
reads 10 bytes and writes 10 bytes (so a 16 byte long double is
actually 80 value bits and 48 bits of rubbish) and doesn't care about
alignment. So having 16 bytes just adds 60 percent more size to any
long double data for no gain.

Under intel 64 the stack has to be aligned to a 8 byte boundary. Pushing
or storing any long double variable would need anyway 16 bytes. Besides,
the processor reads more efficiently if the data is aligned to a 16 byte
boundary.

Many considerations like this make alignment to 16 bytes impossible to
avoid. This makes actually waste a lot of memory like the 64 bit
pointers where in many cases only 16 would be actually needed or at most
32.

jacob
 
P

Phil Carmody

Kaz Kylheku said:
Note that the Microsoft toolchain is free (as in beer).

They have no incentive for improving it because they pretty much wiped out the
non-free, non-open-source competitors, and probably don't care about earning a
bigger slice of zero.


If you think that GCC has better numeric support, then use it.

You can use gcc for compiling Windows programs, such that they
do not depend on any special run-time libraries or any Unix-like
environment: www.mingw.org.

It's nearly a decade since I touched a windows machine, but I seem
to remember that the "portable" code I was writing, and compiling
using mingw, suffered from an inability to understand some of the
printf type specifiers (almost certainly in the long long direction).
when run on windows. Ugly macro mess ensued.

Phil
 
K

Keith Thompson

Phil Carmody said:
It's nearly a decade since I touched a windows machine, but I seem
to remember that the "portable" code I was writing, and compiling
using mingw, suffered from an inability to understand some of the
printf type specifiers (almost certainly in the long long direction).
when run on windows. Ugly macro mess ensued.

That's because MinGW uses gcc as its compiler and the Microsoft
runtime library as its library. That works for most things,
but they differ on the representation of long double. (A quick
experiment indicates that long long isn't a problem.)

This isn't a bug in gcc or in Microsoft's runtime; it's a bug in
MinGW's integration of them.

(I'd think it would be possible to configure gcc to use 64 bits for long
double, which would result in a consistent implementation. Perhaps the
MinGW folks thought the advantage of greater precision was more
important than the drawback of not being able to print long double
values.)
 
A

André Gillibert

christian.bau said:
On the stack it is no problem. And in a struct, padding can be added
when needed. The problem is large arrays of long double, where lets
say a 3 Megabyte cache only holds 196,000 long doubles when it could
hold 314,000. If you have an array of a million long doubles, the
processor will read it a lot faster if each long double is 10 byte,
with 10 byte alignment, than 16 byte.

A size optimization may be a performance optimization on some
datasets, but, it may also be a pessimization on other datasets
(maybe for an array of 10 long double values).

No choice is better in all cases, but, the implementation
developer has to make a choice.
 
J

jacob navia

Le 27/10/11 16:28, André Gillibert a écrit :
A size optimization may be a performance optimization on some
datasets, but, it may also be a pessimization on other datasets
(maybe for an array of 10 long double values).

No choice is better in all cases, but, the implementation
developer has to make a choice.

Or,

long double table[SIZE] __attribute__(packed);

If we had a way of incorporating a directive into the
language that would allow the compiler topack those.
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top