On 17.06.2011, at 8:05PM, Mark Wiebe wrote:
On Thu, Jun 16, 2011 at 8:18 PM, Derek Homeier
wrote: On 17.06.2011, at 2:02AM, Mark Wiebe wrote:
ok, that was a lengthy hunt, but it's in printing the string in make_iso_8601_date:
tmplen = snprintf(substr, sublen, "%04" NPY_INT64_FMT, dts->year); fprintf(stderr, "printed %d[%d]: dts->year=%lld: %s\n", tmplen, sublen, dts->year, substr);
produces
> np.datetime64('1970-03-23 20:00:00Z', 'D') printed 4[62]: dts->year=1970: 0000 numpy.datetime64('0000-03-23','D')
It seems snprintf is not using the correct format for INT64 (as I happened to do in fprintf before realising I had to use "%lld" ;-) - could it be this is a general issue, which just does not show up on little-endian machines because they happen to pass the right half of the int64 to printf? BTW, how is this supposed to be handled (in 4 digits) if the year is indeed beyond the 32bit range (i.e. >~ 0.3 Hubble times...)? Just wondering if one could simply cast it to int32 before print.
I'd prefer to fix the NPY_INT64_FMT macro. There's no point in having it if it doesn't work... What is NumPy setting it to for that platform?
Of course (just felt somewhat lost among all the #defines). It clearly seems to be mis-constructed on PowerPC 32: NPY_SIZEOF_LONG is 4, thus NPY_INT64_FMT is set to NPY_LONGLONG_FMT - "Ld", but this does not seem to handle int64 on big-endian Macs - explicitly printing "%Ld", dts->year also produces 0. Changing the snprintf format to "%04" "lld" produces the correct output, so if nothing else avails, I suggest to put something like
# elseif (defined(__ppc__) || defined(__ppc64__)) #define LONGLONG_FMT "lld" #define ULONGLONG_FMT "llu" # else
into npy_common.h (or possibly simply "defined(__APPLE__)", since %lld seems to work on 32bit i386 Macs just as well).
Probably a minimally invasive change is best, also this kind of thing deserves a comment explaining the problem that was encountered with the specific platforms, so that in the future when people examine this part they can understand why this is there. Do you want to make a pull request for this change?
I'd go with the defined(__APPLE__) then, since %Ld produces wrong results on both 32bit platforms. More precisely, this print "%Ld - %Ld", dts->year, dts->year produces "0 - 1970" on ppc and "1970 - 0" on i386, while "%lld - %lld" prints "1970 - 1970" on both archs. There still is an issue (I now remember this came up with a different test a few months ago), that none of the formats seems to be able to actually print numbers > 2**32 (or 2**31, don't remember), but this seemed out of reach for anyone on this list. Cheers, Derek