[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastrocommits] master 6a291cd: Library type.h: integers can be read
From: 
Mohammad Akhlaghi 
Subject: 
[gnuastrocommits] master 6a291cd: Library type.h: integers can be read as floats when ending in . or .0 
Date: 
Mon, 25 May 2020 18:34:09 0400 (EDT) 
branch: master
commit 6a291cd0f92d6ef1017a404b945628b3b86cefe2
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
Library type.h: integers can be read as floats when ending in . or .0
For numerical analysis, it is common practice to simply put a '.' or '.0'
after them to tell the programs to parse them as floating point (for
example when dividing 2 by 3). However, until now, the
'gal_type_string_to_number' function would parse numbers ending in '.' or
'.0' as integers. The only way to force it to parse them as floating point
was to put a 'f' suffix.
So with this commit, the 'gal_type_string_to_number' function (which is in
charge of parsing strings to numbers) will interpret any number that has a
'.' inside of it as a floating point. Note that it has already been parsed
as a number by the C library, so there is no problem in the '.' having
another meaning.
While correcting the documentation, I noticed that we also force a
floatingpoint type on the 'pow' (topower) operator of Arithmetic. But
that is again nonintuitive, so a step was added to internally convert the
values to floating point (when they are integers), and free them before
coming out.
This task was suggested by Carlos Allende Prieto.

NEWS  16 ++++++++++++++++
THANKS  1 +
doc/announceacknowledge.txt  1 +
doc/gnuastro.texi  32 +++++++++++++++
lib/arithmetic.c  43 ++++++++++++++++++++++++++++++
lib/type.c  8 +++++++
6 files changed, 70 insertions(+), 31 deletions()
diff git a/NEWS b/NEWS
index fb7d08d..efca08b 100644
 a/NEWS
+++ b/NEWS
@@ 7,10 +7,26 @@ See the end of the file for license conditions.
** New features
+ Arithmetic:
+  To force integers to floats, you can also put a '.' or '.0' after
+ them. Until now, it was only possibly by putting an 'f' after
+ them. Hence while '5' will be read as an integer, '5.', '5.0' or '5f'
+ will be read as floating point. This also applies to column arithmetic
+ in Table.
+
** Removed features
** Changed features
+ Arithmetic:
+  The 'pow' operator can also accept integer inputs. This also applies
+ to column arithmetic in Table.
+
+ Library:
+  gal_type_string_to_number: Numbers ending in '.' or '.0' will be
+ parsed as floating point. Until now, it would only parse numbers as
+ floating point if they had nonzero decimals.
+
** Bugs fixed
bug #58434: MakeCatalog crash when ordering is required and no usable pixels
diff git a/THANKS b/THANKS
index 28e0700..707d693 100644
 a/THANKS
+++ b/THANKS
@@ 20,6 +20,7 @@ support in Gnuastro. The list is ordered alphabetically (by
family name).
Valentina Abrilmelgarejo address@hidden
Marjan Akbari address@hidden
+ Carlos Allende Prieto address@hidden
Hamed Altafi address@hidden
Roland Bacon address@hidden
Roberto Baena Gallé address@hidden
diff git a/doc/announceacknowledge.txt b/doc/announceacknowledge.txt
index e160424..010cc61 100644
 a/doc/announceacknowledge.txt
+++ b/doc/announceacknowledge.txt
@@ 1,5 +1,6 @@
Alphabetically ordered list to acknowledge in the next release.
+Carlos Allende Prieto
Raúl Infante Sainz
Zahra Sharbaf
Ole Streicher
diff git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 0f05717..f7aa34c 100644
 a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ 10150,9 +10150,7 @@ Note that the modulo operator only works on integer
types.
Absolute value of first operand, so ``@command{4 abs}'' is equivalent to
@mymath{4}.
@item pow
First operand to the power of the second, so ``@command{4.3 5f pow}'' is
equivalent to @mymath{4.3^{5}}.
Currently @code{pow} will only work on single or double precision floating
point numbers or images.
To be sure that a number is read as a floating point (even if it doesn't have
any nonzero decimals) put an @code{f} after it.
+First operand to the power of the second, so ``@command{4.3 5 pow}'' is
equivalent to @mymath{4.3^{5}}.
@item sqrt
The square root of the first operand, so ``@command{5 sqrt}'' is equivalent to
@mymath{\sqrt{5}}.
@@ 10743,7 +10741,8 @@ $ astarithmetic image.fits image.fits 
out=skysub.fits \
hdu=1 hdu=4
## Add two images, then divide them by 2 (2 is read as floating point):
$ astarithmetic image1.fits image2.fits + 2f / out=average.fits
+## Note that without the '.0', the '2' will be read/used as an integer.
+$ astarithmetic image1.fits image2.fits + 2.0 / out=average.fits
## Use Arithmetic's average operator:
$ astarithmetic image1.fits image2.fits average out=average.fits
@@ 10841,7 +10840,8 @@ But when Arithmetic is called with
@option{dontdelete}, it will appended the d
Arithmetic accepts two kinds of input: images and numbers.
Images are considered to be any of the inputs that is a file name of a
recognized type (see @ref{Arguments}) and has more than one element/pixel.
Numbers on the commandline will be read into the smallest type (see
@ref{Numeric data types}) that can store them, so @command{2} will be read as
a @code{char} type (which is signed on most systems and can thus keep negative
values), @command{2500} will be read as an @code{unsigned short} (all positive
numbers will be read as unsigned), while @code{3.1415926535897} will be read as
a @code{double} and @code{3.14} will be read as a @code{float}.
To force a number to be read as float, add a @code{f} after it, so
@command{5f} will be added to the stack as @code{float} (see @ref{Reverse
polish notation}).
+To force a number to be read as float, put a @code{.} after it (possibly
followed by a zero for easier readability), or add an @code{f} after it.
+Hence while @command{5} will be read as an integer, @command{5.},
@command{5.0} or @command{5f} will be added to the stack as @code{float} (see
@ref{Reverse polish notation}).
Unless otherwise stated (in @ref{Arithmetic operators}), the operators can
deal with numeric multiple data types (see @ref{Numeric data types}).
For example in ``@command{a.fits b.fits +}'', the image types can be
@code{long} and @code{float}.
@@ 18979,15 +18979,16 @@ if( gal_type_from_string(&out, string,
GAL_TYPE_FLOAT32) )
@end deftypefun
@deftypefun {void *} gal_type_string_to_number (char @code{*string}, uint8_t
@code{*type})
Read @code{string} into smallest type that can host the number, the
allocated space for the number will be returned and the type of the number
will be put into the memory that @code{type} points to. If @code{string}
couldn't be read as a number, this function will return @code{NULL}.
+Read @code{string} into smallest type that can host the number, the allocated
space for the number will be returned and the type of the number will be put
into the memory that @code{type} points to.
+If @code{string} couldn't be read as a number, this function will return
@code{NULL}.
For the ranges acceptable by each type see @ref{Numeric data types}. For
integers it is clear, for floating point types, this function will count
the number of significant digits and determine if the given string is
single or double precision as described in that section.
+This function calls the C library's @code{strtod} function to read
@code{string} as a doubleprecision floating point number.
+When successful, it will check the value to put it in the smallest numerical
data type that can handle it.
+However, if @code{string} is successfully parsed as a number @emph{and} there
is @code{.} in @code{string}, it will force the number into floating point
types.
+For example @code{"5"} is read as an integer, while @code{"5."} or
@code{"5.0"}, or @code{"5.00"} will be read as a floating point
(singleprecision).
+
+For the ranges acceptable by each type see @ref{Numeric data types}.
+For integers, the range is clear, but for floating point types, this function
will count the number of significant digits and determine if the given string
is single or double precision as described in that section.
@end deftypefun
@node Pointers, Library blank values, Library data types, Gnuastro library
@@ 22467,10 +22468,7 @@ The output type is a single integer.
@end deffn
@deffn Macro GAL_ARITHMETIC_OP_POW
Binary operator topower operator. When @code{gal_arithmetic} is called
with any of these operators, it will expect two operands: raising the first
by the second. This operator only accepts floating point inputs and the
output is also floating point.
+Binary operator topower operator. When @code{gal_arithmetic} is called with
any of these operators, it will expect two operands: raising the first by the
second (returning a floating point, inputs can be integers).
@end deffn
@deffn Macro GAL_ARITHMETIC_OP_BITAND
diff git a/lib/arithmetic.c b/lib/arithmetic.c
index 8a4c8c6..744b7b1 100644
 a/lib/arithmetic.c
+++ b/lib/arithmetic.c
@@ 79,7 +79,7 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
/* Some functions are only for a floating point operand, so if the input
isn't floating point, inform the user to change the type explicitly,
doing it implicitly/internally puts too much responsability on the
 program. */
+ program.
static void
arithmetic_check_float_input(gal_data_t *in, int operator, char *numstr)
{
@@ 101,7 +101,7 @@ arithmetic_check_float_input(gal_data_t *in, int operator,
char *numstr)
numstr, gal_type_name(in>type, 1));
}
}

+*/
@@ 1682,24 +1682,26 @@ arithmetic_binary(int operator, int flags, gal_data_t
*l, gal_data_t *r)
static gal_data_t *
arithmetic_binary_function_flt(int operator, int flags, gal_data_t *l,
 gal_data_t *r)
+arithmetic_binary_function_flt(int operator, int flags, gal_data_t *il,
+ gal_data_t *ir)
{
int final_otype;
 gal_data_t *o=NULL;
size_t out_size, minmapsize;
 int quietmmap=l>quietmmap && r>quietmmap;

+ gal_data_t *l, *r, *o=NULL;
+ int quietmmap=il>quietmmap && ir>quietmmap;
/* Simple sanity check on the input sizes */
 if( !( (flags & GAL_ARITHMETIC_NUMOK) && (l>size==1  r>size==1))
 && gal_dimension_is_different(l, r) )
+ if( !( (flags & GAL_ARITHMETIC_NUMOK) && (il>size==1  ir>size==1))
+ && gal_dimension_is_different(il, ir) )
error(EXIT_FAILURE, 0, "%s: the input datasets don't have the same "
"dimension/size", __func__);
 /* Check for the types of the left and right operands. */
 arithmetic_check_float_input(l, operator, "first");
 arithmetic_check_float_input(r, operator, "second");
+ /* Convert the values to double precision floating point if they are
+ integer. */
+ l = ( (il>type==GAL_TYPE_FLOAT32  il>type==GAL_TYPE_FLOAT64)
+ ? il : gal_data_copy_to_new_type(il, GAL_TYPE_FLOAT64) );
+ r = ( (ir>type==GAL_TYPE_FLOAT32  ir>type==GAL_TYPE_FLOAT64)
+ ? ir : gal_data_copy_to_new_type(ir, GAL_TYPE_FLOAT64) );
/* Set the output type. */
final_otype = gal_type_out(l>type, r>type);
@@ 1736,7 +1738,7 @@ arithmetic_binary_function_flt(int operator, int flags,
gal_data_t *l,
/* Start setting the operator and operands. */
switch(operator)
{
 case GAL_ARITHMETIC_OP_POW: BINFUNC_F_OPERATOR_SET( pow ); break;
+ case GAL_ARITHMETIC_OP_POW: BINFUNC_F_OPERATOR_SET( pow ); break;
default:
error(EXIT_FAILURE, 0, "%s: operator code %d not recognized",
__func__, operator);
@@ 1753,9 +1755,24 @@ arithmetic_binary_function_flt(int operator, int flags,
gal_data_t *l,
were allocated. */
if(flags & GAL_ARITHMETIC_FREE)
{
+ /* Clean the main used (temporarily allocated) datasets. */
if (o==l) gal_data_free(r);
else if(o==r) gal_data_free(l);
else { gal_data_free(l); gal_data_free(r); }
+
+ /* Clean the raw inputs, if they weren't equal to the datasets. */
+ if (o==il) { if(ir!=r) gal_data_free(ir); }
+ else if(o==ir) { if(il!=l) gal_data_free(il); }
+ else { if(il!=l) gal_data_free(il);
+ if(ir!=r) gal_data_free(ir); }
+ }
+ else
+ {
+ /* Input datasets should be kept, but we don't want the temporary
+ datasets, so if they were allocated (they don't equal the input
+ pointers, free them). */
+ if (l!=il) gal_data_free(l);
+ if (r!=ir) gal_data_free(r);
}
/* Return */
diff git a/lib/type.c b/lib/type.c
index 2e9c6d4..3ade3d4 100644
 a/lib/type.c
+++ b/lib/type.c
@@ 562,8 +562,8 @@ gal_type_string_to_number(char *string, uint8_t *type)
{
void *ptr, *out;
int fnz=1, lnz=0; /* 'F'irst (or 'L'ast) 'N'on'Z'ero. */
 char *tailptr, *cp;
uint8_t forcedfloat=0;
+ char *c, *tailptr, *cp;
/* Define initial spaces to keep the value. */
uint8_t u8; int8_t i8; uint16_t u16; int16_t i16;
@@ 575,6 +575,12 @@ gal_type_string_to_number(char *string, uint8_t *type)
if(*tailptr=='f') { if(tailptr[1]=='\0') forcedfloat=1; else return NULL; }
else if (*tailptr!='\0') return NULL;
+ /* The number has been parsed successfully as a number. But if it
+ contains a '.', then it must a "forced" float also. This won't be a
+ problem in scenarios like '.2', but people may use '2.' or '2.0' to
+ 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 )
{
[Prev in Thread] 
Current Thread 
[Next in Thread] 
 [gnuastrocommits] master 6a291cd: Library type.h: integers can be read as floats when ending in . or .0,
Mohammad Akhlaghi <=