[Numpy-svn] r8372 - in trunk/numpy/core: src/multiarray tests

numpy-svn@scip... numpy-svn@scip...
Tue Apr 27 18:48:16 CDT 2010


Author: stefan
Date: 2010-04-27 18:48:16 -0500 (Tue, 27 Apr 2010)
New Revision: 8372

Modified:
   trunk/numpy/core/src/multiarray/arraytypes.c.src
   trunk/numpy/core/src/multiarray/datetime.c
   trunk/numpy/core/tests/test_datetime.py
Log:
BUG: In datetime, avoid overflow by casting multipliers to npy_int64.

Modified: trunk/numpy/core/src/multiarray/arraytypes.c.src
===================================================================
--- trunk/numpy/core/src/multiarray/arraytypes.c.src	2010-04-27 20:54:08 UTC (rev 8371)
+++ trunk/numpy/core/src/multiarray/arraytypes.c.src	2010-04-27 23:48:16 UTC (rev 8372)
@@ -762,7 +762,7 @@
 }
 
 /*
- * Acknowledgment:  Example code contributed by Marty Fuhr sponsored by
+ * Acknowledgement:  Example code contributed by Marty Fuhr sponsored by
  * Google Summer of Code 2009 was used to integrate and adapt the mxDateTime
  * parser
  */

Modified: trunk/numpy/core/src/multiarray/datetime.c
===================================================================
--- trunk/numpy/core/src/multiarray/datetime.c	2010-04-27 20:54:08 UTC (rev 8371)
+++ trunk/numpy/core/src/multiarray/datetime.c	2010-04-27 23:48:16 UTC (rev 8372)
@@ -153,7 +153,9 @@
 
 /* Returns absolute seconds from an hour, minute, and second
  */
-#define secs_from_hms(hour, min, sec) ((hour)*3600 + (min)*60 + (sec))
+#define secs_from_hms(hour, min, sec, multiplier) (\
+  ((hour)*3600 + (min)*60 + (sec)) * (npy_int64)(multiplier)\
+)
 
 /*
  * Takes a number of days since Jan 1, 1970 (positive or negative)
@@ -314,55 +316,58 @@
         ret = days * 1440 + d->hour * 60 + d->min;
     }
     else if (fr == NPY_FR_s) {
-        ret = days * 86400 + secs_from_hms(d->hour, d->min, d->sec);
+        ret = days * (npy_int64)(86400) +
+            secs_from_hms(d->hour, d->min, d->sec, 1);
     }
     else if (fr == NPY_FR_ms) {
-        ret = days * 86400000 + secs_from_hms(d->hour, d->min, d->sec) * 1000
+        ret = days * (npy_int64)(86400000)
+            + secs_from_hms(d->hour, d->min, d->sec, 1000)
             + (d->us / 1000);
     }
     else if (fr == NPY_FR_us) {
         npy_int64 num = 86400 * 1000;
-        num *= 1000;
-        ret = days * num + secs_from_hms(d->hour, d->min, d->sec) * 1000000
+        num *= (npy_int64)(1000);
+        ret = days * num + secs_from_hms(d->hour, d->min, d->sec, 1000000)
             + d->us;
     }
     else if (fr == NPY_FR_ns) {
         npy_int64 num = 86400 * 1000;
-        num *= 1000 * 1000;
-        ret = days * num + secs_from_hms(d->hour, d->min, d->sec) * 1000000000
-            + d->us * 1000 + (d->ps / 1000);
+        num *= (npy_int64)(1000 * 1000);
+        ret = days * num + secs_from_hms(d->hour, d->min, d->sec, 1000000000)
+            + d->us * (npy_int64)(1000) + (d->ps / 1000);
     }
     else if (fr == NPY_FR_ps) {
         npy_int64 num2 = 1000 * 1000;
         npy_int64 num1;
 
-        num2 *= 1000 * 1000;
-        num1 = 86400 * num2;
-        ret = days * num1 + secs_from_hms(d->hour, d->min, d->sec) * num2
-            + d->us * 1000000 + d->ps;
+        num2 *= (npy_int64)(1000 * 1000);
+        num1 = (npy_int64)(86400) * num2;
+        ret = days * num1 + secs_from_hms(d->hour, d->min, d->sec, num2)
+            + d->us * (npy_int64)(1000000) + d->ps;
     }
     else if (fr == NPY_FR_fs) {
         /* only 2.6 hours */
         npy_int64 num2 = 1000000;
-        num2 *= 1000000;
-        num2 *= 1000;
+        num2 *= (npy_int64)(1000000);
+        num2 *= (npy_int64)(1000);
 
         /* get number of seconds as a postive or negative number */
         if (days >= 0) {
-            ret = secs_from_hms(d->hour, d->min, d->sec);
+            ret = secs_from_hms(d->hour, d->min, d->sec, 1);
         }
         else {
             ret = ((d->hour - 24)*3600 + d->min*60 + d->sec);
         }
-        ret = ret * num2 + d->us * 1000000000 + d->ps * 1000 + (d->as / 1000);
+        ret = ret * num2 + d->us * (npy_int64)(1000000000)
+            + d->ps * (npy_int64)(1000) + (d->as / 1000);
     }
     else if (fr == NPY_FR_as) {
         /* only 9.2 secs */
         npy_int64 num1, num2;
 
         num1 = 1000000;
-        num1 *= 1000000;
-        num2 = num1 * 1000000;
+        num1 *= (npy_int64)(1000000);
+        num2 = num1 * (npy_int64)(1000000);
 
         if (days >= 0) {
             ret = d->sec;
@@ -370,7 +375,8 @@
         else {
             ret = d->sec - 60;
         }
-        ret = ret * num2 + d->us * num1 + d->ps * 1000000 + d->as;
+        ret = ret * num2 + d->us * num1 + d->ps * (npy_int64)(1000000)
+            + d->as;
     }
     else {
         /* Shouldn't get here */
@@ -425,47 +431,51 @@
         ret = d->day + d->sec / 3600;
     }
     else if (fr == NPY_FR_m) {
-        ret = d->day * 1440 + d->sec / 60;
+        ret = d->day * (npy_int64)(1440) + d->sec / 60;
     }
     else if (fr == NPY_FR_s) {
-        ret = d->day * 86400 + d->sec;
+        ret = d->day * (npy_int64)(86400) + d->sec;
     }
     else if (fr == NPY_FR_ms) {
-        ret = d->day * 86400000 + d->sec * 1000 + d->us / 1000;
+        ret = d->day * (npy_int64)(86400000) + d->sec * 1000 + d->us / 1000;
     }
     else if (fr == NPY_FR_us) {
         npy_int64 num = 86400000;
-        num *= 1000;
-        ret = d->day * num + d->sec * 1000000 + d->us;
+        num *= (npy_int64)(1000);
+        ret = d->day * num + d->sec * (npy_int64)(1000000) + d->us;
     }
     else if (fr == NPY_FR_ns) {
         npy_int64 num = 86400000;
-        num *= 1000000;
-        ret = d->day * num + d->sec * 1000000000 + d->us * 1000 + (d->ps / 1000);
+        num *= (npy_int64)(1000000);
+        ret = d->day * num + d->sec * (npy_int64)(1000000000)
+            + d->us * (npy_int64)(1000) + (d->ps / 1000);
     }
     else if (fr == NPY_FR_ps) {
         npy_int64 num2, num1;
 
         num2 = 1000000;
-        num2 *= 1000000;
-        num1 = 86400 * num2;
+        num2 *= (npy_int64)(1000000);
+        num1 = (npy_int64)(86400) * num2;
 
-        ret = d->day * num1 + d->sec * num2 + d->us * 1000000 + d->ps;
+        ret = d->day * num1 + d->sec * num2 + d->us * (npy_int64)(1000000)
+            + d->ps;
     }
     else if (fr == NPY_FR_fs) {
         /* only 2.6 hours */
         npy_int64 num2 = 1000000000;
-        num2 *= 1000000;
-        ret = d->sec * num2 + d->us * 1000000000 + d->ps * 1000 + (d->as / 1000);
+        num2 *= (npy_int64)(1000000);
+        ret = d->sec * num2 + d->us * (npy_int64)(1000000000)
+            + d->ps * (npy_int64)(1000) + (d->as / 1000);
     }
     else if (fr == NPY_FR_as) {
         /* only 9.2 secs */
         npy_int64 num1, num2;
 
         num1 = 1000000;
-        num1 *= 1000000;
-        num2 = num1 * 1000000;
-        ret = d->sec * num2 + d->us * num1 + d->ps * 1000000 + d->as;
+        num1 *= (npy_int64)(1000000);
+        num2 = num1 * (npy_int64)(1000000);
+        ret = d->sec * num2 + d->us * num1 + d->ps * (npy_int64)(1000000)
+            + d->as;
     }
     else {
         /* Shouldn't get here */
@@ -652,7 +662,7 @@
         hms = seconds_to_hmsstruct(tmp / 1000000000);
         tmp = tmp % 1000000000;
         us = tmp / 1000;
-        ps = (tmp % 1000) * 1000;
+        ps = (tmp % 1000) * (npy_int64)(1000);
         year    = ymd.year;
         month   = ymd.month;
         day     = ymd.day;
@@ -663,8 +673,8 @@
     else if (fr == NPY_FR_ps) {
         npy_int64 num1, num2, num3;
         num3 = 1000000000;
-        num3 *= 1000;
-        num1 = 86400 * num3;
+        num3 *= (npy_int64)(1000);
+        num1 = (npy_int64)(86400) * num3;
         num2 = num1 - 1;
 
         if (val >= 0) {
@@ -672,7 +682,7 @@
             tmp = val % num1;
         }
         else {
-            ymd = days_to_ymdstruct((val - num2)/ num1);
+            ymd = days_to_ymdstruct((val - num2) / num1);
             tmp = num2 + (val + 1) % num1;
         }
         hms = seconds_to_hmsstruct(tmp / num3);
@@ -690,8 +700,8 @@
         /* entire range is only += 2.6 hours */
         npy_int64 num1, num2;
         num1 = 1000000000;
-        num1 *= 1000;
-        num2 = num1 * 1000;
+        num1 *= (npy_int64)(1000);
+        num2 = num1 * (npy_int64)(1000);
 
         if (val >= 0) {
             sec = val / num2;
@@ -724,14 +734,14 @@
         us = tmp / 1000000000;
         tmp = tmp % 1000000000;
         ps = tmp / 1000;
-        as = (tmp % 1000) * 1000;
+        as = (tmp % 1000) * (npy_int64)(1000);
     }
     else if (fr == NPY_FR_as) {
         /* entire range is only += 9.2 seconds */
         npy_int64 num1, num2, num3;
         num1 = 1000000;
-        num2 = num1 * 1000000;
-        num3 = num2 * 1000000;
+        num2 = num1 * (npy_int64)(1000000);
+        num3 = num2 * (npy_int64)(1000000);
         if (val >= 0) {
             hour = 0;
             min = 0;
@@ -820,7 +830,7 @@
         sec = (val % 1440)*60;
     }
     else if (fr == NPY_FR_s) {
-        day = val / 86400;
+        day = val / (86400);
         sec = val % 86400;
     }
     else if (fr == NPY_FR_ms) {
@@ -847,13 +857,13 @@
         sec = val / 1000000000;
         val = val % 1000000000;
         us  = val / 1000;
-        ps  = (val % 1000) * 1000;
+        ps  = (val % 1000) * (npy_int64)(1000);
     }
     else if (fr == NPY_FR_ps) {
         npy_int64 num1, num2;
         num2 = 1000000000;
-        num2 *= 1000;
-        num1 = 86400 * num2;
+        num2 *= (npy_int64)(1000);
+        num1 = (npy_int64)(86400) * num2;
 
         day = val / num1;
         ps = val % num1;
@@ -866,7 +876,7 @@
         /* entire range is only += 9.2 hours */
         npy_int64 num1, num2;
         num1 = 1000000000;
-        num2 = num1 * 1000000;
+        num2 = num1 * (npy_int64)(1000000);
 
         day = 0;
         sec = val / num2;
@@ -874,14 +884,14 @@
         us = val / num1;
         val = val % num1;
         ps = val / 1000;
-        as = (val % 1000) * 1000;
+        as = (val % 1000) * (npy_int64)(1000);
     }
     else if (fr == NPY_FR_as) {
         /* entire range is only += 2.6 seconds */
         npy_int64 num1, num2, num3;
         num1 = 1000000;
-        num2 = num1 * 1000000;
-        num3 = num2 * 1000000;
+        num2 = num1 * (npy_int64)(1000000);
+        num3 = num2 * (npy_int64)(1000000);
         day = 0;
         sec = val / num3;
         as = val % num3;

Modified: trunk/numpy/core/tests/test_datetime.py
===================================================================
--- trunk/numpy/core/tests/test_datetime.py	2010-04-27 20:54:08 UTC (rev 8371)
+++ trunk/numpy/core/tests/test_datetime.py	2010-04-27 23:48:16 UTC (rev 8372)
@@ -56,3 +56,18 @@
 
     def test_divisor_conversion_as(self):
         self.assertRaises(ValueError, lambda : np.dtype('M8[as/10]'))
+
+    def test_creation_overflow(self):
+        date = '1980-03-23 20:00:00'
+        timesteps = np.array([date], dtype='datetime64[s]')[0].astype(int)
+        for unit in ['ms', 'us', 'ns']:
+            timesteps *= 1000
+            x = np.array([date], dtype='datetime64[%s]' % unit)
+
+            assert_equal(timesteps, x[0].astype(np.int64),
+                         err_msg='Datetime conversion error for unit %s' % unit)
+
+        assert_equal(x[0].astype(int), 322689600000000000)
+
+if __name__ == "__main__":
+    run_module_suite()



More information about the Numpy-svn mailing list