Prev: Identify the Color of an Image
Next: list.insert
From: kj on 14 Jul 2010 09:24 I have a C library function hg that returns a long double, so when I import it using C types I specify this return type like this: MYLIB.hg.restype = ctypes.c_longdouble But certain non-zero values returned by hg appear as zero Python-side. If I modify hg so that it prints out its value right before returning it, I get stuff like the following: >>> 0 == MYLIB.hg(100, 200, 100, 6000) from hg: 2.96517e-161 False >>> 0 == MYLIB.hg(200, 200, 200, 6000) from hg: 5.28791e-380 True So, although the value returned by hg in the second invocation above is 5.28791e-380, Python sees it as 0. What am I doing wrong? TIA! ~K
From: Thomas Jollans on 14 Jul 2010 12:28 On 07/14/2010 03:24 PM, kj wrote: > > > > I have a C library function hg that returns a long double, so when > I import it using C types I specify this return type like this: > > MYLIB.hg.restype = ctypes.c_longdouble > > But certain non-zero values returned by hg appear as zero Python-side. > If I modify hg so that it prints out its value right before returning > it, I get stuff like the following: > >>>> 0 == MYLIB.hg(100, 200, 100, 6000) > from hg: 2.96517e-161 > False >>>> 0 == MYLIB.hg(200, 200, 200, 6000) > from hg: 5.28791e-380 > True > > So, although the value returned by hg in the second invocation > above is 5.28791e-380, Python sees it as 0. > > What am I doing wrong? Nothing. http://docs.python.org/library/ctypes.html#fundamental-data-types c_longdouble maps to float http://docs.python.org/library/stdtypes.html#numeric-types-int-float-long-complex "floating point numbers are implemented using double in C" ergo, the extra precision a long double gives you versus a normal double is lost if you use Python (or, at least, ctypes) If you really want to keep the precision, you need a new/different type. ctypes won't help you. Cython and NumPy may or may not be useful here. - Thomas
From: kj on 15 Jul 2010 12:41 In <mailman.733.1279124991.1673.python-list(a)python.org> Thomas Jollans <thomas(a)jollans.com> writes: >http://docs.python.org/library/ctypes.html#fundamental-data-types >c_longdouble maps to float Thanks for pointing this out! ~K (Does it make *any difference at all* to use c_longdouble instead of c_double? If not, I wonder what's the point of having c_longdouble at all.)
From: Thomas Jollans on 15 Jul 2010 13:04 On 07/15/2010 06:41 PM, kj wrote: > In <mailman.733.1279124991.1673.python-list(a)python.org> Thomas Jollans <thomas(a)jollans.com> writes: > >> http://docs.python.org/library/ctypes.html#fundamental-data-types > >> c_longdouble maps to float > > Thanks for pointing this out! > ~K > (Does it make *any difference at all* to use c_longdouble instead > of c_double? If not, I wonder what's the point of having c_longdouble > at all.) they're still different types (in C). on my machine, a double is 64 bits wide, while a long double is 128 bits wide. This means that a function that expects a long double argument will expect 16 bytes, but ctypes will only pass 8 bytes if you tell it to pass double. The same applies to return values.
From: kj on 16 Jul 2010 09:53
In <mailman.778.1279213534.1673.python-list(a)python.org> Thomas Jollans <thomas(a)jollans.com> writes: >On 07/15/2010 06:41 PM, kj wrote: >> In <mailman.733.1279124991.1673.python-list(a)python.org> Thomas Jollans <thomas(a)jollans.com> writes: >> >>> http://docs.python.org/library/ctypes.html#fundamental-data-types >> >>> c_longdouble maps to float >> >> Thanks for pointing this out! >> ~K >> (Does it make *any difference at all* to use c_longdouble instead >> of c_double? If not, I wonder what's the point of having c_longdouble >> at all.) >they're still different types (in C). i understand that doubles and long doubles are different in C. >on my machine, a double is 64 bits wide, while a long double is 129 bits >wide. This means that a function that expects a long double argument >will expect 16 bytes, but ctypes will only pass 8 bytes if you tell it >to pass double. The same applies to return values. This is extremely confusing. From my naive reading of the documentation, I would have expected that the following two blocks would produce identical results (expl is one of the standard C math library exponential functions, with signature "long double expl(long double)"): MATH.expl.argtypes = [c_longdouble] MATH.expl.restype = c_longdouble print MATH.expl(0) MATH.expl.argtypes = [c_double] MATH.expl.restype = c_double print MATH.expl(0) ....but no, they don't: the first one prints out the correct result, 1.0, while the second one prints out 0.0, of all things. (In fact, with the second (mis)configuration, the value returned by MATH.expl is always equal to its argument, go figure.) I find these results perplexing because, based on the docs, I expected that they *both* would be analogous to doing the following in C: printf("%f\n", (double) expl((double) 0.0)); /* prints out 1.000000 */ i.e., in *both* cases, expl would get passed a double (which gets automatically cast into a long double), and in both cases its returned value would be cast into a double. Clearly, this is not what's happening, but I can't figure out the correct interpreation of what's going on based on the documentation... |