[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master a4c5b9d 012/125: Binary operator arithmetic wo
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master a4c5b9d 012/125: Binary operator arithmetic works on uncompiled types |
Date: |
Sun, 23 Apr 2017 22:36:26 -0400 (EDT) |
branch: master
commit a4c5b9dc6cd86a523f50e783a3072cb2fe24a338
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
Binary operator arithmetic works on uncompiled types
Until now, if the inputs to the binary operators were an uncompiled type,
`gal_data_arithmetic' would stop with an error. But now, there are checks
before the actual operation and if the types of any of the inputs or output
are not compiled, they will be convereted to an existing larger datatype.
In `configure.ac', the check to set the printed value in the configure
message was moved immediately after the value is set, so nothing in the
middle can possibly change it, making the printed value more trustable.
The new function `gal_data_type_string' was also created so it will be easy
to print readable debugging messages, but it can be used in other contexts
too.
---
configure.ac | 22 ++--
doc/gnuastro.texi | 52 ++++----
lib/data-arithmetic-binary.h | 279 +++++++++++++++++++++++++++++++++++++++----
lib/data-arithmetic.c | 8 +-
lib/data.c | 74 +++++++++++-
lib/gnuastro/data.h | 5 +-
6 files changed, 378 insertions(+), 62 deletions(-)
diff --git a/configure.ac b/configure.ac
index 2bda5cc..0ae190c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -296,10 +296,10 @@ AC_ARG_ENABLE([bin-op-uchar],
[Native binary operators on unsigned char data.])],
[AS_IF([test "x$enable_bin_op_uchar" != xno],
[binop_uchar=1], [binop_uchar=0])], [])
+AS_IF([test "x$binop_uchar" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_UCHAR], [$binop_uchar],
[Native binary operations on unsigned char data.])
AC_SUBST(HAVE_BIN_OP_UCHAR, [$binop_uchar])
-AS_IF([test "x$binop_uchar" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile char binary data operators)
@@ -308,10 +308,10 @@ AC_ARG_ENABLE([bin-op-char],
[Native binary operations on char data.])],
[AS_IF([test "x$enable_bin_op_char" != xno],
[binop_char=1], [binop_char=0])], [])
+AS_IF([test "x$binop_char" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_CHAR], [$binop_char],
[Native binary operations on char data.])
AC_SUBST(HAVE_BIN_OP_CHAR, [$binop_char])
-AS_IF([test "x$binop_char" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile unsigned short binary data operators)
@@ -320,10 +320,10 @@ AC_ARG_ENABLE([bin-op-ushort],
[Native binary operators on unsigned short data.])],
[AS_IF([test "x$enable_bin_op_ushort" != xno],
[binop_ushort=1], [binop_ushort=0])], [])
+AS_IF([test "x$binop_ushort" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_USHORT], [$binop_ushort],
[Native binary operations on unsigned short data.])
AC_SUBST(HAVE_BIN_OP_USHORT, [$binop_ushort])
-AS_IF([test "x$binop_ushort" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile short binary data operators)
@@ -332,10 +332,10 @@ AC_ARG_ENABLE([bin-op-short],
[Native binary operations on short data.])],
[AS_IF([test "x$enable_bin_op_short" != xno],
[binop_short=1], [binop_short=0])], [])
+AS_IF([test "x$binop_short" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_SHORT], [$binop_short],
[Native binary operations on short data.])
AC_SUBST(HAVE_BIN_OP_SHORT, [$binop_short])
-AS_IF([test "x$binop_short" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile unsigned int binary data operators)
@@ -344,10 +344,10 @@ AC_ARG_ENABLE([bin-op-uint],
[Native binary operators on unsigned int data.])],
[AS_IF([test "x$enable_bin_op_uint" != xno],
[binop_uint=1], [binop_uint=0])], [])
+AS_IF([test "x$binop_uint" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_UINT], [$binop_uint],
[Native binary operations on unsigned int data.])
AC_SUBST(HAVE_BIN_OP_UINT, [$binop_uint])
-AS_IF([test "x$binop_uint" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile int binary data operators)
@@ -356,10 +356,10 @@ AC_ARG_ENABLE([bin-op-int],
[Native binary operations on int data.])],
[AS_IF([test "x$enable_bin_op_int" != xno],
[binop_int=1], [binop_int=0])], [])
+AS_IF([test "x$binop_int" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_INT], [$binop_int],
[Native binary operations on int data.])
AC_SUBST(HAVE_BIN_OP_INT, [$binop_int])
-AS_IF([test "x$binop_int" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile unsigned long binary data operators)
@@ -368,10 +368,10 @@ AC_ARG_ENABLE([bin-op-ulong],
[Native binary operators on unsigned long data.])],
[AS_IF([test "x$enable_bin_op_ulong" != xno],
[binop_ulong=1], [binop_ulong=0])], [])
+AS_IF([test "x$binop_ulong" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_ULONG], [$binop_ulong],
[Native binary operations on unsigned long data.])
AC_SUBST(HAVE_BIN_OP_ULONG, [$binop_ulong])
-AS_IF([test "x$binop_ulong" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile long native binary data operators)
@@ -380,10 +380,10 @@ AC_ARG_ENABLE([bin-op-long],
[Native binary operations on long data.])],
[AS_IF([test "x$enable_bin_op_long" != xno],
[binop_long=1], [binop_long=0])], [])
+AS_IF([test "x$binop_long" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_LONG], [$binop_long],
[Native binary operations on long data.])
AC_SUBST(HAVE_BIN_OP_LONG, [$binop_long])
-AS_IF([test "x$binop_long" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile LONGLONG native binary data operators)
@@ -392,10 +392,10 @@ AC_ARG_ENABLE([bin-op-longlong],
[Native binary operations on LONGLONG data.])],
[AS_IF([test "x$enable_bin_op_longlong" != xno],
[binop_longlong=1], [binop_longlong=0])], [])
+AS_IF([test "x$binop_longlong" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_LONGLONG], [$binop_longlong],
[Native binary operations on LONGLONG data.])
AC_SUBST(HAVE_BIN_OP_LONG, [$binop_longlong])
-AS_IF([test "x$binop_longlong" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile float native binary data operators)
@@ -404,10 +404,10 @@ AC_ARG_ENABLE([bin-op-float],
[Native binary operations on float data.])],
[AS_IF([test "x$enable_bin_op_float" != xno],
[binop_float=1], [binop_float=0])], [])
+AS_IF([test "x$binop_float" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_FLOAT], [$binop_float],
[Native binary operations on float data.])
AC_SUBST(HAVE_BIN_OP_FLOAT, [$binop_float])
-AS_IF([test "x$binop_float" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile double native binary data operators)
@@ -416,10 +416,10 @@ AC_ARG_ENABLE([bin-op-double],
[Native binary operations on double data.])],
[AS_IF([test "x$enable_bin_op_double" != xno],
[binop_double=1], [binop_double=0])], [])
+AS_IF([test "x$binop_double" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_DOUBLE], [$binop_double],
[Native binary operations on double data.])
AC_SUBST(HAVE_BIN_OP_DOUBLE, [$binop_double])
-AS_IF([test "x$binop_double" != x0], [binoptprint=yes], [binoptprint=no])
AC_MSG_RESULT($binoptprint)
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 10f574d..4a6bbb7 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -3142,19 +3142,21 @@ Enable the binary data-structure operators to work
natively on the
respective type of data (@option{u} stands for unsigned types). Some types
are compiled by default, to disable them (or disable any other type),
either run @option{enable-bin-op-TYPE=no}, or run
address@hidden You can tell which types are acceptable by
-default by inspecting the messages of @command{./configure}.
-
-Binary operators are some of the most common operators to the
address@hidden program or the @code{gal_data_arithmetic} function in
address@hidden library}. To operate most efficiently (as fast as possible
-without using too much of the system resources like memory or CPU), it is
-best to rely on the native types of the input data. For example, if you
-want to add an integer array with a floating point array, using the native
-types, means using the C language's internal type conversion. If we don't
-use the native conversion, then the integer array has to be converted to
-the same type as the floating point array to do the conversion. This will
-consume memory and CPU resources and ultimately slow down the running.
address@hidden You can tell which types are configured by
+default by inspecting the messages of @command{./configure} without any of
+these options.
+
+Binary operators, for example @code{+} or @code{>} (greater than), are some
+of the most common operators to the @ref{Arithmetic} program or the
address@hidden function in @ref{Gnuastro library}. To operate
+most efficiently (as fast as possible without using extra memory or CPU
+resources), it is best to rely on the native types of the input data. For
+example, if you want to add an integer array with a floating point array,
+using the native types, means relying the system's internal type conversion
+for each array element. If we don't use the native conversion, then the
+integer array has to be converted to the same type as the floating point
+array to do the conversion. This will consume memory and CPU resources and
+ultimately slow down the running.
There are many binary operators and in order to have them operate natively
on of each of the above types, the compiler has to prepare for many
@@ -3163,16 +3165,20 @@ address@hidden can also greatly increase the file size
of the
library, from a few hundred kilobytes to a few megabytes} (when you run
@command{make}). For example, with only one type, compilation will take
less than a minute, but if you enable all types, it can take upto an hour
-or more depending on your computer. However, this time that is invested
-once at compilation time will result in great profits each time you run
-Gnuastro programs or libraries, because no internal type conversion will be
-necessary.
-
-Therefore, if you commonly work with very specific data-types, you can add
-them (and remove the default ones you don't need them) with these options
-to speed up your work. Alternatively, GNU/Linux distribution package
-managers who compile once (for all the users who just download the compiled
-programs and executables), can enable all types to help their users.
+or more depending on your computer. However, the profits of significant
+investment at compilation time (only once) will be directly felt each time
+you run Gnuastro programs or libraries, because no internal type conversion
+will be necessary.
+
+If you commonly work with very specific data-types, you can add them (and
+remove the default ones you don't need) with these options to speed up your
+work. Alternatively, GNU/Linux distribution package managers who compile
+once (for a large audience of users who just download the compiled programs
+and executables), can enable all types to help their users. Since the
+outputs of comparison operators are @code{unsigned char} type and most
+astronomical datasets are in @code{float}, the recommended minimum enabled
+types are @code{unsigned char} and @code{float}.
+
diff --git a/lib/data-arithmetic-binary.h b/lib/data-arithmetic-binary.h
index 241d86c..cb08758 100644
--- a/lib/data-arithmetic-binary.h
+++ b/lib/data-arithmetic-binary.h
@@ -33,9 +33,9 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
/************************************************************************/
#if GAL_CONFIG_BIN_OP_UCHAR == 1
#define BINARY_LEFT_RIGHT_DONE_UCHAR(LT, RT, OP) \
- case GAL_DATA_TYPE_UCHAR: \
- BINARY_OPERATOR_FOR_TYPE(LT, RT, unsigned char, OP); \
- break;
+ case GAL_DATA_TYPE_UCHAR: \
+ BINARY_OPERATOR_FOR_TYPE(LT, RT, unsigned char, OP); \
+ break;
#define BINARY_LEFT_DONE_UCHAR(LT, OP) \
case GAL_DATA_TYPE_UCHAR: \
BINARY_LEFT_RIGHT_DONE(LT, unsigned char, OP); \
@@ -304,8 +304,186 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
/************************************************************************/
-/************* Binary conversion macros *****************/
+/************* Macros for specifying the type *****************/
/************************************************************************/
+
+#define BINARY_TYPE_FOR_CONVERT_TO_COMPILED_TYPE(intype) \
+ ntype=0; \
+ switch(intype) \
+ { \
+ case GAL_DATA_TYPE_UCHAR: \
+ if(GAL_CONFIG_BIN_OP_UCHAR) ntype=GAL_DATA_TYPE_UCHAR; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_USHORT) ntype=GAL_DATA_TYPE_USHORT; \
+ else if(GAL_CONFIG_BIN_OP_SHORT) ntype=GAL_DATA_TYPE_SHORT; \
+ else if(GAL_CONFIG_BIN_OP_UINT) ntype=GAL_DATA_TYPE_UINT; \
+ else if(GAL_CONFIG_BIN_OP_INT) ntype=GAL_DATA_TYPE_INT; \
+ else if(GAL_CONFIG_BIN_OP_ULONG) ntype=GAL_DATA_TYPE_ULONG; \
+ else if(GAL_CONFIG_BIN_OP_LONG) ntype=GAL_DATA_TYPE_LONG; \
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG;\
+ else if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_CHAR: \
+ if(GAL_CONFIG_BIN_OP_CHAR) ntype=GAL_DATA_TYPE_CHAR; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_SHORT) ntype=GAL_DATA_TYPE_SHORT; \
+ else if(GAL_CONFIG_BIN_OP_INT) ntype=GAL_DATA_TYPE_INT; \
+ else if(GAL_CONFIG_BIN_OP_LONG) ntype=GAL_DATA_TYPE_LONG; \
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG;\
+ else if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_USHORT: \
+ if(GAL_CONFIG_BIN_OP_USHORT) ntype=GAL_DATA_TYPE_USHORT; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_UINT) ntype=GAL_DATA_TYPE_UINT; \
+ else if(GAL_CONFIG_BIN_OP_INT) ntype=GAL_DATA_TYPE_INT; \
+ else if(GAL_CONFIG_BIN_OP_ULONG) ntype=GAL_DATA_TYPE_ULONG; \
+ else if(GAL_CONFIG_BIN_OP_LONG) ntype=GAL_DATA_TYPE_LONG; \
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG;\
+ else if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_SHORT: \
+ if(GAL_CONFIG_BIN_OP_SHORT) ntype=GAL_DATA_TYPE_SHORT; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_INT) ntype=GAL_DATA_TYPE_INT; \
+ else if(GAL_CONFIG_BIN_OP_LONG) ntype=GAL_DATA_TYPE_LONG; \
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG;\
+ else if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_UINT: \
+ if(GAL_CONFIG_BIN_OP_UINT) ntype=GAL_DATA_TYPE_UINT; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_ULONG) ntype=GAL_DATA_TYPE_ULONG; \
+ else if(GAL_CONFIG_BIN_OP_LONG) ntype=GAL_DATA_TYPE_LONG; \
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG;\
+ else if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_INT: \
+ if(GAL_CONFIG_BIN_OP_INT) ntype=GAL_DATA_TYPE_INT; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_LONG) ntype=GAL_DATA_TYPE_LONG; \
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG;\
+ else if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_ULONG: \
+ if(GAL_CONFIG_BIN_OP_ULONG) ntype=GAL_DATA_TYPE_ULONG; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG;\
+ else if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_LONG: \
+ if(GAL_CONFIG_BIN_OP_LONG) ntype=GAL_DATA_TYPE_LONG; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG;\
+ else if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_LONGLONG: \
+ if(GAL_CONFIG_BIN_OP_LONGLONG) ntype=GAL_DATA_TYPE_LONGLONG; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_FLOAT: \
+ if(GAL_CONFIG_BIN_OP_FLOAT) ntype=GAL_DATA_TYPE_FLOAT; \
+ else \
+ { \
+ if (GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ } \
+ break; \
+ \
+ case GAL_DATA_TYPE_DOUBLE: \
+ if(GAL_CONFIG_BIN_OP_DOUBLE) ntype=GAL_DATA_TYPE_DOUBLE; \
+ break; \
+ \
+ default: \
+ error(EXIT_FAILURE, 0, "type %d not recognized in " \
+ "BINARY_CONVERT_TO_COMPILED_TYPE", intype); \
+ }
+
+
+
+
+
+/* Note that for signed types, we won't be considering the unsigned types
+ of the larger types. */
+#define BINARY_CONVERT_TO_COMPILED_TYPE(in, out) \
+ \
+ /* Initialize the values that will be set. */ \
+ out=NULL; \
+ \
+ /* Set the values. */ \
+ BINARY_TYPE_FOR_CONVERT_TO_COMPILED_TYPE(in->type); \
+ \
+ /* If type is not compiled, then convert the dataset to the */ \
+ /* first compiled larger type. */ \
+ if(in->type==ntype) \
+ out=in; \
+ else \
+ { \
+ if(ntype) \
+ { \
+ out=gal_data_copy_to_new_type(in, ntype); \
+ if(flags & GAL_DATA_ARITH_FREE) \
+ { gal_data_free(in); in=NULL; } \
+ } \
+ else \
+ { \
+ char *typestring=gal_data_type_string(in->type); \
+ error(EXIT_FAILURE, 0, "The given %s type data given to " \
+ "binary operators is not compiled for native operation "\
+ "and no larger types are compiled either.\n\nThe " \
+ "largest type (which can act as a fallback for any " \
+ "input type is double, so configure Gnuastro again " \
+ "with `--enable-bin-op-double' to not get this error " \
+ "any more. However, if you commonly deal with %s type " \
+ "data, also enable %s with a similar option at " \
+ "configure time to greatly increase running time and " \
+ "avoid unnecessary RAM and CPU resources. Run" \
+ "`./configure --help' in Gnuastro's top source " \
+ "directory (after unpacking the tarball) for the full " \
+ "list of options", typestring, typestring, typestring); \
+ } \
+ }
+
+
+
+
+
#define BINARY_OPERATOR_FOR_TYPE(LT, RT, OT, OP){ \
LT *la=l->array; \
RT *ra=r->array; \
@@ -369,33 +547,71 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/************************************************************************/
+/************* Top level macro *****************/
+/************************************************************************/
/* Prepare the inputs and output for binary operations and do the job.*/
#define BINARY_INTERNAL(OP, OUT_TYPE) { \
\
/* Read the variable arguments. */ \
- gal_data_t *l, *r; \
- l = va_arg(va, gal_data_t *); \
- r = va_arg(va, gal_data_t *); \
+ /* `lo' and `ro' keep the original data, in case their type isn't */ \
+ /* built (based on configure options are configure time). */ \
+ size_t out_size, minmapsize; \
+ int ntype, otype, final_otype; \
+ gal_data_t *l, *r, *lo, *ro, *tmp_o; \
+ \
+ \
+ /* Prepare original data structures from the input arguments. */ \
+ lo = va_arg(va, gal_data_t *); \
+ ro = va_arg(va, gal_data_t *); \
\
\
/* Simple sanity check on the input sizes */ \
- if( !( (flags & GAL_DATA_ARITH_NUMOK) && (l->size==1 || r->size==1)) \
- && gal_data_dsize_is_different(l, r) ) \
- error(EXIT_FAILURE, 0, "The datasets don't have the same " \
- "dimension/size"); \
+ if( !( (flags & GAL_DATA_ARITH_NUMOK) && (lo->size==1 || ro->size==1))\
+ && gal_data_dsize_is_different(lo, ro) ) \
+ error(EXIT_FAILURE, 0, "ini BINARY_INTERNAL, the input datasets " \
+ "don't have the same dimension/size"); \
\
\
/* Set the output type and size. */ \
- out_type = OUT_TYPE ? OUT_TYPE : gal_data_out_type(l, r); \
- out_size = l->size > r->size ? l->size : r->size; \
+ minmapsize = ( lo->minmapsize < ro->minmapsize \
+ ? lo->minmapsize : ro->minmapsize ); \
+ out_size = lo->size > ro->size ? lo->size : ro->size; \
+ final_otype = OUT_TYPE ? OUT_TYPE : gal_data_out_type(lo, ro); \
+ \
+ \
+ /* Make sure the input arrays have one of the compiled types. */ \
+ BINARY_CONVERT_TO_COMPILED_TYPE(lo, l); \
+ BINARY_CONVERT_TO_COMPILED_TYPE(ro, r); \
+ \
+ \
+ /* Temporary output type (in case its type isn't compiled). */ \
+ /* Note that the final output of this macro is put in `ntype'. */ \
+ BINARY_TYPE_FOR_CONVERT_TO_COMPILED_TYPE(final_otype); \
+ otype=ntype; \
\
\
/* If we want inplace output, set the output pointer to one input. */ \
/* Note that the output type can be different from both inputs. */ \
if(flags & GAL_DATA_ARITH_INPLACE) \
{ \
- if(l->type==out_type && out_size==l->size) o = l; \
- else if(r->type==out_type && out_size==r->size) o = r; \
+ if (l->type==otype && out_size==l->size) o = l; \
+ else if(r->type==otype && out_size==r->size) o = r; \
} \
\
\
@@ -406,12 +622,11 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
/* So we just have to choose the smaller minmapsize of the two to */ \
/* decide if the output array should be in RAM or not. */ \
if(o==NULL) \
- o = gal_data_alloc(NULL, out_type, \
+ o = gal_data_alloc(NULL, otype, \
l->size>1 ? l->ndim : r->ndim, \
l->size>1 ? l->dsize : r->dsize, \
- l->size>1 ? l->wcs : r->wcs, 0, \
- ( l->minmapsize<r->minmapsize \
- ? l->minmapsize : r->minmapsize ) ); \
+ l->size>1 ? l->wcs : r->wcs, 0, minmapsize ); \
+ \
\
/* Do the operations based on the different types. */ \
switch(l->type) \
@@ -434,13 +649,37 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
"for l->type in BINARY_MULTISWITCH", l->type); \
} \
\
- /* Clean up. */ \
+ \
+ /* Clean up. Note that if the input arrays can be freed, and any of */\
+ /* right or left arrays needed conversion, */ \
+ /*`BINARY_CONVERT_TO_COMPILED_TYPE' has already freed the input */ \
+ /* arrays, and we only have `r' and `l' allocated in any case. */ \
+ /* Alternatively, when the inputs shouldn't be freed, the only */ \
+ /* allocated spaces are the `r' and `l' arrays if their types */ \
+ /* weren't compiled for binary operations, we can tell this from */ \
+ /* the pointers: if they are different from the original pointers, */ \
+ /* they were allocated. */ \
if(flags & GAL_DATA_ARITH_FREE) \
{ \
if (o==l) gal_data_free(r); \
else if(o==r) gal_data_free(l); \
else { gal_data_free(l); gal_data_free(r); } \
} \
+ else \
+ { \
+ if(l!=lo) gal_data_free(l); \
+ if(r!=ro) gal_data_free(r); \
+ } \
+ \
+ \
+ /* In case otype and final_otype aren't equal, we need to convert */ \
+ /* the output data structure to the proper type. */ \
+ if(otype!=final_otype) \
+ { \
+ tmp_o=gal_data_copy_to_new_type(o, final_otype); \
+ gal_data_free(o); \
+ o=tmp_o; \
+ } \
}
diff --git a/lib/data-arithmetic.c b/lib/data-arithmetic.c
index 77acfa2..1cc7794 100644
--- a/lib/data-arithmetic.c
+++ b/lib/data-arithmetic.c
@@ -39,8 +39,6 @@ gal_data_t *
gal_data_arithmetic(int operator, unsigned char flags, ...)
{
va_list va;
- int out_type;
- size_t out_size;
gal_data_t *o=NULL;
/* Prepare the variable arguments (starting after the flags argument). */
@@ -50,9 +48,9 @@ gal_data_arithmetic(int operator, unsigned char flags, ...)
switch(operator)
{
case GAL_DATA_OPERATOR_PLUS: BINARY_INTERNAL(+, 0); break;
- case GAL_DATA_OPERATOR_MINUS: BINARY_INTERNAL(-, 0); break;
- case GAL_DATA_OPERATOR_MULTIPLY: BINARY_INTERNAL(*, 0); break;
- case GAL_DATA_OPERATOR_DIVIDE: BINARY_INTERNAL(/, 0); break;
+ case GAL_DATA_OPERATOR_MINUS: BINARY_INTERNAL(-, 0); break;
+ case GAL_DATA_OPERATOR_MULTIPLY: BINARY_INTERNAL(*, 0); break;
+ case GAL_DATA_OPERATOR_DIVIDE: BINARY_INTERNAL(/, 0); break;
case GAL_DATA_OPERATOR_LT: BINARY_INTERNAL(<, GAL_DATA_TYPE_UCHAR);
break;
case GAL_DATA_OPERATOR_LE: BINARY_INTERNAL(<=, GAL_DATA_TYPE_UCHAR);
break;
diff --git a/lib/data.c b/lib/data.c
index 155c93c..87a8fcb 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -45,7 +45,6 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
-
/*********************************************************************/
/************* Size and allocation *******************/
/*********************************************************************/
@@ -878,8 +877,79 @@ gal_data_blank_to_value(gal_data_t *data, void *value)
/*************************************************************
- ************** Copy ***************
+ ************** Types and copying ***************
*************************************************************/
+char *
+gal_data_type_string(int type)
+{
+ switch(type)
+ {
+ case GAL_DATA_TYPE_BIT:
+ return "bit";
+
+ case GAL_DATA_TYPE_UCHAR:
+ return "unsigned char";
+
+ /* CFITSIO says "int for keywords, char for table columns". Here we
+ are only assuming table columns. So in practice this also applies
+ to TSBYTE.*/
+ case GAL_DATA_TYPE_CHAR: case GAL_DATA_TYPE_LOGICAL:
+ return "char";
+
+ case GAL_DATA_TYPE_STRING:
+ return "string";
+
+ case GAL_DATA_TYPE_USHORT:
+ return "unsigned short";
+
+ case GAL_DATA_TYPE_SHORT:
+ return "short";
+
+ case GAL_DATA_TYPE_UINT:
+ return "unsigned int";
+
+ case GAL_DATA_TYPE_INT:
+ return "int";
+
+ case GAL_DATA_TYPE_ULONG:
+ return "unsigned long";
+
+ case GAL_DATA_TYPE_LONG:
+ return "long";
+
+ case GAL_DATA_TYPE_LONGLONG:
+ return "LONGLONG";
+
+ case GAL_DATA_TYPE_FLOAT:
+ return "float";
+
+ case GAL_DATA_TYPE_DOUBLE:
+ return "double";
+
+ case GAL_DATA_TYPE_COMPLEX:
+ return "complex float";
+
+ case GAL_DATA_TYPE_DCOMPLEX:
+ return "complex double";
+
+ default:
+ error(EXIT_FAILURE, 0, "type value of %d not recognized in "
+ "`gal_data_type_string'", type);
+ }
+
+ /* Any of the cases above should return this function, so if control
+ reaches here, there is a bug. */
+ error(EXIT_FAILURE, 0, "a bug! Please contact us at %s so we can address "
+ "the problem. For some reason control has reached the end of "
+ "the `gal_data_type_string' function. This must not happen",
+ PACKAGE_BUGREPORT);
+ return NULL;
+}
+
+
+
+
+
gal_data_t *
gal_data_copy(gal_data_t *in)
{
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index 8545033..dd89444 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -250,8 +250,11 @@ gal_data_blank_to_value(gal_data_t *data, void *value);
/*************************************************************
- ************** Copy ***************
+ ************** Types and copying ***************
*************************************************************/
+char *
+gal_data_type_string(int type);
+
gal_data_t *
gal_data_copy(gal_data_t *in);
- [gnuastro-commits] master 591461c 015/125: Corrected occurance of "remainder" with modulo, (continued)
- [gnuastro-commits] master 591461c 015/125: Corrected occurance of "remainder" with modulo, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 1ea9ea2 009/125: Data structure mmap information updated, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 531c263 008/125: Operators treated as macros, not string, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master ff9258a 006/125: Arithmetic with internal type conversion, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 5336d5c 024/125: Small but important corrections, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master c2fcb3e 020/125: Absolute value operator in gal_data_arithmetic, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master fdb6183 019/125: Where operator implemented in gal_data_arithmetic, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 493bc6f 001/125: Defined new gnuastro/data.h header, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master c6462d1 016/125: Type conversion operators in Arithmetic, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master c10c4be 002/125: Moved type code and alloc functions into data.h, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master a4c5b9d 012/125: Binary operator arithmetic works on uncompiled types,
Mohammad Akhlaghi <=
- [gnuastro-commits] master ad2810d 029/125: Work started on getting text table information, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master bc57ade 021/125: Minimum and maximum value operators implemented, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 2dea9a7 011/125: All binary operator types set at configure time, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master ff0b76d 018/125: New Data types section in book, bitwise not added, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master c62b01e 031/125: Corrected incrementation issue with and and or operators, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 0a32a82 027/125: Any number of searched columns from FITS are read, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master d0aa78e 005/125: Arithmetic operation on data structures in library, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 0ad0906 014/125: Bitwise operators available in arithmetic operations, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 3ad83a4 010/125: data-arithmetic and data-copy separated from data.c, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 6c6382a 013/125: Use of function instead of macros for binary operators, Mohammad Akhlaghi, 2017/04/23