4

I apologize in advance for my poor knowledge of C: I use Python to code and have written a few modules with Cython using the standard C functions to effect a great increase in speed. However, I need a range higher than 1e308 (yes, you read it right), which is what I currently get by using the type double complex and the functions cexp and cabs.

I tried to use the functions cexpl and cabsl, and declared my variables to be of type long double complex, but I still encounter overflows after 1e308. This probably means that my compiler converts long doubles to doubles, is that right? But according to Wikipedia,

With the GNU C Compiler, long double is 80-bit extended precision on x86 processors regardless of the physical storage used for the type (which can be either 96 or 128 bits)..[4]

I am using a 64-bit system with arch Linux (and Python 2.7.8 if it matters).

How do I write a Cython module that forces the use of long doubles? I need such big numbers for some scientific computation I am doing.

Edit: Compiling with the flag -m128bit-long-double gives the same result. As indicated here,

In the x86-64 compiler, -m128bit-long-double is the default choice as its ABI specifies that long double is to be aligned on 16 byte boundary.

So this seems to make no difference.

I also ran this following program to check the range on my system:

#include <stdio.h>
#include <float.h>

int main()
{
   printf("Storage size for float : %d \n", sizeof(float));
   printf("Minimum float positive value: %E\n", FLT_MIN );
   printf("Maximum float positive value: %E\n", FLT_MAX );
   printf("Precision value: %d\n", FLT_DIG );

   printf("Storage size for double : %d \n", sizeof(double));
   printf("Minimum double positive value: %E\n", DBL_MIN );
   printf("Maximum double positive value: %E\n", DBL_MAX );
   printf("Precision value: %d\n", DBL_DIG );

   printf("Storage size for long double : %d \n", sizeof(long double));
   printf("Minimum long double positive value: %Le\n", LDBL_MIN );
   printf("Maximum long double positive value: %Le\n", LDBL_MAX );
   printf("Precision value: %d\n", LDBL_DIG );

   return 0;
}

and got the following output:

Storage size for float : 4 
Minimum float positive value: 1.175494E-38
Maximum float positive value: 3.402823E+38
Precision value: 6
Storage size for double : 8 
Minimum double positive value: 2.225074E-308
Maximum double positive value: 1.797693E+308
Precision value: 15
Storage size for long double : 16 
Minimum long double positive value: 3.362103e-4932
Maximum long double positive value: 1.189731e+4932
Precision value: 18

So I guess the problem lies in my code, is that right? Are there any explicit identifiers I need to add other than declaring variables to ensure that my program actually uses long doubles?

Abhinav
  • 268
  • 1
  • 7
  • 19
  • 1
    I'm not putting this as an answer because I'm not sure if it's right... but if you can add compiler flags, try either `-m96bit-long-double` or `-m128bit-long-double` and see what happens. [This question might be useful as well.](http://stackoverflow.com/questions/13516476/long-double-gcc-specific-and-float128) Good luck. – Al.Sal Aug 19 '14 at 13:06
  • Thanks for the direction! I updated the question. How do I check whether my compiler (gcc) is really using 80 or 96 bit long doubles with a range of around `1e4392` apart from getting the overflow? – Abhinav Aug 19 '14 at 14:33
  • I found [this question](http://stackoverflow.com/questions/423404/long-double-returns-and-ctypes?lq=1) that shows that my C module was returning long doubles, but was being interpreted by Python as `inf` because it exceeded the size of a `double`. As it stands, my question is not really the right question to ask because it stood on a faulty premise. How can I vote to close it? Or should I let this question remain for someone else who might think the same? – Abhinav Aug 19 '14 at 18:11
  • 1
    Good on ya for putting in the work and figuring out the problem. If I were you, I would write up my solution, post it as an answer, and accept it for future reference. This practice is [actively supported](http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/) on SO. – Al.Sal Aug 19 '14 at 18:13

1 Answers1

3

As was seen in the edit to the question, my system and compiler was behaving as expected by printing the correct range for long double, the relevant variable here being LDBL_MAX = 1.189731e+4932

Also, the module written with Cython was correctly giving an output of type long double. However, since this type is not natively supported in Python (see this question), the value that was returned was greater than the maximum size of double ,1.797693E+308 on my system and hence being equated to +inf + 0j. So this was not related to gcc at all, but to Python interpreting long doubles in an incorrect way.

I can hopefully get around this by working with another C module that can accept long double input types and process it further, the expected results from this sub-part is not expected to be outside the range of a double (or for that matter, even a float).

Another option might be to use libraries with Python that can support high precision and high range numbers, possibly GMPY.

Community
  • 1
  • 1
Abhinav
  • 268
  • 1
  • 7
  • 19