gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 531c263 008/125: Operators treated as macros,


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 531c263 008/125: Operators treated as macros, not string
Date: Sun, 23 Apr 2017 22:36:25 -0400 (EDT)

branch: master
commit 531c2636bf0ffc9bbe003fc322b36aed12fcae2c
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Operators treated as macros, not string
    
    The different operators are now recorgnized as macros in
    `gal_data_arithmetic'. Until now, they were treated as strings which made
    it a little slow and hard to generalize.
    
    Also the `!=' operator is now called `ne' in Arithmetic, until now it was
    called `neq'. This follows the names of the comparison operators in the
    shell.
---
 bin/arithmetic/args.h       |  2 +-
 bin/arithmetic/arithmetic.c | 97 ++++++++++++++++++++++++++++++++++++++++-----
 doc/gnuastro.texi           |  2 +-
 lib/data-arithmetic.h       | 94 +++++++++++++++++++++----------------------
 lib/data.c                  | 39 ++++++++++--------
 lib/gnuastro/data.h         | 44 +++++++++++++++++++-
 6 files changed, 198 insertions(+), 80 deletions(-)

diff --git a/bin/arithmetic/args.h b/bin/arithmetic/args.h
index 2be11b8..c9bf2a9 100644
--- a/bin/arithmetic/args.h
+++ b/bin/arithmetic/args.h
@@ -69,7 +69,7 @@ const char doc[] =
   "Please see the manual for more information. "
   "\n\nThe operators/functions recognized by "SPACK_NAME" are: +, -, *, /, "
   "abs, pow, sqrt, log, log10, minvalue, maxvalue, min, max, average, median, "
-  "lt, le, gt, ge, eq, neq, and, or, not, isblank. Please run `info gnuastro "
+  "lt, le, gt, ge, eq, ne, and, or, not, isblank. Please run `info gnuastro "
   "\"Arithmetic operators\"' for detailed information on each operator. Note "
   "that multiplication should be quoted (like \"*\", or '*') to avoid shell "
   "expansion.\n"
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index ec457f3..d9e5919 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -67,6 +67,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 void
 reversepolish(struct imgarithparams *p)
 {
+  int op=0, nop=0;
   struct gal_linkedlist_stll *token;
   gal_data_t *d1=NULL, *d2=NULL, *d3=NULL;
   unsigned char flags = ( GAL_DATA_ARITH_INPLACE | GAL_DATA_ARITH_FREE
@@ -90,20 +91,96 @@ reversepolish(struct imgarithparams *p)
         add_operand(p, NULL, d1);
       else
         {
-          /* Note that the first popped operand is the right/second given
-             operand on the command-line. */
-          if( !strcmp(token->v, "+") || !strcmp(token->v, "-")
-              || !strcmp(token->v, "*") || !strcmp(token->v, "/") )
-            {
-              d2=pop_operand(p, token->v);
-              d1=pop_operand(p, token->v);
-            }
+          if      (!strcmp(token->v, "+" ))
+            { op=GAL_DATA_OPERATOR_PLUS;          nop=2;  }
+          else if (!strcmp(token->v, "-" ))
+            { op=GAL_DATA_OPERATOR_MINUS;         nop=2;  }
+          else if (!strcmp(token->v, "*" ))
+            { op=GAL_DATA_OPERATOR_MULTIPLY;      nop=2;  }
+          else if (!strcmp(token->v, "/" ))
+            { op=GAL_DATA_OPERATOR_DIVIDE;        nop=2;  }
+
+          else if (!strcmp(token->v, "lt" ))
+            { op=GAL_DATA_OPERATOR_LT;            nop=2;  }
+          else if (!strcmp(token->v, "le"))
+            { op=GAL_DATA_OPERATOR_LE;            nop=2;  }
+          else if (!strcmp(token->v, "gt" ))
+            { op=GAL_DATA_OPERATOR_GT;            nop=2;  }
+          else if (!strcmp(token->v, "ge"))
+            { op=GAL_DATA_OPERATOR_LE;            nop=2;  }
+          else if (!strcmp(token->v, "eq"))
+            { op=GAL_DATA_OPERATOR_EQ;            nop=2;  }
+          else if (!strcmp(token->v, "ne"))
+            { op=GAL_DATA_OPERATOR_NE;            nop=2;  }
+          else if (!strcmp(token->v, "and"))
+            { 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"))
+            { op=GAL_DATA_OPERATOR_ISBLANK;       nop=1;  }
+          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;  }
+
+          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",
                   token->v);
-          add_operand(p, NULL,
-                      gal_data_arithmetic(token->v, flags, d1, d2, d3));
+
+          /* Pop the necessary number of operators. */
+          if(nop==1)
+            d1=pop_operand(p, token->v);
+          else if(nop==2)
+          {
+            d2=pop_operand(p, token->v);
+            d1=pop_operand(p, token->v);
+          }
+          else if(nop==3)
+          {
+            d3=pop_operand(p, token->v);
+            d2=pop_operand(p, token->v);
+            d1=pop_operand(p, token->v);
+          }
+          else if(nop==-1)
+            /* It might be possible to add a `next' pointer to the data
+               structure so it can act like a linked list too. In that
+               case, t */
+            error(EXIT_FAILURE, 0, "Operators with an unknown number of "
+                  "operands are not yet implemented.");
+          else
+            error(EXIT_FAILURE, 0, "No operators need %d operands", nop);
+
+          /* Do the arithemtic operation. */
+          add_operand(p, NULL, gal_data_arithmetic(op, flags, d1, d2, d3));
         }
     }
 
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 28b6d2b..0487a20 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -7183,7 +7183,7 @@ Equality: similar to @code{lt} (`less than' operator), 
but returning 1 when
 the two popped operands are equal (to double precision floating point
 accuracy).
 
address@hidden neq
address@hidden ne
 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).
diff --git a/lib/data-arithmetic.h b/lib/data-arithmetic.h
index a0ef183..da5f766 100644
--- a/lib/data-arithmetic.h
+++ b/lib/data-arithmetic.h
@@ -217,7 +217,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
                                                                         \
     default:                                                            \
       error(EXIT_FAILURE, 0, "type %d not recognized in "               \
-            "for o->type in BINARY_LEFT_RIGHT_DONE", type);             \
+            "for o->type in BINARY_LEFT_RIGHT_DONE", o->type);          \
     }
 
 
@@ -253,14 +253,52 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
                                                                         \
     default:                                                            \
       error(EXIT_FAILURE, 0, "type %d not recognized in "               \
-            "for r->type in BINARY_LEFT_DONE", type);                   \
+            "for r->type in BINARY_LEFT_DONE", r->type);                \
     }
 
 
 
 
 
-#define BINARY_MULTISWITCH(OP)                                          \
+/* 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 *);                                         \
+                                                                        \
+                                                                        \
+  /* 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");                                            \
+                                                                        \
+                                                                        \
+  /* 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;                     \
+                                                                        \
+                                                                        \
+  /* 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 the output pointer was not set for any reason, allocate it. */  \
+  if(o==NULL)                                                           \
+    o = gal_data_alloc(NULL, out_type,                                  \
+                       l->size>1 ? l->ndim  : r->ndim,                  \
+                       l->size>1 ? l->dsize : r->dsize,                 \
+                       0, l->mmapped || r->mmapped);                    \
+                                                                        \
+                                                                        \
+  /* Do the operations based on the different types. */                 \
   switch(l->type)                                                       \
     {                                                                   \
     case GAL_DATA_TYPE_UCHAR:                                           \
@@ -289,51 +327,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
                                                                         \
     default:                                                            \
       error(EXIT_FAILURE, 0, "type %d not recognized in "               \
-            "for l->type in BINARY_MULTISWITCH", type);                 \
-    }
-
-
-
-
-
-/* Preparations for binary operators.
-
-   Note that after `gal_data_to_same_type', we are only concerned with the
-   `l' and `s' pointers. */
-#define BINARY_INTERNAL(OP, OUT_TYPE)                                   \
-                                                                        \
-  gal_data_t *l, *r;                                                    \
-                                                                        \
-                                                                        \
-  /* Read the variable arguments. */                                    \
-  l = va_arg(va, gal_data_t *);                                         \
-  r = 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 ) )   \
-    type=0;      /* Everything is ok, just a place-holder. */           \
-  else if (gal_data_dsize_is_different(l, r))                           \
-    error(EXIT_FAILURE, 0, "The datasets don't have the same "          \
-          "dimension/size");                                            \
-                                                                        \
-                                                                        \
-  /* Find the best output type. */                                      \
-  type=gal_data_out_type(l, r);                                         \
-                                                                        \
-                                                                        \
-  /* Output can point to any one of the two arrays. */                  \
-  if(flags & GAL_DATA_ARITH_INPLACE)                                    \
-    o = l->size>1 ? l : r;                                              \
-  else                                                                  \
-    o = gal_data_alloc(NULL, type,                                      \
-                       l->size>1 ? l->ndim  : r->ndim,                  \
-                       l->size>1 ? l->dsize : r->dsize,                 \
-                       0, l->mmapped || r->mmapped);                    \
-                                                                        \
-                                                                        \
-  /* In block to allow definitions. */                                  \
-  BINARY_MULTISWITCH(OP);                                               \
+            "for l->type in BINARY_MULTISWITCH", l->type);              \
+    }                                                                   \
                                                                         \
   /* Clean up. */                                                       \
   if(flags & GAL_DATA_ARITH_FREE)                                       \
@@ -341,7 +336,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
       if(o==l) gal_data_free(r);                                        \
       else if(o==r) gal_data_free(l);                                   \
       else {gal_data_free(l); gal_data_free(r);}                        \
-    }
+    }                                                                   \
+}
 
 
 
diff --git a/lib/data.c b/lib/data.c
index cd5bc67..e34d9b1 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -1141,28 +1141,32 @@ gal_data_string_to_number(char *string)
  **************           Arithmetic           ***************
  *************************************************************/
 gal_data_t *
-gal_data_arithmetic(char *operator, unsigned char flags, ...)
+gal_data_arithmetic(int operator, unsigned char flags, ...)
 {
-  int type;
   va_list va;
+  int out_type;
+  size_t out_size;
   gal_data_t *o=NULL;
 
   /* Prepare the variable arguments (starting after the flags argument). */
   va_start(va, flags);
 
   /* Depending on the operator do the job: */
-  if      (!strcmp(operator, "+"))   { BINARY_INTERNAL(+, 0); }
-  else if (!strcmp(operator, "-"))   { BINARY_INTERNAL(-, 0); }
-  else if (!strcmp(operator, "*"))   { BINARY_INTERNAL(*, 0); }
-  else if (!strcmp(operator, "/"))   { BINARY_INTERNAL(/, 0); }
-  else if (!strcmp(operator, "lt"))  { BINARY_INTERNAL(<, 0); }
-  else if (!strcmp(operator, "le"))  { BINARY_INTERNAL(<=, 0); }
-  else if (!strcmp(operator, "gt"))  { BINARY_INTERNAL(>, 0); }
-  else if (!strcmp(operator, "ge"))  { BINARY_INTERNAL(>=, 0); }
-  else if (!strcmp(operator, "eq"))  { BINARY_INTERNAL(==, 0); }
-  else if (!strcmp(operator, "neq")) { BINARY_INTERNAL(!=, 0); }
-  else if (!strcmp(operator, "and")) { BINARY_INTERNAL(&&, 0); }
-  else if (!strcmp(operator, "or"))  { BINARY_INTERNAL(||, 0); }
+  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_LT:  BINARY_INTERNAL(<,  GAL_DATA_TYPE_UCHAR); 
break;
+    case GAL_DATA_OPERATOR_LE:  BINARY_INTERNAL(<=, GAL_DATA_TYPE_UCHAR); 
break;
+    case GAL_DATA_OPERATOR_GT:  BINARY_INTERNAL(>,  GAL_DATA_TYPE_UCHAR); 
break;
+    case GAL_DATA_OPERATOR_GE:  BINARY_INTERNAL(>=, GAL_DATA_TYPE_UCHAR); 
break;
+    case GAL_DATA_OPERATOR_EQ:  BINARY_INTERNAL(==, GAL_DATA_TYPE_UCHAR); 
break;
+    case GAL_DATA_OPERATOR_NE:  BINARY_INTERNAL(!=, GAL_DATA_TYPE_UCHAR); 
break;
+    case GAL_DATA_OPERATOR_AND: BINARY_INTERNAL(&&, GAL_DATA_TYPE_UCHAR); 
break;
+    case GAL_DATA_OPERATOR_OR:  BINARY_INTERNAL(||, GAL_DATA_TYPE_UCHAR); 
break;
 
 #if 0
   else if(!strcmp(operator, "abs"))       takeabs(p);
@@ -1181,9 +1185,10 @@ gal_data_arithmetic(char *operator, unsigned char flags, 
...)
   else if(!strcmp(operator, "where"))     where(p);
 #endif
 
-  else
-    error(EXIT_FAILURE, 0, "the argument \"%s\" could not be "
-          "interpretted as an operator", operator);
+    default:
+      error(EXIT_FAILURE, 0, "the argument \"%d\" could not be "
+            "interpretted as an operator", operator);
+    }
 
   /* End the variable argument structure and return. */
   va_end(va);
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index d841833..497ef5e 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -103,7 +103,7 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 enum gal_data_alltypes
 {
   GAL_DATA_TYPE_BIT,       /* Bit              (TBIT).        */
-  GAL_DATA_TYPE_UCHAR,     /* Unsigned char    (TBYTE).       */
+  GAL_DATA_TYPE_UCHAR,     /* unsigned char    (TBYTE).       */
   GAL_DATA_TYPE_CHAR,      /* char             (TSBYTE).      */
   GAL_DATA_TYPE_LOGICAL,   /* char             (TLOGICAL).    */
   GAL_DATA_TYPE_STRING,    /* string           (TSTRING).     */
@@ -124,6 +124,46 @@ enum gal_data_alltypes
 
 
 
+enum gal_data_operators
+{
+  GAL_DATA_OPERATOR_PLUS,      /*   +    */
+  GAL_DATA_OPERATOR_MINUS,     /*   -    */
+  GAL_DATA_OPERATOR_MULTIPLY,  /*   *    */
+  GAL_DATA_OPERATOR_DIVIDE,    /*   /    */
+
+  GAL_DATA_OPERATOR_LT,        /*   <    */
+  GAL_DATA_OPERATOR_LE,        /*   <=   */
+  GAL_DATA_OPERATOR_GT,        /*   >    */
+  GAL_DATA_OPERATOR_GE,        /*   >=   */
+  GAL_DATA_OPERATOR_EQ,        /*   ==   */
+  GAL_DATA_OPERATOR_NE,        /*   !=   */
+  GAL_DATA_OPERATOR_AND,       /*   &&   */
+  GAL_DATA_OPERATOR_OR,        /*   ||   */
+  GAL_DATA_OPERATOR_BITAND,    /*   &    */
+  GAL_DATA_OPERATOR_BITOR,     /*   |    */
+
+  GAL_DATA_OPERATOR_NOT,       /*   !    */
+  GAL_DATA_OPERATOR_ISBLANK,   /* Similar to isnan() for floats. */
+  GAL_DATA_OPERATOR_WHERE,     /*   ?:   */
+
+  GAL_DATA_OPERATOR_ABS,       /* abs()  */
+  GAL_DATA_OPERATOR_POW,       /* pow()  */
+  GAL_DATA_OPERATOR_SQRT,      /* sqrt() */
+  GAL_DATA_OPERATOR_LOG,       /* log()  */
+  GAL_DATA_OPERATOR_LOG10,     /* log()  */
+
+  GAL_DATA_OPERATOR_MINVAL,    /* Minimum value of array.                */
+  GAL_DATA_OPERATOR_MAXVAL,    /* Maximum value of array.                */
+  GAL_DATA_OPERATOR_MIN,       /* Minimum per pixel of multiple arrays.  */
+  GAL_DATA_OPERATOR_MAX,       /* Maximum per pixel of multiple arrays.  */
+  GAL_DATA_OPERATOR_AVERAGE,   /* Average per pixel of multiple arrays.  */
+  GAL_DATA_OPERATOR_MEDIAN,    /* Median per pixel of multiple arrays.   */
+};
+
+
+
+
+
 /* Main data structure
 
    If mmaped==0, it is assumed that the data is allocated (using
@@ -226,7 +266,7 @@ gal_data_string_to_number(char *string);
  **************           Arithmetic           ***************
  *************************************************************/
 gal_data_t *
-gal_data_arithmetic(char *operator, unsigned char flags, ...);
+gal_data_arithmetic(int operator, unsigned char flags, ...);
 
 
 



reply via email to

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