[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master 0ad0906 014/125: Bitwise operators available i
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master 0ad0906 014/125: Bitwise operators available in arithmetic operations |
Date: |
Sun, 23 Apr 2017 22:36:27 -0400 (EDT) |
branch: master
commit 0ad0906b75cf95f5b2803b5abb71e52910c63623
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
Bitwise operators available in arithmetic operations
Mask images in astronomy commonly use bit values where every bit has a
special meaning. Therefore bitwise operators are important in low-level
analysis of the data. With this commit, Gnuastro's `gal_data_arithmetic'
function and thus the Arithmetic program now support bitwise operators on
integer types.
Some other minor works in this commit:
- Two new blank pixel related functions have been added:
`gal_data_has_blank' and `gal_data_flag_blank'.
- Three new operators added to `gal_data_arithmetic': "modulo"
(remainder), "isblank", and "not".
- The message at the end of configure also lets the users know that some
libraries will take a while to compile.
- Work has also started on unary operators.
This finishes task #13868.
---
bin/arithmetic/arithmetic.c | 69 +++--
configure.ac | 11 +-
doc/gnuastro.texi | 59 +++-
lib/Makefile.am | 11 +-
lib/data-arithmetic-onlyint.c | 663 ++++++++++++++++++++++++++++++++++++++++++
lib/data-arithmetic-onlyint.h | 32 ++
lib/data-arithmetic-unary.c | 100 +++++++
lib/data-arithmetic-unary.h | 31 ++
lib/data.c | 333 ++++++++++++++++++++-
lib/gnuastro/data.h | 11 +
10 files changed, 1270 insertions(+), 50 deletions(-)
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index 13883f6..ffc94a5 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -91,6 +91,8 @@ reversepolish(struct imgarithparams *p)
add_operand(p, NULL, d1);
else
{
+ /* Order is the same as in the manual. */
+ /* Simple arithmetic operators. */
if (!strcmp(token->v, "+" ))
{ op=GAL_DATA_OPERATOR_PLUS; nop=2; }
else if (!strcmp(token->v, "-" ))
@@ -99,7 +101,36 @@ reversepolish(struct imgarithparams *p)
{ op=GAL_DATA_OPERATOR_MULTIPLY; nop=2; }
else if (!strcmp(token->v, "/" ))
{ op=GAL_DATA_OPERATOR_DIVIDE; nop=2; }
+ else if (!strcmp(token->v, "%" ))
+ { op=GAL_DATA_OPERATOR_REMAINDER; nop=2; }
+ /* Mathematical Operators. */
+ else if (!strcmp(token->v, "abs"))
+ { op=GAL_DATA_OPERATOR_ABS; nop=1; }
+ else if (!strcmp(token->v, "pow"))
+ { op=GAL_DATA_OPERATOR_POW; nop=2; }
+ else if (!strcmp(token->v, "sqrt"))
+ { op=GAL_DATA_OPERATOR_SQRT; nop=1; }
+ else if (!strcmp(token->v, "log"))
+ { op=GAL_DATA_OPERATOR_LOG; nop=1; }
+ else if (!strcmp(token->v, "log10"))
+ { op=GAL_DATA_OPERATOR_LOG10; nop=1; }
+
+ /* Statistical operators. */
+ else if (!strcmp(token->v, "minval"))
+ { op=GAL_DATA_OPERATOR_MINVAL; nop=1; }
+ else if (!strcmp(token->v, "maxval"))
+ { op=GAL_DATA_OPERATOR_MAXVAL; nop=1; }
+ else if (!strcmp(token->v, "min"))
+ { op=GAL_DATA_OPERATOR_MIN; nop=-1; }
+ else if (!strcmp(token->v, "max"))
+ { op=GAL_DATA_OPERATOR_MAX; nop=-1; }
+ else if (!strcmp(token->v, "average"))
+ { op=GAL_DATA_OPERATOR_AVERAGE; nop=-1; }
+ else if (!strcmp(token->v, "median"))
+ { op=GAL_DATA_OPERATOR_MEDIAN; nop=-1; }
+
+ /* Conditional operators. */
else if (!strcmp(token->v, "lt" ))
{ op=GAL_DATA_OPERATOR_LT; nop=2; }
else if (!strcmp(token->v, "le"))
@@ -116,11 +147,6 @@ reversepolish(struct imgarithparams *p)
{ op=GAL_DATA_OPERATOR_AND; nop=2; }
else if (!strcmp(token->v, "or"))
{ op=GAL_DATA_OPERATOR_OR; nop=2; }
- else if (!strcmp(token->v, "bitand"))
- { op=GAL_DATA_OPERATOR_BITAND; nop=2; }
- else if (!strcmp(token->v, "bitor"))
- { op=GAL_DATA_OPERATOR_BITOR; nop=2; }
-
else if (!strcmp(token->v, "not"))
{ op=GAL_DATA_OPERATOR_NOT; nop=1; }
else if (!strcmp(token->v, "isblank"))
@@ -128,29 +154,18 @@ reversepolish(struct imgarithparams *p)
else if (!strcmp(token->v, "where"))
{ op=GAL_DATA_OPERATOR_WHERE; nop=3; }
- else if (!strcmp(token->v, "abs"))
- { op=GAL_DATA_OPERATOR_ABS; nop=1; }
- else if (!strcmp(token->v, "pow"))
- { op=GAL_DATA_OPERATOR_POW; nop=2; }
- else if (!strcmp(token->v, "sqrt"))
- { op=GAL_DATA_OPERATOR_SQRT; nop=1; }
- else if (!strcmp(token->v, "log"))
- { op=GAL_DATA_OPERATOR_LOG; nop=1; }
- else if (!strcmp(token->v, "log10"))
- { op=GAL_DATA_OPERATOR_LOG10; nop=1; }
+ /* Bitwise operators. */
+ else if (!strcmp(token->v, "bitand"))
+ { op=GAL_DATA_OPERATOR_BITAND; nop=2; }
+ else if (!strcmp(token->v, "bitor"))
+ { op=GAL_DATA_OPERATOR_BITOR; nop=2; }
+ else if (!strcmp(token->v, "bitxor"))
+ { op=GAL_DATA_OPERATOR_BITXOR; nop=2; }
+ else if (!strcmp(token->v, "lshift"))
+ { op=GAL_DATA_OPERATOR_BITLSH; nop=2; }
+ else if (!strcmp(token->v, "rshift"))
+ { op=GAL_DATA_OPERATOR_BITRSH; nop=2; }
- else if (!strcmp(token->v, "minval"))
- { op=GAL_DATA_OPERATOR_MINVAL; nop=1; }
- else if (!strcmp(token->v, "maxval"))
- { op=GAL_DATA_OPERATOR_MAXVAL; nop=1; }
- else if (!strcmp(token->v, "min"))
- { op=GAL_DATA_OPERATOR_MIN; nop=-1; }
- else if (!strcmp(token->v, "max"))
- { op=GAL_DATA_OPERATOR_MAX; nop=-1; }
- else if (!strcmp(token->v, "average"))
- { op=GAL_DATA_OPERATOR_AVERAGE; nop=-1; }
- else if (!strcmp(token->v, "median"))
- { op=GAL_DATA_OPERATOR_MEDIAN; nop=-1; }
else
error(EXIT_FAILURE, 0, "the argument \"%s\" could not be "
"interpretted as a FITS file, number, or operator",
diff --git a/configure.ac b/configure.ac
index 0ae190c..d2a13c1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -675,8 +675,8 @@ AC_OUTPUT
AS_IF([test x$enable_guide_message = xyes],
[
AS_ECHO([])
-
AS_ECHO([===================================================================])
-
AS_ECHO([===================================================================])
+
AS_ECHO([====================================================================])
+
AS_ECHO([====================================================================])
AS_ECHO(["$PACKAGE_NAME (Gnuastro) $PACKAGE_VERSION is successfully"])
AS_ECHO(["configured for this machine."])
AS_ECHO([])
@@ -709,9 +709,10 @@ AS_IF([test x$enable_guide_message = xyes],
AS_ECHO([])
AS_ECHO([" make"])
AS_ECHO([])
- AS_ECHO(["(Build faster on N threads with 'make -jN'.)"])
+ AS_ECHO(["(RECOMMENDED: Build faster on N threads with 'make -jN'.)"])
AS_ECHO(["(Configure with '--disable-guide-message' for no messages.)"])
-
AS_ECHO([===================================================================])
-
AS_ECHO([===================================================================])
+ AS_ECHO(["(Please be patient, some libraries take a few minutes to
compile.)"])
+
AS_ECHO([====================================================================])
+
AS_ECHO([====================================================================])
AS_ECHO([])
])
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 4a6bbb7..b84329c 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -7145,6 +7145,10 @@ the multiplication sign (for example @command{"*"}).
@item /
Division, so address@hidden 5 /}'' is equivalent to @mymath{4/5}.
address@hidden %
+Remainder, so address@hidden 2 %}'' is equivalent to @mymath{1}. Note that
+the remainder operator only works on integer types.
+
@item abs
Absolute value of first operand, so address@hidden abs}'' is
equivalent to @mymath{|4|}.
@@ -7245,16 +7249,6 @@ Non-Equality: similar to @code{lt} (`less than'
operator), but returning 1
when the two popped operands are @emph{not} equal (to double precision
floating point accuracy).
address@hidden Blank pixel
address@hidden isblank
-Test for a blank value (see @ref{Blank pixels}). In essence, this is very
-similar to the conditional operators: the output is either 1 or 0 (see the
-`less than' operator above). The difference is that it only needs one
-operand. Because of the definition of a blank pixel, a blank value is not
-even equal to itself, so you cannot use the equal operator above to select
-blank pixels. See the ``Blank pixels'' box below for more on Blank pixels
-in Arithmetic.
-
@item and
Logical AND: returns 1 if both operands have a non-zero value and 0 if both
are zero. Both operands have to be the same kind: either both images or
@@ -7270,6 +7264,16 @@ Logical NOT: returns 1 when the operand is zero and 0
when the operand is
non-zero. The operand can be an image or number, for an image, it is
applied to each pixel separately.
address@hidden Blank pixel
address@hidden isblank
+Test for a blank value (see @ref{Blank pixels}). In essence, this is very
+similar to the conditional operators: the output is either 1 or 0 (see the
+`less than' operator above). The difference is that it only needs one
+operand. Because of the definition of a blank pixel, a blank value is not
+even equal to itself, so you cannot use the equal operator above to select
+blank pixels. See the ``Blank pixels'' box below for more on Blank pixels
+in Arithmetic.
+
@item where
Change the input (pixel) value `where' a certain condition holds. The
conditional operators above can be used to define the condition. Three
@@ -7297,6 +7301,41 @@ internally. For example the case below:
$ astarithmetic in.fits reference.fits 100 gt new.fits where
@end example
address@hidden bitand
+Bitwise AND operator: only bits with values of 1 will get the value of 1,
+the rest will be set to 0. For example (assuming numbers can be written as
+bit strings on the command-line): @code{00101000 00100010 bitand} will give
address@hidden Note that the bitwise operators only work on integer type
+datasets.
+
address@hidden bitor
+Bitwise inclusive OR operator: The bit will stay 1 if atleast one of the
+two inputs has a 1 value on that bit. For example (assuming numbers can be
+written as bit strings on the command-line): @code{00101000 00100010
+bitand} will give @code{00101010}. Note that the bitwise operators only
+work on integer type datasets.
+
address@hidden bitxor
+Bitwise exclusive OR operator: A bit will be 1 if it differs between the
+two inputs. For example (assuming numbers can be written as bit strings on
+the command-line): @code{00101000 00100010 bitand} will give
address@hidden Note that the bitwise operators only work on integer type
+datasets.
+
address@hidden lshift
+Bitwise left shift operator: shift all the bits of the first operand to the
+left by a number of times given by the second operand. For example
+(assuming numbers can be written as bit strings on the command-line):
address@hidden 2 lshift} will give @code{10100000}. This is equivalent to
+multiplication by 4. Note that the bitwise operators only work on integer
+type datasets.
+
address@hidden rshift
+Bitwise right shift operator: shift all the bits of the first operand to
+the right by a number of times given by the second operand. For example
+(assuming numbers can be written as bit strings on the command-line):
address@hidden 2 rshift} will give @code{00001010}. Note that the bitwise
+operators only work on integer type datasets.
@end table
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d363c0a..09f2c9c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -41,7 +41,8 @@ libgnuastro_la_LDFLAGS = -version-info $(GAL_LT_VERSION)
# Specify the library .c files
libgnuastro_la_SOURCES = array.c box.c checkset.c configfiles.c data.c \
- data-arithmetic-binary.c data-copy.c fits.c git.c linkedlist.c mesh.c \
+ data-arithmetic-binary.c data-arithmetic-onlyint.c \
+ data-arithmetic-unary.c data-copy.c fits.c git.c linkedlist.c mesh.c \
mode.c polygon.c qsort.c spatialconvolve.c statistics.c threads.c \
timing.c txtarray.c wcs.c
@@ -69,10 +70,10 @@ pkginclude_HEADERS = gnuastro/config.h
$(headersdir)/array.h \
# and if they are not explicitly mentioned somewhere in the Makefile, they
# will not distributed, so we need to explicitly tell Automake to
# distribute them here.
-EXTRA_DIST = gnuastro.pc.in data-arithmetic.h data-arithmetic-binary.h \
- data-copy.h config.h.in checkset.h commonargs.h commonparams.h \
- configfiles.h fixedstringmacros.h mode.h neighbors.h timing.h \
- $(headersdir)/README
+EXTRA_DIST = gnuastro.pc.in data-arithmetic.h data-arithmetic-binary.h \
+ data-arithmetic-onlyint.h data-arithmetic-unary.h data-copy.h \
+ config.h.in checkset.h commonargs.h commonparams.h configfiles.h \
+ fixedstringmacros.h mode.h neighbors.h timing.h $(headersdir)/README
diff --git a/lib/data-arithmetic-onlyint.c b/lib/data-arithmetic-onlyint.c
new file mode 100644
index 0000000..9b247d0
--- /dev/null
+++ b/lib/data-arithmetic-onlyint.c
@@ -0,0 +1,663 @@
+/*********************************************************************
+Arithmetic operations on data structures.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+ Mohammad Akhlaghi <address@hidden>
+Contributing author(s):
+Copyright (C) 2016, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+
+#include <gnuastro/data.h>
+#include <data-arithmetic-onlyint.h>
+
+
+
+/************************************************************************/
+/************* Possibly set onlyint types to convert *************/
+/************************************************************************/
+#if GAL_CONFIG_BIN_OP_UCHAR == 1
+#define ONLYINT_LEFT_RIGHT_DONE_UCHAR(LT, RT, OP) \
+ case GAL_DATA_TYPE_UCHAR: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, unsigned char, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_UCHAR(LT, OP) \
+ case GAL_DATA_TYPE_UCHAR: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, unsigned char, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_UCHAR(OP) \
+ case GAL_DATA_TYPE_UCHAR: \
+ ONLYINT_LEFT_DONE(unsigned char, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_UCHAR(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_UCHAR(LT, OP)
+#define ONLYINT_MULTISWITCH_UCHAR(OP)
+#endif
+
+
+
+
+
+#if GAL_CONFIG_BIN_OP_CHAR == 1
+#define ONLYINT_LEFT_RIGHT_DONE_CHAR(LT, RT, OP) \
+ case GAL_DATA_TYPE_CHAR: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, char, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_CHAR(LT, OP) \
+ case GAL_DATA_TYPE_CHAR: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, char, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_CHAR(OP) \
+ case GAL_DATA_TYPE_CHAR: \
+ ONLYINT_LEFT_DONE(char, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_CHAR(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_CHAR(LT, OP)
+#define ONLYINT_MULTISWITCH_CHAR(OP)
+#endif
+
+
+
+
+
+#if GAL_CONFIG_BIN_OP_USHORT == 1
+#define ONLYINT_LEFT_RIGHT_DONE_USHORT(LT, RT, OP) \
+ case GAL_DATA_TYPE_USHORT: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, unsigned short, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_USHORT(LT, OP) \
+ case GAL_DATA_TYPE_USHORT: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, unsigned short, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_USHORT(OP) \
+ case GAL_DATA_TYPE_USHORT: \
+ ONLYINT_LEFT_DONE(unsigned short, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_USHORT(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_USHORT(LT, OP)
+#define ONLYINT_MULTISWITCH_USHORT(OP)
+#endif
+
+
+
+
+
+#if GAL_CONFIG_BIN_OP_SHORT == 1
+#define ONLYINT_LEFT_RIGHT_DONE_SHORT(LT, RT, OP) \
+ case GAL_DATA_TYPE_SHORT: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, short, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_SHORT(LT, OP) \
+ case GAL_DATA_TYPE_SHORT: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, short, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_SHORT(OP) \
+ case GAL_DATA_TYPE_SHORT: \
+ ONLYINT_LEFT_DONE(short, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_SHORT(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_SHORT(LT, OP)
+#define ONLYINT_MULTISWITCH_SHORT(OP)
+#endif
+
+
+
+
+
+#if GAL_CONFIG_BIN_OP_UINT == 1
+#define ONLYINT_LEFT_RIGHT_DONE_UINT(LT, RT, OP) \
+ case GAL_DATA_TYPE_UINT: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, unsigned int, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_UINT(LT, OP) \
+ case GAL_DATA_TYPE_UINT: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, unsigned int, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_UINT(OP) \
+ case GAL_DATA_TYPE_UINT: \
+ ONLYINT_LEFT_DONE(unsigned int, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_UINT(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_UINT(LT, OP)
+#define ONLYINT_MULTISWITCH_UINT(OP)
+#endif
+
+
+
+
+
+#if GAL_CONFIG_BIN_OP_INT == 1
+#define ONLYINT_LEFT_RIGHT_DONE_INT(LT, RT, OP) \
+ case GAL_DATA_TYPE_INT: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, int, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_INT(LT, OP) \
+ case GAL_DATA_TYPE_INT: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, int, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_INT(OP) \
+ case GAL_DATA_TYPE_INT: \
+ ONLYINT_LEFT_DONE(int, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_INT(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_INT(LT, OP)
+#define ONLYINT_MULTISWITCH_INT(OP)
+#endif
+
+
+
+
+
+#if GAL_CONFIG_BIN_OP_ULONG == 1
+#define ONLYINT_LEFT_RIGHT_DONE_ULONG(LT, RT, OP) \
+ case GAL_DATA_TYPE_ULONG: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, unsigned long, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_ULONG(LT, OP) \
+ case GAL_DATA_TYPE_ULONG: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, unsigned long, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_ULONG(OP) \
+ case GAL_DATA_TYPE_ULONG: \
+ ONLYINT_LEFT_DONE(unsigned long, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_ULONG(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_ULONG(LT, OP)
+#define ONLYINT_MULTISWITCH_ULONG(OP)
+#endif
+
+
+
+
+
+#if GAL_CONFIG_BIN_OP_LONG == 1
+#define ONLYINT_LEFT_RIGHT_DONE_LONG(LT, RT, OP) \
+ case GAL_DATA_TYPE_LONG: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, long, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_LONG(LT, OP) \
+ case GAL_DATA_TYPE_LONG: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, long, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_LONG(OP) \
+ case GAL_DATA_TYPE_LONG: \
+ ONLYINT_LEFT_DONE(long, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_LONG(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_LONG(LT, OP)
+#define ONLYINT_MULTISWITCH_LONG(OP)
+#endif
+
+
+
+
+
+#if GAL_CONFIG_BIN_OP_LONGLONG == 1
+#define ONLYINT_LEFT_RIGHT_DONE_LONGLONG(LT, RT, OP) \
+ case GAL_DATA_TYPE_LONGLONG: \
+ ONLYINT_OPERATOR_FOR_TYPE(LT, RT, LONGLONG, OP); \
+ break;
+#define ONLYINT_LEFT_DONE_LONGLONG(LT, OP) \
+ case GAL_DATA_TYPE_LONGLONG: \
+ ONLYINT_LEFT_RIGHT_DONE(LT, long long, OP); \
+ break;
+#define ONLYINT_MULTISWITCH_LONGLONG(OP) \
+ case GAL_DATA_TYPE_LONGLONG: \
+ ONLYINT_LEFT_DONE(LONGLONG, OP); \
+ break;
+#else
+#define ONLYINT_LEFT_RIGHT_DONE_LONGLONG(LT, RT, OP)
+#define ONLYINT_LEFT_DONE_LONGLONG(LT, OP)
+#define ONLYINT_MULTISWITCH_LONGLONG(OP)
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/************************************************************************/
+/************* Macros for specifying the type *****************/
+/************************************************************************/
+
+#define ONLYINT_OPERATOR_FOR_TYPE(LT, RT, OT, OP){ \
+ LT *la=l->array; \
+ RT *ra=r->array; \
+ OT *oa=o->array, *of=oa + o->size; \
+ if(l->size==r->size) do *oa = *la++ OP *ra++; while(++oa<of); \
+ else if(l->size==1) do *oa = *la OP *ra++; while(++oa<of); \
+ else do *oa = *la++ OP *ra; while(++oa<of); \
+ }
+
+
+
+
+
+#define ONLYINT_LEFT_RIGHT_DONE(LT, RT, OP) \
+ switch(o->type) \
+ { \
+ \
+ ONLYINT_LEFT_RIGHT_DONE_UCHAR(LT, RT, OP); \
+ ONLYINT_LEFT_RIGHT_DONE_CHAR(LT, RT, OP); \
+ ONLYINT_LEFT_RIGHT_DONE_SHORT(LT, RT, OP); \
+ ONLYINT_LEFT_RIGHT_DONE_USHORT(LT, RT, OP); \
+ ONLYINT_LEFT_RIGHT_DONE_INT(LT, RT, OP); \
+ ONLYINT_LEFT_RIGHT_DONE_UINT(LT, RT, OP); \
+ ONLYINT_LEFT_RIGHT_DONE_ULONG(LT, RT, OP); \
+ ONLYINT_LEFT_RIGHT_DONE_LONG(LT, RT, OP); \
+ ONLYINT_LEFT_RIGHT_DONE_LONGLONG(LT, RT, OP); \
+ \
+ default: \
+ error(EXIT_FAILURE, 0, "type %d not recognized in " \
+ "for o->type in ONLYINT_LEFT_RIGHT_DONE", o->type); \
+ }
+
+
+
+
+
+#define ONLYINT_LEFT_DONE(LT, OP) \
+ switch(r->type) \
+ { \
+ \
+ ONLYINT_LEFT_DONE_UCHAR(LT, OP); \
+ ONLYINT_LEFT_DONE_CHAR(LT, OP); \
+ ONLYINT_LEFT_DONE_USHORT(LT, OP); \
+ ONLYINT_LEFT_DONE_SHORT(LT, OP); \
+ ONLYINT_LEFT_DONE_UINT(LT, OP); \
+ ONLYINT_LEFT_DONE_INT(LT, OP); \
+ ONLYINT_LEFT_DONE_ULONG(LT, OP); \
+ ONLYINT_LEFT_DONE_LONG(LT, OP); \
+ ONLYINT_LEFT_DONE_LONGLONG(LT, OP); \
+ \
+ default: \
+ error(EXIT_FAILURE, 0, "type %d not recognized in " \
+ "for r->type in ONLYINT_LEFT_DONE", r->type); \
+ }
+
+
+
+
+
+#define ONLYINT_OPERATOR_DONE(OP) \
+ switch(l->type) \
+ { \
+ \
+ ONLYINT_MULTISWITCH_UCHAR(OP); \
+ ONLYINT_MULTISWITCH_CHAR(OP); \
+ ONLYINT_MULTISWITCH_USHORT(OP); \
+ ONLYINT_MULTISWITCH_SHORT(OP); \
+ ONLYINT_MULTISWITCH_UINT(OP); \
+ ONLYINT_MULTISWITCH_INT(OP); \
+ ONLYINT_MULTISWITCH_ULONG(OP); \
+ ONLYINT_MULTISWITCH_LONG(OP); \
+ ONLYINT_MULTISWITCH_LONGLONG(OP); \
+ \
+ default: \
+ error(EXIT_FAILURE, 0, "type %d not recognized in " \
+ "for l->type in data_arithmetic_onlyint", l->type); \
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/********************************************************************/
+/**************** Intermediate functions ***************/
+/********************************************************************/
+static int
+onlyint_type_for_convert_to_compiled_type(int intype)
+{
+ switch(intype)
+ {
+ case GAL_DATA_TYPE_UCHAR:
+ if(GAL_CONFIG_BIN_OP_UCHAR) return GAL_DATA_TYPE_UCHAR;
+ else
+ {
+ if (GAL_CONFIG_BIN_OP_USHORT) return GAL_DATA_TYPE_USHORT;
+ else if(GAL_CONFIG_BIN_OP_SHORT) return GAL_DATA_TYPE_SHORT;
+ else if(GAL_CONFIG_BIN_OP_UINT) return GAL_DATA_TYPE_UINT;
+ else if(GAL_CONFIG_BIN_OP_INT) return GAL_DATA_TYPE_INT;
+ else if(GAL_CONFIG_BIN_OP_ULONG) return GAL_DATA_TYPE_ULONG;
+ else if(GAL_CONFIG_BIN_OP_LONG) return GAL_DATA_TYPE_LONG;
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ }
+ break;
+
+ case GAL_DATA_TYPE_CHAR:
+ if(GAL_CONFIG_BIN_OP_CHAR) return GAL_DATA_TYPE_CHAR;
+ else
+ {
+ if (GAL_CONFIG_BIN_OP_SHORT) return GAL_DATA_TYPE_SHORT;
+ else if(GAL_CONFIG_BIN_OP_INT) return GAL_DATA_TYPE_INT;
+ else if(GAL_CONFIG_BIN_OP_LONG) return GAL_DATA_TYPE_LONG;
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ }
+ break;
+
+ case GAL_DATA_TYPE_USHORT:
+ if(GAL_CONFIG_BIN_OP_USHORT) return GAL_DATA_TYPE_USHORT;
+ else
+ {
+ if (GAL_CONFIG_BIN_OP_UINT) return GAL_DATA_TYPE_UINT;
+ else if(GAL_CONFIG_BIN_OP_INT) return GAL_DATA_TYPE_INT;
+ else if(GAL_CONFIG_BIN_OP_ULONG) return GAL_DATA_TYPE_ULONG;
+ else if(GAL_CONFIG_BIN_OP_LONG) return GAL_DATA_TYPE_LONG;
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ }
+ break;
+
+ case GAL_DATA_TYPE_SHORT:
+ if(GAL_CONFIG_BIN_OP_SHORT) return GAL_DATA_TYPE_SHORT;
+ else
+ {
+ if (GAL_CONFIG_BIN_OP_INT) return GAL_DATA_TYPE_INT;
+ else if(GAL_CONFIG_BIN_OP_LONG) return GAL_DATA_TYPE_LONG;
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ }
+ break;
+
+ case GAL_DATA_TYPE_UINT:
+ if(GAL_CONFIG_BIN_OP_UINT) return GAL_DATA_TYPE_UINT;
+ else
+ {
+ if (GAL_CONFIG_BIN_OP_ULONG) return GAL_DATA_TYPE_ULONG;
+ else if(GAL_CONFIG_BIN_OP_LONG) return GAL_DATA_TYPE_LONG;
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ }
+ break;
+
+ case GAL_DATA_TYPE_INT:
+ if(GAL_CONFIG_BIN_OP_INT) return GAL_DATA_TYPE_INT;
+ else
+ {
+ if (GAL_CONFIG_BIN_OP_LONG) return GAL_DATA_TYPE_LONG;
+ else if(GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ }
+ break;
+
+ case GAL_DATA_TYPE_ULONG:
+ if(GAL_CONFIG_BIN_OP_ULONG) return GAL_DATA_TYPE_ULONG;
+ else
+ {
+ if (GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ }
+ break;
+
+ case GAL_DATA_TYPE_LONG:
+ if(GAL_CONFIG_BIN_OP_LONG) return GAL_DATA_TYPE_LONG;
+ else
+ {
+ if (GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ }
+ break;
+
+ case GAL_DATA_TYPE_LONGLONG:
+ if(GAL_CONFIG_BIN_OP_LONGLONG) return GAL_DATA_TYPE_LONGLONG;
+ break;
+
+ default:
+ error(EXIT_FAILURE, 0, "type %d not recognized in "
+ "ONLYINT_CONVERT_TO_COMPILED_TYPE (note that onlyint "
+ "operators only accept integer types)", intype);
+ }
+
+ return 0;
+}
+
+
+
+
+
+/* Note that for signed types, we won't be considering the unsigned types
+ of the larger types. */
+gal_data_t *
+onlyint_convert_to_compiled_type(gal_data_t *in, unsigned char flags)
+{
+ int ntype;
+ char *typestring;
+ gal_data_t *out=NULL;
+
+ /* Set the best compiled type. */
+ ntype=onlyint_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
+ {
+ typestring=gal_data_type_string(in->type);
+ error(EXIT_FAILURE, 0, "The given %s type data given to "
+ "onlyint 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);
+ }
+ }
+
+ /* Return the output data structure */
+ if(out==NULL)
+ error(EXIT_FAILURE, 0, "A bug! Please contact us at %s, so we can fix "
+ "the problem. For some reason, the `out' array in "
+ "`onlyint_convert_to_compiled_type' is not set", PACKAGE_BUGREPORT);
+ return out;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/************************************************************************/
+/************* Top level function *****************/
+/************************************************************************/
+gal_data_t *
+data_arithmetic_onlyint_binary(int operator, unsigned char flags,
+ gal_data_t *lo, gal_data_t *ro)
+{
+ /* Read the variable arguments. `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;
+ gal_data_t *l, *r, *o=NULL, *tmp_o;
+ int out_type=0, otype, final_otype;
+
+
+ /* Simple sanity check on the input sizes */
+ if( !( (flags & GAL_DATA_ARITH_NUMOK) && (lo->size==1 || ro->size==1))
+ && gal_data_dsize_is_different(lo, ro) )
+ error(EXIT_FAILURE, 0, "ini ONLYINT_INTERNAL, the input datasets "
+ "don't have the same dimension/size");
+
+
+ /* Make sure the input arrays have one of the compiled types. */
+ l=onlyint_convert_to_compiled_type(lo, flags);
+ r=onlyint_convert_to_compiled_type(ro, flags);
+
+
+ /* For the left/right shift bitwise operators, the length of the integer
+ matters. So if the lengths of the inputs have changed with these two
+ operators, then print a warning. */
+ if(operator==GAL_DATA_OPERATOR_BITLSH || GAL_DATA_OPERATOR_BITRSH)
+ if(lo->type!=l->type || ro->type!=r->type)
+ error(EXIT_FAILURE, 0, "at least one of the input types to the bitwise "
+ "left or right shift operators was not compiled. The result "
+ "will thus not be what is expected. To configure Gnuastro with "
+ "the respective type, use the following options at configure "
+ "time: `--enable-bin-op-TYPE', run `./configure --help' to see "
+ "the full list.");
+
+
+ /* Set the output type. By default, `out_type' is initialized to zero,
+ this means that the type of the output data structure will be
+ determined based on the inputs. However, for the comparison operators,
+ the output type is either 0 or 1, so we will set the output to
+ unsigned character to save space and memory. Note that since this
+ switch check, is only relevant for certain operators, we don't need a
+ `default' statement.*/
+ final_otype = out_type ? out_type : gal_data_out_type(lo, ro);
+ otype=onlyint_type_for_convert_to_compiled_type(final_otype);
+
+
+ /* Set the output sizes. */
+ minmapsize = ( lo->minmapsize < ro->minmapsize
+ ? lo->minmapsize : ro->minmapsize );
+ out_size = lo->size > ro->size ? lo->size : ro->size;
+
+
+ /* 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==otype && out_size==l->size) o = l;
+ else if(r->type==otype && out_size==r->size) o = r;
+ }
+
+
+ /* If the output pointer was not set for any reason, allocate it. For
+ `mmapsize', note that since its `size_t', it will always be
+ Positive. The `-1' that is recommended to give when you want the value
+ in RAM is actually the largest possible memory location. 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, otype,
+ l->size>1 ? l->ndim : r->ndim,
+ l->size>1 ? l->dsize : r->dsize,
+ l->size>1 ? l->wcs : r->wcs, 0, minmapsize );
+
+
+ /* Start setting the operator and operands. */
+ switch(operator)
+ {
+ case GAL_DATA_OPERATOR_MODULO: ONLYINT_OPERATOR_DONE( % ); break;
+ case GAL_DATA_OPERATOR_BITAND: ONLYINT_OPERATOR_DONE( & ); break;
+ case GAL_DATA_OPERATOR_BITOR: ONLYINT_OPERATOR_DONE( | ); break;
+ case GAL_DATA_OPERATOR_BITXOR: ONLYINT_OPERATOR_DONE( ^ ); break;
+ case GAL_DATA_OPERATOR_BITLSH: ONLYINT_OPERATOR_DONE( << ); break;
+ case GAL_DATA_OPERATOR_BITRSH: ONLYINT_OPERATOR_DONE( >> ); break;
+ default:
+ error(EXIT_FAILURE, 0, "Operator code %d not recognized in "
+ "data_arithmetic_onlyint when preparing for the operation",
+ operator);
+ }
+
+
+ /* Clean up. Note that if the input arrays can be freed, and any of right
+ or left arrays needed conversion, `ONLYINT_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 onlyint 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;
+ }
+
+ /* Return */
+ return o;
+}
diff --git a/lib/data-arithmetic-onlyint.h b/lib/data-arithmetic-onlyint.h
new file mode 100644
index 0000000..afe255e
--- /dev/null
+++ b/lib/data-arithmetic-onlyint.h
@@ -0,0 +1,32 @@
+/*********************************************************************
+Arithmetic operations on data structures.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+ Mohammad Akhlaghi <address@hidden>
+Contributing author(s):
+Copyright (C) 2015, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#ifndef __GAL_ARITHMETIC_ONLYINT_H__
+#define __GAL_ARITHMETIC_ONLYINT_H__
+
+
+gal_data_t *
+data_arithmetic_onlyint_binary(int operator, unsigned char flags,
+ gal_data_t *lo, gal_data_t *ro);
+
+
+#endif
diff --git a/lib/data-arithmetic-unary.c b/lib/data-arithmetic-unary.c
new file mode 100644
index 0000000..2ffbd7e
--- /dev/null
+++ b/lib/data-arithmetic-unary.c
@@ -0,0 +1,100 @@
+/*********************************************************************
+Arithmetic operations on data structures.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+ Mohammad Akhlaghi <address@hidden>
+Contributing author(s):
+Copyright (C) 2016, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+
+#include <gnuastro/data.h>
+
+
+
+
+/* Return an array of value 1 for any zero valued element and zero for any
+ non-zero valued element. */
+#define TYPE_CASE_FOR_NOT(TYPE, IN, IN_FINISH) { \
+ case TYPE: \
+ do *o++ = !*IN; while(++IN<IN_FINISH); \
+ break; \
+ }
+
+gal_data_t *
+data_arithmetic_not(gal_data_t *data)
+{
+ gal_data_t *out;
+
+ /* 'value' will only be read from one of these based on the
+ datatype. Which the caller assigned. If there is any problem, it is
+ their responsability, not this function's.*/
+ void *A=data->array;
+ size_t S=data->size;
+ unsigned char *uc = A, *ucf = A+S, *o;
+ char *c = A, *cf = A+S;
+ unsigned short *us = A, *usf = A+S;
+ short *s = A, *sf = A+S;
+ unsigned int *ui = A, *uif = A+S;
+ int *in = A, *inf = A+S;
+ unsigned long *ul = A, *ulf = A+S;
+ long *l = A, *lf = A+S;
+ LONGLONG *L = A, *Lf = A+S;
+ float *f = A, *ff = A+S;
+ double *d = A, *df = A+S;
+
+
+ /* Allocate the output array. */
+ out=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, data->ndim, data->dsize,
+ data->wcs, 0, data->minmapsize);
+ o=out->array;
+
+
+ /* Go over the pixels and set the output values. */
+ switch(data->type)
+ {
+
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_UCHAR, uc, ucf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_CHAR, c, cf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_LOGICAL, c, cf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_USHORT, us, usf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_SHORT, s, sf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_UINT, ui, uif)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_INT, in, inf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_ULONG, ul, ulf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_LONG, l, lf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_LONGLONG, L, Lf)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_FLOAT, f, ff)
+ TYPE_CASE_FOR_NOT(GAL_DATA_TYPE_DOUBLE, d, df)
+
+ case GAL_DATA_TYPE_BIT:
+ error(EXIT_FAILURE, 0, "Currently Gnuastro doesn't support bit "
+ "datatype, please get in touch with us to implement it.");
+
+ default:
+ error(EXIT_FAILURE, 0, "type value (%d) not recognized "
+ "in `data_arithmetic_not'", data->type);
+ }
+
+ /* Return */
+ return out;
+}
diff --git a/lib/data-arithmetic-unary.h b/lib/data-arithmetic-unary.h
new file mode 100644
index 0000000..50954f0
--- /dev/null
+++ b/lib/data-arithmetic-unary.h
@@ -0,0 +1,31 @@
+/*********************************************************************
+Arithmetic operations on data structures.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+ Mohammad Akhlaghi <address@hidden>
+Contributing author(s):
+Copyright (C) 2015, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#ifndef __GAL_ARITHMETIC_UNARY_H__
+#define __GAL_ARITHMETIC_UNARY_H__
+
+
+gal_data_t *
+data_arithmetic_not(gal_data_t *data);
+
+
+#endif
diff --git a/lib/data.c b/lib/data.c
index 0b21222..86bf0d1 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -38,7 +38,9 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <checkset.h>
#include <data-copy.h>
+#include <data-arithmetic-unary.h>
#include <data-arithmetic-binary.h>
+#include <data-arithmetic-onlyint.h>
@@ -861,6 +863,307 @@ gal_data_blank_to_value(gal_data_t *data, void *value)
+/* Return 1 if the dataset has a blank value and zero if it doesn't. */
+int
+gal_data_has_blank(gal_data_t *data)
+{
+ /* 'value' will only be read from one of these based on the
+ datatype. Which the caller assigned. If there is any problem, it is
+ their responsability, not this function's.*/
+ void *A=data->array;
+ size_t S=data->size;
+ unsigned char *uc = A, *ucf = A+S;
+ char *c = A, *cf = A+S;
+ char **str = A, **strf = A+S;
+ unsigned short *us = A, *usf = A+S;
+ short *s = A, *sf = A+S;
+ unsigned int *ui = A, *uif = A+S;
+ int *in = A, *inf = A+S;
+ unsigned long *ul = A, *ulf = A+S;
+ long *l = A, *lf = A+S;
+ LONGLONG *L = A, *Lf = A+S;
+ float *f = A, *ff = A+S;
+ double *d = A, *df = A+S;
+ gsl_complex_float *cx = A, *cxf = A+S;
+ gsl_complex *dcx = A, *dcxf = A+S;
+
+
+ /* Go over the pixels and check: */
+ switch(data->type)
+ {
+ case GAL_DATA_TYPE_BIT:
+ error(EXIT_FAILURE, 0, "Currently Gnuastro doesn't support bit "
+ "datatype, please get in touch with us to implement it.");
+
+ case GAL_DATA_TYPE_UCHAR:
+ do if(*uc==GAL_DATA_BLANK_UCHAR) return 1; while(uc<ucf);
+ break;
+
+
+ case GAL_DATA_TYPE_CHAR: case GAL_DATA_TYPE_LOGICAL:
+ do if(*c++==GAL_DATA_BLANK_CHAR) return 1; while(c<cf);
+ break;
+
+
+ case GAL_DATA_TYPE_STRING:
+ do if(*str++==GAL_DATA_BLANK_STRING) return 1; while(str<strf);
+ break;
+
+
+ case GAL_DATA_TYPE_USHORT:
+ do if(*us++==GAL_DATA_BLANK_USHORT) return 1; while(us<usf);
+ break;
+
+
+ case GAL_DATA_TYPE_SHORT:
+ do if(*s++==GAL_DATA_BLANK_SHORT) return 1; while(s<sf);
+ break;
+
+
+ case GAL_DATA_TYPE_UINT:
+ do if(*ui++==GAL_DATA_BLANK_UINT) return 1; while(ui<uif);
+ break;
+
+
+ case GAL_DATA_TYPE_INT:
+ do if(*in++==GAL_DATA_BLANK_INT) return 1; while(in<inf);
+ break;
+
+
+ case GAL_DATA_TYPE_ULONG:
+ do if(*ul++==GAL_DATA_BLANK_ULONG) return 1; while(ul<ulf);
+ break;
+
+
+ case GAL_DATA_TYPE_LONG:
+ do if(*l++==GAL_DATA_BLANK_LONG) return 1; while(l<lf);
+ break;
+
+
+ case GAL_DATA_TYPE_LONGLONG:
+ do if(*L++==GAL_DATA_BLANK_LONGLONG) return 1; while(L<Lf);
+ break;
+
+
+ /* Note that a NaN value is not equal to another NaN value, so we
+ can't use the easy check for cases were the blank value is
+ NaN. Also note that `isnan' is actually a macro, so it works for
+ both float and double types.*/
+ case GAL_DATA_TYPE_FLOAT:
+ if(isnan(GAL_DATA_BLANK_FLOAT))
+ do if(isnan(*f++)) return 1; while(f<ff);
+ else
+ do if(*f++==GAL_DATA_BLANK_FLOAT) return 1; while(f<ff);
+ break;
+
+
+ case GAL_DATA_TYPE_DOUBLE:
+ if(isnan(GAL_DATA_BLANK_DOUBLE))
+ do if(isnan(*d++)) return 1; while(d<df);
+ else
+ do if(*d++==GAL_DATA_BLANK_FLOAT) return 1; while(d<df);
+ break;
+
+
+ case GAL_DATA_TYPE_COMPLEX:
+ if(isnan(GAL_DATA_BLANK_FLOAT))
+ do
+ if(isnan(GSL_COMPLEX_P_REAL(cx))
+ && isnan(GSL_COMPLEX_P_IMAG(cx)) )
+ return 1;
+ while(++cx<cxf);
+ else
+ do
+ if( GSL_COMPLEX_P_REAL(cx) == GAL_DATA_BLANK_FLOAT
+ && GSL_COMPLEX_P_IMAG(cx) == GAL_DATA_BLANK_FLOAT)
+ return 1;
+ while(++cx<cxf);
+ break;
+
+
+ case GAL_DATA_TYPE_DCOMPLEX:
+ if(isnan(GAL_DATA_BLANK_DOUBLE))
+ do
+ if(isnan(GSL_COMPLEX_P_REAL(dcx))
+ && isnan(GSL_COMPLEX_P_IMAG(dcx)) )
+ return 1;
+ while(++dcx<dcxf);
+ else
+ do
+ if( GSL_COMPLEX_P_REAL(dcx) == GAL_DATA_BLANK_FLOAT
+ && GSL_COMPLEX_P_IMAG(dcx) == GAL_DATA_BLANK_FLOAT)
+ return 1;
+ while(++dcx<dcxf);
+ break;
+
+
+ default:
+ error(EXIT_FAILURE, 0, "a bug! type value (%d) not recognized "
+ "in `gal_data_blank_to_value'", data->type);
+ }
+
+ /* If there was a blank value, then the function would have returned with
+ a value of 1. So if it reaches here, then we can be sure that there
+ was no blank values, hence, return 0. */
+ return 0;
+}
+
+
+
+
+
+/* Output a data-set of the the same size as the input, but with an
+ unsigned character type that has a value of 1 for data that are blank
+ and 0 for those that aren't. */
+gal_data_t *
+gal_data_flag_blank(gal_data_t *data)
+{
+ gal_data_t *out;
+
+ /* 'value' will only be read from one of these based on the
+ datatype. Which the caller assigned. If there is any problem, it is
+ their responsability, not this function's.*/
+ void *A=data->array;
+ size_t S=data->size;
+ unsigned char *uc = A, *ucf = A+S, *o;
+ char *c = A, *cf = A+S;
+ char **str = A, **strf = A+S;
+ unsigned short *us = A, *usf = A+S;
+ short *s = A, *sf = A+S;
+ unsigned int *ui = A, *uif = A+S;
+ int *in = A, *inf = A+S;
+ unsigned long *ul = A, *ulf = A+S;
+ long *l = A, *lf = A+S;
+ LONGLONG *L = A, *Lf = A+S;
+ float *f = A, *ff = A+S;
+ double *d = A, *df = A+S;
+ gsl_complex_float *cx = A, *cxf = A+S;
+ gsl_complex *dcx = A, *dcxf = A+S;
+
+
+ /* Allocate the output array. */
+ out=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, data->ndim, data->dsize,
+ data->wcs, 0, data->minmapsize);
+ o=out->array;
+
+
+ /* Go over the pixels and set the output values. */
+ switch(data->type)
+ {
+ case GAL_DATA_TYPE_BIT:
+ error(EXIT_FAILURE, 0, "Currently Gnuastro doesn't support bit "
+ "datatype, please get in touch with us to implement it.");
+
+ case GAL_DATA_TYPE_UCHAR:
+ do *o++ = *uc==GAL_DATA_BLANK_UCHAR; while(++uc<ucf);
+ break;
+
+
+ case GAL_DATA_TYPE_CHAR: case GAL_DATA_TYPE_LOGICAL:
+ do *o++ = *c==GAL_DATA_BLANK_CHAR; while(++c<cf);
+ break;
+
+
+ case GAL_DATA_TYPE_STRING:
+ do *o++ = *str==GAL_DATA_BLANK_STRING; while(++str<strf);
+ break;
+
+
+ case GAL_DATA_TYPE_USHORT:
+ do *o++ = *us==GAL_DATA_BLANK_USHORT; while(++us<usf);
+ break;
+
+
+ case GAL_DATA_TYPE_SHORT:
+ do *o++ = *s==GAL_DATA_BLANK_SHORT; while(++s<sf);
+ break;
+
+
+ case GAL_DATA_TYPE_UINT:
+ do *o++ = *ui==GAL_DATA_BLANK_UINT; while(++ui<uif);
+ break;
+
+
+ case GAL_DATA_TYPE_INT:
+ do *o++ = *in==GAL_DATA_BLANK_INT; while(++in<inf);
+ break;
+
+
+ case GAL_DATA_TYPE_ULONG:
+ do *o++ = *ul==GAL_DATA_BLANK_ULONG; while(++ul<ulf);
+ break;
+
+
+ case GAL_DATA_TYPE_LONG:
+ do *o++ = *l==GAL_DATA_BLANK_LONG; while(++l<lf);
+ break;
+
+
+ case GAL_DATA_TYPE_LONGLONG:
+ do *o++ = *L==GAL_DATA_BLANK_LONGLONG; while(++L<Lf);
+ break;
+
+
+ /* Note that a NaN value is not equal to another NaN value, so we
+ can't use the easy check for cases were the blank value is
+ NaN. Also note that `isnan' is actually a macro, so it works for
+ both float and double types.*/
+ case GAL_DATA_TYPE_FLOAT:
+ if(isnan(GAL_DATA_BLANK_FLOAT))
+ do *o++ = isnan(*f); while(++f<ff);
+ else
+ do *o++ = *f==GAL_DATA_BLANK_FLOAT; while(++f<ff);
+ break;
+
+
+ case GAL_DATA_TYPE_DOUBLE:
+ if(isnan(GAL_DATA_BLANK_DOUBLE))
+ do *o++ = isnan(*d); while(++d<df);
+ else
+ do *o++ = *d==GAL_DATA_BLANK_DOUBLE; while(++d<df);
+ break;
+
+
+ case GAL_DATA_TYPE_COMPLEX:
+ if(isnan(GAL_DATA_BLANK_FLOAT))
+ do
+ *o++ = ( isnan(GSL_COMPLEX_P_REAL(cx))
+ && isnan(GSL_COMPLEX_P_IMAG(cx)) );
+ while(++cx<cxf);
+ else
+ do
+ *o++ = ( GSL_COMPLEX_P_REAL(cx) == GAL_DATA_BLANK_FLOAT
+ && GSL_COMPLEX_P_IMAG(cx) == GAL_DATA_BLANK_FLOAT );
+ while(++cx<cxf);
+ break;
+
+
+ case GAL_DATA_TYPE_DCOMPLEX:
+ if(isnan(GAL_DATA_BLANK_DOUBLE))
+ do
+ *o++ = ( isnan(GSL_COMPLEX_P_REAL(dcx))
+ && isnan(GSL_COMPLEX_P_IMAG(dcx)) );
+ while(++dcx<dcxf);
+ else
+ do
+ *o++ = ( GSL_COMPLEX_P_REAL(dcx) == GAL_DATA_BLANK_FLOAT
+ && GSL_COMPLEX_P_IMAG(dcx) == GAL_DATA_BLANK_FLOAT );
+ while(++dcx<dcxf);
+ break;
+
+
+ default:
+ error(EXIT_FAILURE, 0, "type value (%d) not recognized "
+ "in `gal_data_flag_blank'", data->type);
+ }
+
+ /* Return */
+ return out;
+}
+
+
+
+
@@ -1150,11 +1453,12 @@ gal_data_arithmetic(int operator, unsigned char flags,
...)
/* Depending on the operator do the job: */
switch(operator)
{
- /* If we have an ordinary (not bitwise) binary operator: */
+ /* Binary operators with any data type. */
case GAL_DATA_OPERATOR_PLUS:
case GAL_DATA_OPERATOR_MINUS:
case GAL_DATA_OPERATOR_MULTIPLY:
case GAL_DATA_OPERATOR_DIVIDE:
+ case GAL_DATA_OPERATOR_MODULO:
case GAL_DATA_OPERATOR_LT:
case GAL_DATA_OPERATOR_LE:
case GAL_DATA_OPERATOR_GT:
@@ -1163,12 +1467,36 @@ gal_data_arithmetic(int operator, unsigned char flags,
...)
case GAL_DATA_OPERATOR_NE:
case GAL_DATA_OPERATOR_AND:
case GAL_DATA_OPERATOR_OR:
- /* Prepare original data structures from the input arguments. */
d1 = va_arg(va, gal_data_t *);
d2 = va_arg(va, gal_data_t *);
out=data_arithmetic_binary(operator, flags, d1, d2);
break;
+ case GAL_DATA_OPERATOR_NOT:
+ d1 = va_arg(va, gal_data_t *);
+ out=data_arithmetic_not(d1);
+ break;
+
+ /* Binary operators that only work on integer types. */
+ case GAL_DATA_OPERATOR_BITAND:
+ case GAL_DATA_OPERATOR_BITOR:
+ case GAL_DATA_OPERATOR_BITXOR:
+ case GAL_DATA_OPERATOR_BITLSH:
+ case GAL_DATA_OPERATOR_BITRSH:
+ d1 = va_arg(va, gal_data_t *);
+ d2 = va_arg(va, gal_data_t *);
+ out=data_arithmetic_onlyint_binary(operator, flags, d1, d2);
+ break;
+
+ /* Ones component (bitwise) operator.*/
+
+ case GAL_DATA_OPERATOR_ISBLANK:
+ d1 = va_arg(va, gal_data_t *);
+ out = gal_data_flag_blank(d1);
+ if(flags & GAL_DATA_ARITH_FREE)
+ gal_data_free(d1);
+
+
#if 0
else if(!strcmp(operator, "abs")) takeabs(p);
@@ -1183,7 +1511,6 @@ gal_data_arithmetic(int operator, unsigned char flags,
...)
|| !strcmp(operator, "average")
|| !strcmp(operator, "median")) alloppixs(p, operator);
else if(!strcmp(operator, "not")) notfunc(p);
- else if(!strcmp(operator, "isblank")) opisblank(p);
else if(!strcmp(operator, "where")) where(p);
#endif
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index 3298f9f..b8c0a61 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -136,6 +136,7 @@ enum gal_data_operators
GAL_DATA_OPERATOR_MINUS, /* - */
GAL_DATA_OPERATOR_MULTIPLY, /* * */
GAL_DATA_OPERATOR_DIVIDE, /* / */
+ GAL_DATA_OPERATOR_MODULO, /* % */
GAL_DATA_OPERATOR_LT, /* < */
GAL_DATA_OPERATOR_LE, /* <= */
@@ -148,6 +149,10 @@ enum gal_data_operators
GAL_DATA_OPERATOR_BITAND, /* & */
GAL_DATA_OPERATOR_BITOR, /* | */
+ GAL_DATA_OPERATOR_BITXOR, /* ^ */
+ GAL_DATA_OPERATOR_BITLSH, /* << */
+ GAL_DATA_OPERATOR_BITRSH, /* >> */
+ GAL_DATA_OPERATOR_BITOCM, /* ~ */
GAL_DATA_OPERATOR_NOT, /* ! */
GAL_DATA_OPERATOR_ISBLANK, /* Similar to isnan() for floats. */
@@ -246,6 +251,12 @@ gal_data_apply_mask(gal_data_t *in, gal_data_t *mask);
void
gal_data_blank_to_value(gal_data_t *data, void *value);
+int
+gal_data_has_blank(gal_data_t *data);
+
+gal_data_t *
+gal_data_flag_blank(gal_data_t *data);
+
- [gnuastro-commits] master c6462d1 016/125: Type conversion operators in Arithmetic, (continued)
- [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, 2017/04/23
- [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 <=
- [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
- [gnuastro-commits] master ce73959 030/125: Reading FITS keywords into linked list not array, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master e0e8679 017/125: Removed `anyblank' from datastructure, several new operators, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 6d68470 033/125: Column info format for writing ASCII tables, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 0fd75fe 040/125: With no columns, Table program will print all columns, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 8090e6d 038/125: Corrections to FITS table reading, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 1156793 035/125: ASCII table information fully ready for selection, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 3c7773f 037/125: Table library prints ASCII columns with blanks, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 1dca684 047/125: Minor corrections to Gnuastro plain text table format, Mohammad Akhlaghi, 2017/04/23