gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master d0cd5594: Lib (type.h): properly reading sci.


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master d0cd5594: Lib (type.h): properly reading sci. notation (like 1e5) as integers
Date: Thu, 2 Jun 2022 11:22:11 -0400 (EDT)

branch: master
commit d0cd559423cd6bc0d70f42a0a45d76a99cc3524a
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Lib (type.h): properly reading sci. notation (like 1e5) as integers
    
    Until now, when Arithmetic (or column arithmetic in Table) were given
    integers that were written in scientific format (like '1e5'), it would
    crash by a bug report: saying that while the number could be read as a
    floating point, it can't be read as an integer.
    
    With this commit, we have added a check after the attempt to read the
    number as an integer: if the character that couldn't be read as an integer
    was 'e', then we simply use the floating point value and write it into the
    integer value (instead of re-reading the number).
    
    In the process, I also noticed that until now, we weren't actually checking
    if the integer actually falls within the range of 64-bit integers! Without
    this check, overflow would occur, and the results were unreasonable! With
    this commit, that issue has also been addressed.
    
    This bug was reported by Elham Saremi.
    
    This fixes bug #62564.
---
 NEWS       |  2 ++
 lib/type.c | 27 +++++++++++++++++++++------
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/NEWS b/NEWS
index 277832b1..9f11cdbc 100644
--- a/NEWS
+++ b/NEWS
@@ -93,6 +93,8 @@ See the end of the file for license conditions.
   bug #62548: Table doesn't recognize plain-text string column when defined
               width is larger and it is the last column. Found with the
               help of Sepideh Eskandarlou.
+  bug #62564: Arithmetic not parsing numbers in scientific notation (for
+              example '1e5'). Found by Elham Saremi.
 
 
 
diff --git a/lib/type.c b/lib/type.c
index 50d5a6b0..49186311 100644
--- a/lib/type.c
+++ b/lib/type.c
@@ -582,8 +582,13 @@ gal_type_string_to_number(char *string, uint8_t *type)
      force a float and this loop is necessary in such cases. */
   for(c=string; *c!='\0'; ++c) if(*c=='.') { forcedfloat=1; break; }
 
-  /* See if the number is actually an integer: */
-  if( forcedfloat==0 && ceil(d) == d )
+  /* Read the number as an integer if 1) we aren't in forced-float mode, 2)
+     the number is actually an integer ('ceil(d)==d'), and 3) the number
+     fits within interger limits: the maximum value of an unsigned 64-bit
+     integer is ~1.8e19, and the minimum value of a signed 64-bit integer
+     is ~9.2e-18), see the "Numeric data types" section of Gnuastro's
+     book. */
+  if( forcedfloat==0 && ceil(d) == d && d<1.8e19f && d>-1.8e19f )
     {
       /* We know the number is an integer, so we should re-read it again,
          but this time, as an integer, because: 1) floating point numbers
@@ -593,10 +598,20 @@ gal_type_string_to_number(char *string, uint8_t *type)
          secondary because the parsing itself takes more time! */
       l=strtol(string, &tailptr, 0);
       if(*tailptr!='\0')
-        error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s "
-              "to fix this problem. The string '%s' couldn't be "
-              "parsed with 'strtol', but was parsed by 'strtod'",
-              __func__, PACKAGE_BUGREPORT, string);
+        {
+          /* If 'tailptr' is simply an 'e', the input string was in
+             scientific notation (for example '1e5'). In such cases, the
+             number of decimals is (usually!) enough to fit in a double,
+             and we can simply put the value of 'd' in 'l'. Note that with
+             'ceil(d)==d' we have confirmed that the number is actually an
+             integer (and not a float). */
+          if(*tailptr=='e') l=d;
+          else
+            error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at "
+                  "%s to fix this problem. The string '%s' couldn't "
+                  "be parsed with 'strtol', but was parsed by 'strtod'",
+                  __func__, PACKAGE_BUGREPORT, string);
+        }
 
       /* If the number is negative, put it in the signed types (based on
          its value). If its zero or positive, then put it in the unsigned



reply via email to

[Prev in Thread] Current Thread [Next in Thread]