Wintel compilers with: C99 tgmath.h? 16-byte "long double"?

B

bq

Hello,
Two questions related to floating point support:

What C compilers for the wintel (MS Windows + x86) platform are C99
compliant as far as <math.h> and <tgmath.h> are concerned?

What wintel compilers support a 16-byte "long double" (with 33 decimal
digits of accuracy) including proper printf() support. I found some
compilers that did support "long double", but theirs was an 8-byte or
10-byte or 12-byte type with accuracy the same or nearly the same as
the plain 8-byte "double".

Thanks
fq

Note: My numbers were obtained by "sizeof" and "float.h" macros
DBL_DIGITS and LDBL_DIGITS.

Here is output from OpenWatcom 1.2:
FLT_EPSILON = 1.19209e-007
DBL_EPSILON = 2.22045e-016
LDBL_EPSILON = 2.22045e-016
FLT_DIG = 6
DBL_DIG = 15
LDBL_DIG = 15
FLT_MANT_DIG = 24
DBL_MANT_DIG = 53
LDBL_MANT_DIG = 53

and from Borland 5.5.1:
FLT_EPSILON = 1.19209e-07
DBL_EPSILON = 2.22045e-16
LDBL_EPSILON = 1.0842e-19
FLT_DIG = 6
DBL_DIG = 15
LDBL_DIG = 18
FLT_MANT_DIG = 24
DBL_MANT_DIG = 53
LDBL_MANT_DIG = 64

and, for comparison, from the SUN compiler (on Solaris):
FLT_EPSILON = 1.19209e-07
DBL_EPSILON = 2.22045e-16
LDBL_EPSILON = 1.92593e-34
FLT_DIG = 6
DBL_DIG = 15
LDBL_DIG = 33
FLT_MANT_DIG = 24
DBL_MANT_DIG = 53
LDBL_MANT_DIG = 113
 
J

jacob navia

bq said:
Hello,
Two questions related to floating point support:

What C compilers for the wintel (MS Windows + x86) platform are C99
compliant as far as <math.h> and <tgmath.h> are concerned?
lcc-win32. The headers may be not in 100% standard compliance, but the basic
hardware support is there.
What wintel compilers support a 16-byte "long double" (with 33 decimal
digits of accuracy) including proper printf() support.

lcc-win32 supports 10 byte long double. If that is too little for
you, you can use 350 bits floating point.

I found some
compilers that did support "long double", but theirs was an 8-byte or
10-byte or 12-byte type with accuracy the same or nearly the same as
the plain 8-byte "double".

No, the accuracy is better, of course, and also the range. As you
know, 64 bit is not the same as 80 bit.

Please be consequent. The "wintel" compilers must generate
code for the intel architecture. That architecture doesn't support
natively 16 bytes doubles as the sparc does.

If the purpose of your post was just to make publicity
for this fact, granted, but please do not blame the
compilers. They can't give you in hardware what the
hardware doesn't support.

lcc-win32 supports software
floating point with very high precision. I thought that
instead of 16 byte doubles, 350 bits would make
a real difference. The performance is good for a software
implementation, but do not expect hardware speeds.

gcc supports 10 byte doubles too, and gmp (their
multiprecision package) is a high speed implementation.
 
P

P.J. Plauger

Two questions related to floating point support:

What C compilers for the wintel (MS Windows + x86) platform are C99
compliant as far as <math.h> and <tgmath.h> are concerned?

This is a library issue. If you add our library to any of several
compilers (VC++, Comeau, mingw) you can get a wintel compiler that
supports these headers properly.
What wintel compilers support a 16-byte "long double" (with 33 decimal
digits of accuracy) including proper printf() support. I found some
compilers that did support "long double", but theirs was an 8-byte or
10-byte or 12-byte type with accuracy the same or nearly the same as
the plain 8-byte "double".

VC++ supports only 8-byte long double (same as double). Comeau has
the same limitation, at least when sitting atop VC++. mingw supports
the native Intel 10-byte long double, though their library has poor
long double precision. Our library supports the maximum of whatever
the compiler will handle. No wintel compiler supports 16-byte long
double, to my knowledge, because the hardware doesn't support it.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
B

bq

jacob navia said:
lcc-win32. The headers may be not in 100% standard compliance, but the basic
hardware support is there.


lcc-win32 supports 10 byte long double. If that is too little for
you, you can use 350 bits floating point.

I am not familair with that 350 bit mode.
Is that through library functions or some other special tools?
If the purpose of your post was just to make publicity
for this fact, granted, but please do not blame the
compilers.

No blame was meant. In fact the compiler+library that had 16-byte
support
(I won't repeat its name!) had a few thins I didn't like. Example: the
sqrt() function operated as if <tgmath.h> was included even when it
wasn't.
However, hypot() operated in "double" regardless of its argument type,
and there is no hypotl() to use. It took me a while to figure out why
one routine (an SVD calculation) was losing precision. Once hypot()
was replaced with my own routine, full precision was recovered.

Thanks.
bq
 
B

bq

jacob navia said:
lcc-win32. The headers may be not in 100% standard compliance, but the basic
hardware support is there.


lcc-win32 supports 10 byte long double. If that is too little for
you, you can use 350 bits floating point.

I am not familair with that 350 bit mode.
Is that through library functions or some other special tools?
If the purpose of your post was just to make publicity
for this fact, granted, but please do not blame the
compilers.

No blame was meant. In fact the compiler+library that had 16-byte
support
(I won't repeat its name!) had a few thins I didn't like. Example: the
sqrt() function operated as if <tgmath.h> was included even when it
wasn't.
However, hypot() operated in "double" regardless of its argument type,
and there is no hypotl() to use. It took me a while to figure out why
one routine (an SVD calculation) was losing precision. Once hypot()
was replaced with my own routine, full precision was recovered.

Thanks.
bq
 
J

jacob navia

bq said:
"jacob navia" <[email protected]> wrote in message

I am not familair with that 350 bit mode.
Is that through library functions or some other special tools?


No blame was meant. In fact the compiler+library that had 16-byte
support
(I won't repeat its name!) had a few thins I didn't like. Example: the
sqrt() function operated as if <tgmath.h> was included even when it
wasn't.
However, hypot() operated in "double" regardless of its argument type,
and there is no hypotl() to use. It took me a while to figure out why
one routine (an SVD calculation) was losing precision. Once hypot()
was replaced with my own routine, full precision was recovered.

Thanks.
bq
 
J

jacob navia

Here is an example of 350 bit mode:

#include <qfloat.h>
#include <stdio.h>
int main(void)
{
qfloat q = -1.570796Q;
qfloat result = tanq(q); // tanq is tangent for qfloat

printf("tan is: %70.40qf\n",result);
}

Produces:

tan
-3060023.3061935646797771659336362687358523

If you want to be sure which result is right (-3060023.3061 or -3060024.455
?)
this comes handy

lcc-win32:

http://www.cs.virginia.edu/~lcc-win32
 
C

CBFalconer

bq said:
.... snip ...

However, hypot() operated in "double" regardless of its argument
type, and there is no hypotl() to use. It took me a while to

As it should. If you called it with errooneous arguments it seems
clear to me where the blame should fall.
 
D

Dan Pop

In said:
Here is an example of 350 bit mode:

#include <qfloat.h>
#include <stdio.h>
int main(void)
{
qfloat q = -1.570796Q;
qfloat result = tanq(q); // tanq is tangent for qfloat

printf("tan is: %70.40qf\n",result);
}

Produces:

tan
-3060023.3061935646797771659336362687358523

Wrong! On my system, it produces:

fangorn:~/tmp 225> gcc -ansi -pedantic test.c
test.c:1:20: qfloat.h: No such file or directory
test.c: In function `main':
test.c:5: error: `qfloat' undeclared (first use in this function)
test.c:5: error: (Each undeclared identifier is reported only once
test.c:5: error: for each function it appears in.)
test.c:5: error: parse error before "q"
test.c:5:21: invalid suffix "Q" on floating constant

Please don't post example code that doesn't even compile with a standard
C compiler to this newsgroup. Keep your stuff for comp.compilers.lcc!

You've been told countless times that we're not interested in your
extensions. Is it that difficult to you to understand this or are you
an asshole who couldn't care less?

Dan
 
J

jacob navia

Dan Pop said:
Please don't post example code that doesn't even compile with a standard
C compiler to this newsgroup. Keep your stuff for comp.compilers.lcc!

You've been told countless times that we're not interested in your
extensions. Is it that difficult to you to understand this or are you
an asshole who couldn't care less?

I couldn't care less about your opinion Mr Pop. Yes. That is clear.

Concerning your language, you just show who you are, that's all.

Insults are the ressort of desperate people that have no longer
any arguments.

I am answering a question about the 350 bit mode of lcc-win32.

This mode is clearly marked as an extension. It allows greater
numerical precision. If your compiler doesn't support it, do not
use this mode.

I can post in the usenet as you can. You have no authority to
tell me what should I write or what should I think.
 
B

bq

CBFalconer said:
As it should. If you called it with errooneous arguments it seems
clear to me where the blame should fall.

Here is the code I used. The error "ey" was on the order 1e-16 in all
three cases. A similar procedure applied to sqrt() gave errors of
order 1e-8, 1e-16 and 1e-33. Where are the "errooneous arguments"?

Thanks
bq

#include <stdio.h>
#include <math.h>

int main ()
{
long double x=1, y, ey;

printf("x: %40.35Lg \n", x );

printf("y=hypot((float) x, (float) x)\n" );
y=hypot((float) x,(float) x);
ey = y*y-2*x*x;
printf("y: %40.35Lg \n", y );
printf("ey: %40.35Lg \n", ey);
printf("\n") ;

printf("y=hypot((double) x, (double) x)\n" );
y=hypot((double) x,(double) x);
ey = y*y-2*x*x;
printf("y: %40.35Lg \n", y );
printf("ey: %40.35Lg \n", ey);
printf("\n") ;

printf("y=hypot((long double) x, (long double) x)\n" );
y=hypot((long double) x,(long double) x);
ey = y*y-2*x*x;
printf("y: %40.35Lg \n", y );
printf("ey: %40.35Lg \n", ey);
printf("\n") ;


return 0;
}
 
B

bq

jacob navia said:
Here is an example of 350 bit mode:

#include <qfloat.h>
#include <stdio.h>

I am currently developing a numeric library, and the problem is this.
The basic library-wide floating type is, say, T.
There are two requirements. 1) I'd like to be able to recompile the
library, and for it to work and yield the expected precision whether T
is float, double or long double. Several functions in the library need
to call sqrt(), hypot() and fabs(). If long double is N decimal digits
of accuracy, the library should attain that precision. I don't care
whether N is 15 or 18 or 33 or something else, although the point of
allowing long double is to achieve N>15 when desired or called for,
and where it is available.

2) I'd like the library to work with most of the widely available
compilers/libraries without any #ifdef's to adapt to specific
compilers or operating systems. [C99's "tgmath" would solve the
problem, but that is not widely available]

The library works fine with double [on all compilers tested so far].
It also works with float (if I rely on automatic conversion of float
to double) on several compilers that I tested so far. However, getting
long double to work seems to require many #ifdef's to adapt to all
sorts of compiler+library behavior.

For long double, I've considered writing a special my_sqrt() function
that calls the double version sqrt() then improves the result by one
or two Newton-Raphson iterations. That would work on all systems, but
it would be inefficient on systems with a sqrtl() or a polymorhic
sqrt().

Any suggestions or comments are welcome.

Thanks.
bq
 
J

jacob navia

bq said:
int main ()
{
long double x=1, y, ey;

Here is the bug. y and ey are long doubles!
printf("x: %40.35Lg \n", x );

printf("y=hypot((float) x, (float) x)\n" );
y=hypot((float) x,(float) x);
ey = y*y-2*x*x;
This is WRONG.
You are doing all calculations in long double precision
instead of float precision!!
Changing this to:
ey = (float)y*(float)y-2*(float)x*(float)x;

I obtain
ey: -6.845708355740498516e-08
and NOT what you obtain. This forces calculations
into single precision...

BUT, (and this is even better) you have discovered a BUG
in lcc-win32.

I do destroy precision (by making a cast) from double or long
double to float, but I do not destroy precision in the conversion
of long double to double.

(double) x with x long double
generates nothing. This will be fixed ASAP.

By the way, adding

qfloat qy,qey;
printf("y=hypot((qfloat) x, (qfloat) x)\n" );
qy=hypotq((qfloat) x,(qfloat) x);
qey = qy*qy-2*(qfloat)x*(qfloat)x;
printf("y: %40.35qg \n", qy );
printf("ey: %40.35qg \n", qey);
printf("\n") ;

I obtain:
y=hypot((qfloat) x, (qfloat) x)
y: 1.41421356237309504880168872420969808
ey: 0

jacob
 
J

jacob navia

bq said:
"jacob navia" <[email protected]> wrote in message
The library works fine with double [on all compilers tested so far].
It also works with float (if I rely on automatic conversion of float
to double) on several compilers that I tested so far. However, getting
long double to work seems to require many #ifdef's to adapt to all
sorts of compiler+library behavior.

What kind of problems are you getting?

Beware that under microsoft compilers long double is
equal to double
For long double, I've considered writing a special my_sqrt() function
that calls the double version sqrt() then improves the result by one
or two Newton-Raphson iterations. That would work on all systems, but
it would be inefficient on systems with a sqrtl() or a polymorhic
sqrt().

Difficult to say without a concrete example of compiler
misbehavior...
 
P

P.J. Plauger

I am currently developing a numeric library, and the problem is this.
The basic library-wide floating type is, say, T.
There are two requirements. 1) I'd like to be able to recompile the
library, and for it to work and yield the expected precision whether T
is float, double or long double. Several functions in the library need
to call sqrt(), hypot() and fabs(). If long double is N decimal digits
of accuracy, the library should attain that precision. I don't care
whether N is 15 or 18 or 33 or something else, although the point of
allowing long double is to achieve N>15 when desired or called for,
and where it is available.

2) I'd like the library to work with most of the widely available
compilers/libraries without any #ifdef's to adapt to specific
compilers or operating systems. [C99's "tgmath" would solve the
problem, but that is not widely available]

The library works fine with double [on all compilers tested so far].
It also works with float (if I rely on automatic conversion of float
to double) on several compilers that I tested so far. However, getting
long double to work seems to require many #ifdef's to adapt to all
sorts of compiler+library behavior.

For long double, I've considered writing a special my_sqrt() function
that calls the double version sqrt() then improves the result by one
or two Newton-Raphson iterations. That would work on all systems, but
it would be inefficient on systems with a sqrtl() or a polymorhic
sqrt().

Any suggestions or comments are welcome.

Well, we have a library that does all that, but it ain't free.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
C

CBFalconer

bq said:
Here is the code I used. The error "ey" was on the order 1e-16 in all
three cases. A similar procedure applied to sqrt() gave errors of
order 1e-8, 1e-16 and 1e-33. Where are the "errooneous arguments"?

#include <stdio.h>
#include <math.h>

int main ()
{
long double x=1, y, ey;

printf("x: %40.35Lg \n", x );

printf("y=hypot((float) x, (float) x)\n" );
y=hypot((float) x,(float) x);

hypot takes and returns doubles.
 
R

Richard Bos

P.J. Plauger said:
Not necessarily in C99, if you include <tgmath.h>. And not in
C++, if you support TR1.

C++ is completely immaterial, obviously. As for <tgmath.h>, you're
correct, but bq did in fact _not_ #include it.

Richard
 
R

Richard Bos

jacob navia said:
I couldn't care less about your opinion Mr Pop. Yes. That is clear.

Concerning your language, you just show who you are, that's all.

Insults are the ressort of desperate people that have no longer
any arguments.

This is true, but...
I am answering a question about the 350 bit mode of lcc-win32.

This mode is clearly marked as an extension. It allows greater
numerical precision. If your compiler doesn't support it, do not
use this mode.

....his actual point was correct, regardless of the way he phrased it.
Your extensions _are_ off-topic on comp.lang.c, and you cannot possibly
expect a useful discussion of lcc here. As far as this group is
concerned, your program invoked undefined behaviour from the very first
line.
I can post in the usenet as you can. You have no authority to
tell me what should I write or what should I think.

The second sentence is true, but it has no bearing on the first. While
Dan has no authority over you, newsgroup tradition _has_. Only an
anti-social person would insistently discuss off-topic matters on a
technical newsgroup.

Richard
 
P

P.J. Plauger

C++ is completely immaterial, obviously.

So is TR1. You forgot that part.
As for <tgmath.h>, you're
correct, but bq did in fact _not_ #include it.

And yet he got overload behavior for sqrt. So why didn't you
say "sqrt takes and returs doubles"? If you're going to quibble,
at least do so consistently.

The larger point is that the OP has discovered a mishmash of
behaviors in the general area of overloading math functions
in C libraries. He's looking for ways to get uniformity, and
I suggested some.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 

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,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top