gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master ff23b87 1/3: Table: the set- operator now avai


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master ff23b87 1/3: Table: the set- operator now availabe in column arithmetic
Date: Fri, 19 Feb 2021 23:07:06 -0500 (EST)

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

    Table: the set- operator now availabe in column arithmetic
    
    The 'set-' operator has been very useful in the Arithmetic
    program. However, until now this operator wasn't available in Table's
    column arithmetic.
    
    With this commit, the core functions that done the job for the Arithmetic
    program have been moved into the Gnuastro library and thus the same
    function is now being used in both the Arithmetic program and Table's
    column arithmetic. In order to do this, some small polishing was done in
    both the Arithmetic program and Table (the parts related to column
    arithmetic).
    
    In the process two minor issues have been found and corrected:
    
     - The error messages in the arithmetic library that reported the operator
       name didn't have any single-quotes around them.
    
     - The "multiply" operator was being mistakenly reported as '*' instead of
       'x'.
    
     - In the Fits program, when correcting the types of the columns as the
       data was being read, a typo had caused mistakenly using the 'key'
       variable instead of the correct 'write' variable.
---
 NEWS                                   |   4 +
 bin/arithmetic/arithmetic.c            |  45 +++++--
 bin/arithmetic/main.c                  |   2 +-
 bin/arithmetic/main.h                  |   6 +-
 bin/arithmetic/operands.c              | 229 +++++----------------------------
 bin/arithmetic/operands.h              |   3 +
 bin/fits/keywords.c                    |   2 +-
 bin/table/arithmetic.c                 | 183 ++++++++++++++++++++------
 bin/table/arithmetic.h                 |   3 +-
 bin/table/main.h                       |   5 +-
 bin/table/ui.c                         |  43 ++++---
 doc/gnuastro.texi                      |   2 +-
 lib/Makefile.am                        |  21 +--
 lib/arithmetic-set.c                   | 193 +++++++++++++++++++++++++++
 lib/arithmetic.c                       |  10 +-
 lib/gnuastro-internal/arithmetic-set.h |  51 ++++++++
 16 files changed, 513 insertions(+), 289 deletions(-)

diff --git a/NEWS b/NEWS
index 738a0db..b2ac437 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,10 @@ See the end of the file for license conditions.
      the rows. It takes an integer, selects that many rows from the input
      randomly.
    - New column arithmetic operators:
+     - 'set-AAA' operator (which allows storing the popped operand into a
+       named variable for easy usage in complex operations) is also usable
+       in Table's column arithmetic. Until now this operator was only
+       available in the Arithmetic program (for operation on images).
      - 'date-to-sec' Convert FITS date format ('YYYY-MM-DDThh:mm:ss') into
        seconds from the Unix epoch (1970-01-01,00:00:00 UTC). This can be
        very useful in combination with the new '--keyvalue' option of the
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index 2ed86fc..3975a7a 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -1344,6 +1344,28 @@ arithmetic_operator_run(struct arithmeticparams *p, int 
operator,
 
 
 
+/* Used by the 'set-' operator. */
+static int
+arithmetic_set_name_used_later(void *in, char *name)
+{
+  struct gal_arithmetic_set_params *p=(struct gal_arithmetic_set_params *)in;
+  gal_list_str_t *token, *tokens = (gal_list_str_t *)(p->tokens);
+
+  size_t counter=0;
+
+  /* If the name exists after the current token, then return 1. */
+  for(token=tokens;token!=NULL;token=token->next)
+    if( counter++ > p->tokencounter && !strcmp(token->v, name) )
+      return 1;
+
+  /* If we get to this point, it means that the name doesn't exist. */
+  return 0;
+}
+
+
+
+
+
 /* This function implements the reverse polish algorithm as explained
    in the Wikipedia page.
 
@@ -1358,11 +1380,14 @@ reversepolish(struct arithmeticparams *p)
   char *hdu, *filename, *printnum;
   int operator=GAL_ARITHMETIC_OP_INVALID;
 
-
   /* Prepare the processing: */
-  p->operands=NULL;
   p->popcounter=0;
-
+  p->operands=NULL;
+  p->setprm.params=p;
+  p->setprm.tokencounter=0;
+  p->setprm.tokens=p->tokens;
+  p->setprm.pop=operands_pop_wrapper_set;
+  p->setprm.used_later=arithmetic_set_name_used_later;
 
   /* Go over each input token and do the work. */
   for(token=p->tokens;token!=NULL;token=token->next)
@@ -1379,11 +1404,11 @@ reversepolish(struct arithmeticparams *p)
       else if( !strncmp(OPERATOR_PREFIX_TOFILEFREE, token->v,
                    OPERATOR_PREFIX_LENGTH_TOFILE) )
         arithmetic_tofile(p, token->v, 1);
-      else if( !strncmp(token->v, OPERATOR_PREFIX_SET,
-                        OPERATOR_PREFIX_LENGTH_SET) )
-        operands_set_name(p, token->v);
-      else if( gal_array_name_recognized(token->v)
-          || operands_is_name(p, token->v) )
+      else if( !strncmp(token->v, GAL_ARITHMETIC_SET_PREFIX,
+                        GAL_ARITHMETIC_SET_PREFIX_LENGTH) )
+        gal_arithmetic_set_name(&p->setprm, token->v);
+      else if(    gal_array_name_recognized(token->v)
+               || gal_arithmetic_set_is_name(p->setprm.named, token->v) )
         operands_add(p, token->v, NULL);
       else if( (data=gal_data_copy_string_to_number(token->v)) )
         {
@@ -1403,7 +1428,7 @@ reversepolish(struct arithmeticparams *p)
         }
 
       /* Increment the token counter. */
-      ++p->tokencounter;
+      ++p->setprm.tokencounter;
     }
 
 
@@ -1480,7 +1505,7 @@ reversepolish(struct arithmeticparams *p)
      into 'data', so it is freed when freeing 'data'. */
   gal_data_free(data);
   free(p->refdata.dsize);
-  gal_list_data_free(p->named);
+  gal_list_data_free(p->setprm.named);
 
 
   /* Clean up. Note that the tokens were taken from the command-line
diff --git a/bin/arithmetic/main.c b/bin/arithmetic/main.c
index 4000ca0..f1e72f5 100644
--- a/bin/arithmetic/main.c
+++ b/bin/arithmetic/main.c
@@ -36,7 +36,7 @@ int
 main (int argc, char *argv[])
 {
   struct timeval t1;
-  struct arithmeticparams p={{{0},0},0};
+  struct arithmeticparams p={{{0},0},{0},0};
 
   /* Set the starting time. */
   time(&p.rawtime);
diff --git a/bin/arithmetic/main.h b/bin/arithmetic/main.h
index a01d98a..f53c46a 100644
--- a/bin/arithmetic/main.h
+++ b/bin/arithmetic/main.h
@@ -27,6 +27,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/list.h>
 
 #include <gnuastro-internal/options.h>
+#include <gnuastro-internal/arithmetic-set.h>
 
 
 /* Progarm name macros: */
@@ -40,10 +41,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 /* Constants: */
 #define NEG_DASH_REPLACE 11 /* Vertical tab (ASCII=11) for negative dash */
-#define OPERATOR_PREFIX_SET               "set-"
 #define OPERATOR_PREFIX_TOFILE            "tofile-"
 #define OPERATOR_PREFIX_TOFILEFREE        "tofilefree-"
-#define OPERATOR_PREFIX_LENGTH_SET        strlen(OPERATOR_PREFIX_SET)
 #define OPERATOR_PREFIX_LENGTH_TOFILE     strlen(OPERATOR_PREFIX_TOFILE)
 #define OPERATOR_PREFIX_LENGTH_TOFILEFREE strlen(OPERATOR_PREFIX_TOFILEFREE)
 
@@ -71,6 +70,7 @@ struct arithmeticparams
 {
   /* Other structures: */
   struct gal_options_common_params cp;  /* Common parameters.           */
+  struct gal_arithmetic_set_params setprm; /* Parameters for 'set-'.    */
 
   /* Input: */
   gal_list_str_t     *hdus;  /* List of all given HDU strings.          */
@@ -82,8 +82,6 @@ struct arithmeticparams
   char          *globalhdu;  /* Single HDU for all inputs.              */
   uint8_t      onedasimage;  /* Write 1D outputs as an image not table. */
   uint8_t     onedonstdout;  /* Write 1D outputs on stdout, not table.  */
-  gal_data_t        *named;  /* List containing variables.              */
-  size_t      tokencounter;  /* Counter for finding place in tokens.    */
 
   /* Operating mode: */
   int        wcs_collapsed;  /* If the internal WCS is already collapsed.*/
diff --git a/bin/arithmetic/operands.c b/bin/arithmetic/operands.c
index 36c32af..1c06500 100644
--- a/bin/arithmetic/operands.c
+++ b/bin/arithmetic/operands.c
@@ -34,6 +34,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/tiff.h>
 #include <gnuastro/array.h>
 #include <gnuastro-internal/checkset.h>
+#include <gnuastro-internal/arithmetic-set.h>
 
 #include "main.h"
 
@@ -76,192 +77,6 @@ operands_num(struct arithmeticparams *p)
 
 
 /**********************************************************************/
-/************                Named operands             ***************/
-/**********************************************************************/
-static int
-operands_name_is_used_later(struct arithmeticparams *p, char *name)
-{
-  size_t counter=0;
-  gal_list_str_t *token;
-
-  /* If the name indeed exists afterwards, then just return 1. */
-  for(token=p->tokens;token!=NULL;token=token->next)
-    if( counter++ > p->tokencounter && !strcmp(token->v, name) )
-      return 1;
-
-  /* If we get to this point, it means that the name doesn't exist. */
-  return 0;
-}
-
-
-
-
-
-/* Remove a name from the list of names and return the dataset it points
-   to. */
-static gal_data_t *
-operands_remove_name(struct arithmeticparams *p, char *name)
-{
-  gal_data_t *tmp, *removed=NULL, *prev=NULL;
-
-  /* Go over all the given names. */
-  for(tmp=p->named;tmp!=NULL;tmp=tmp->next)
-    {
-      if( !strcmp(tmp->name, name) )
-        {
-          removed=tmp;
-          if(prev) prev->next = tmp->next;
-          else     p->named   = tmp->next;
-        }
-
-      /* Set this node as the 'prev' pointer. */
-      prev=tmp;
-    }
-
-  /* A small sanity check. */
-  if(removed==NULL)
-    error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
-          "problem. 'removed' must not be NULL at this point", __func__,
-          PACKAGE_BUGREPORT);
-
-  /* Nothing in the list points to it now. So we can safely modify and
-     return it. */
-  free(removed->name);
-  removed->next=NULL;
-  removed->name=NULL;
-  return removed;
-}
-
-
-
-
-
-/* Pop a dataset and keep it in the 'named' list for later use. */
-void
-operands_set_name(struct arithmeticparams *p, char *token)
-{
-  gal_data_t *tmp, *tofree;
-  char *varname=&token[ OPERATOR_PREFIX_LENGTH_SET ];
-
-  /* If a dataset with this name already exists, it will be removed/deleted
-     so we can use the name for the newly designated dataset. */
-  for(tmp=p->named; tmp!=NULL; tmp=tmp->next)
-    if( !strcmp(varname, tmp->name) )
-      {
-        tofree=operands_remove_name(p, varname);
-        gal_data_free(tofree);
-
-        /* IMPORTANT: we MUST break here! 'tmp' does't point to the right
-           place any more. We can define a 'prev' node and modify it on
-           every attempt, but since there is only one dataset with a given
-           name, that is redundant and will just make the program slow. */
-        break;
-      }
-
-  /* Pop the top operand, then add it to the list of named datasets, but
-     only if it is used in later tokens. If it isn't, free the popped
-     dataset. The latter case (to define a name, but not use it), is
-     obviously a redundant operation, but that is upto the user, we
-     shouldn't worry about it here. We should just have everything in
-     place, so no crashes occur or no extra memory is consumed. */
-  if( operands_name_is_used_later(p, varname) )
-    {
-      /* Add the top popped operand to the list of names. */
-      gal_list_data_add(&p->named, operands_pop(p, "set"));
-
-      /* Write the requested name into this dataset. But note that 'name'
-         MUST be already empty. So to be safe, we'll do a sanity check. */
-      if(p->named->name)
-        error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix "
-              "the problem. The 'name' element should be NULL at this "
-              "point, but it isn't", __func__, PACKAGE_BUGREPORT);
-      gal_checkset_allocate_copy(varname, &p->named->name);
-    }
-  else
-    {
-      /* Pop the top operand, then free it. */
-      tmp=operands_pop(p, "set");
-      gal_data_free(tmp);
-    }
-}
-
-
-
-
-
-/* See if a given token is the name of a variable. */
-int
-operands_is_name(struct arithmeticparams *p, char *token)
-{
-  gal_data_t *tmp;
-
-  /* Make sure the variable name hasn't been set before. */
-  for(tmp=p->named; tmp!=NULL; tmp=tmp->next)
-    if( !strcmp(token, tmp->name) )
-      return 1;
-
-  /* If control reaches here, then there was no match*/
-  return 0;
-}
-
-
-
-
-
-/* Return a copy of the named dataset. */
-static gal_data_t *
-operands_copy_named(struct arithmeticparams *p, char *name)
-{
-  gal_data_t *out=NULL, *tmp;
-
-  /* Find the proper named element to use. */
-  for(tmp=p->named;tmp!=NULL;tmp=tmp->next)
-    if( !strcmp(tmp->name, name) )
-      {
-        /* If the named operand is used later, then copy it into the
-           output. */
-        if( operands_name_is_used_later(p, name) )
-          {
-            out=gal_data_copy(tmp);
-            free(out->name);
-            out->name=NULL;
-            out->next=NULL;
-          }
-        /* The named operand is not used any more. Remove it from the list
-           of named datasets and continue. */
-        else out=operands_remove_name(p, name);
-      }
-
-  /* A small sanity check. */
-  if(out==NULL)
-    error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s to fix the "
-          "problem. The requested name '%s' couldn't be found in the list",
-          __func__, PACKAGE_BUGREPORT, name);
-
-  /* Return. */
-  return out;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**********************************************************************/
 /************      Adding to and popping from stack     ***************/
 /**********************************************************************/
 void
@@ -285,10 +100,10 @@ operands_add(struct arithmeticparams *p, char *filename, 
gal_data_t *data)
 
       /* If the 'filename' is the name of a dataset, then use a copy of it.
          otherwise, do the basic analysis. */
-      if( filename && operands_is_name(p, filename) )
+      if( filename && gal_arithmetic_set_is_name(p->setprm.named, filename) )
         {
           newnode->filename=NULL;
-          newnode->data=operands_copy_named(p, filename);
+          newnode->data=gal_arithmetic_set_copy_named(&p->setprm, filename);
         }
       else
         {
@@ -313,8 +128,10 @@ operands_add(struct arithmeticparams *p, char *filename, 
gal_data_t *data)
               if(readwcs && p->refdata.wcs==NULL)
                 {
                   /* If the HDU is an image, read its size. */
-                  dsize = ( gal_fits_hdu_format(filename, 
newnode->hdu)==IMAGE_HDU
-                            ? gal_fits_img_info_dim(filename, newnode->hdu, 
&ndim)
+                  dsize = ( gal_fits_hdu_format(filename,
+                                                newnode->hdu)==IMAGE_HDU
+                            ? gal_fits_img_info_dim(filename,
+                                                    newnode->hdu, &ndim)
                             : NULL);
 
                   /* Read the WCS. */
@@ -325,13 +142,15 @@ operands_add(struct arithmeticparams *p, char *filename, 
gal_data_t *data)
                      image HDU). */
                   if(dsize)
                     {
-                      ndim=gal_dimension_remove_extra(ndim, dsize, 
p->refdata.wcs);
+                      ndim=gal_dimension_remove_extra(ndim, dsize,
+                                                      p->refdata.wcs);
                       free(dsize);
                     }
 
                   /* Let the user know that the WCS is read. */
                   if(p->refdata.wcs && !p->cp.quiet)
-                    printf(" - WCS: %s (hdu %s).\n", filename, newnode->hdu);
+                    printf(" - WCS: %s (hdu %s).\n", filename,
+                           newnode->hdu);
                 }
             }
           else newnode->hdu=NULL;
@@ -374,11 +193,14 @@ operands_pop(struct arithmeticparams *p, char *operator)
                                  p->cp.quietmmap);
       data->ndim=gal_dimension_remove_extra(data->ndim, data->dsize, NULL);
 
-      /* Arithmetic changes the contents of a dataset, so the existing name
-         (in the FITS 'EXTNAME' keyword) should not be passed on beyond
-         this point. Also, in Arithmetic, the 'name' element is used to
-         identify variables. */
-      if(data->name) { free(data->name); data->name=NULL; }
+      /* Arithmetic changes the contents of a dataset, so the old name and
+         metadata (in the FITS 'EXTNAME' keyword for example) must not be
+         used beyond this point. Furthermore, in Arithmetic, the 'name'
+         element is used to identify variables (with the 'set-'
+         operator). */
+      if(data->name)    { free(data->name);    data->name=NULL;    }
+      if(data->unit)    { free(data->unit);    data->unit=NULL;    }
+      if(data->comment) { free(data->comment); data->comment=NULL; }
 
       /* When the reference data structure's dimensionality is non-zero, it
          means that this is not the first image read. So, write its basic
@@ -421,3 +243,16 @@ operands_pop(struct arithmeticparams *p, char *operator)
   free(operands);
   return data;
 }
+
+
+
+
+/* Wrapper to use the 'operands_pop' function with the 'set-' operator. */
+gal_data_t *
+operands_pop_wrapper_set(void *in)
+{
+  struct gal_arithmetic_set_params *tprm
+    = (struct gal_arithmetic_set_params *)in;
+  struct arithmeticparams *p=(struct arithmeticparams *)tprm->params;
+  return operands_pop(p, "set");
+}
diff --git a/bin/arithmetic/operands.h b/bin/arithmetic/operands.h
index 9f18921..2c9d62d 100644
--- a/bin/arithmetic/operands.h
+++ b/bin/arithmetic/operands.h
@@ -32,6 +32,9 @@ operands_add(struct arithmeticparams *p, char *filename, 
gal_data_t *data);
 gal_data_t *
 operands_pop(struct arithmeticparams *p, char *operator);
 
+gal_data_t *
+operands_pop_wrapper_set(void *in);
+
 void
 operands_set_name(struct arithmeticparams *p, char *token);
 
diff --git a/bin/fits/keywords.c b/bin/fits/keywords.c
index 9d4a950..9a325f6 100644
--- a/bin/fits/keywords.c
+++ b/bin/fits/keywords.c
@@ -746,7 +746,7 @@ keywords_value_in_output_rest(struct fitsparams *p, 
gal_data_t *out,
                       ? key
                       : gal_data_copy_to_new_type(key, goodtype) );
           goodwrite = ( write->type==goodtype
-                        ? key
+                        ? write
                         : gal_data_copy_to_new_type(write, goodtype) );
 
           /* Copy the row into the output. */
diff --git a/bin/table/arithmetic.c b/bin/table/arithmetic.c
index 0b8a0e2..c9996d1 100644
--- a/bin/table/arithmetic.c
+++ b/bin/table/arithmetic.c
@@ -32,6 +32,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/type.h>
 
 #include <gnuastro-internal/checkset.h>
+#include <gnuastro-internal/arithmetic-set.h>
 
 #include "main.h"
 #include "arithmetic.h"
@@ -57,6 +58,8 @@ arithmetic_add_new_to_end(struct arithmetic_token **list)
 
   /* Initialize its elements. */
   node->next=NULL;
+  node->name_def=NULL;
+  node->name_use=NULL;
   node->constant=NULL;
   node->index=GAL_BLANK_SIZE_T;
   node->operator=GAL_ARITHMETIC_OP_INVALID;
@@ -85,6 +88,11 @@ arithmetic_token_free(struct arithmetic_token *list)
   struct arithmetic_token *tmp;
   while(list!=NULL)
     {
+      /* Free allocated elements first. */
+      if(list->name_def) free(list->name_def);
+      if(list->name_use) free(list->name_use);
+
+      /* Set the next list node, and free this one. */
       tmp=list->next;
       free(list);
       list=tmp;
@@ -120,6 +128,7 @@ arithmetic_operator_name(int operator)
   if(out==NULL)
     switch(operator)
       {
+      case ARITHMETIC_TABLE_OP_SET: out="set"; break;
       case ARITHMETIC_TABLE_OP_SIN: out="sin"; break;
       case ARITHMETIC_TABLE_OP_COS: out="cos"; break;
       case ARITHMETIC_TABLE_OP_TAN: out="tan"; break;
@@ -184,6 +193,7 @@ arithmetic_set_operator(struct tableparams *p, char *string,
   /* Set the operator and number of operands. */
   if( op==GAL_ARITHMETIC_OP_INVALID )
     {
+      /* Simple operators. */
       if(      !strcmp(string, "sin"))
         { op=ARITHMETIC_TABLE_OP_SIN; *num_operands=0; }
       else if( !strcmp(string, "cos"))
@@ -250,7 +260,7 @@ arithmetic_init(struct tableparams *p, struct 
arithmetic_token **arith,
   size_t one=1;
   uint8_t ntype;
   char *str, *delimiter=" \t";
-  struct arithmetic_token *node=NULL;
+  struct arithmetic_token *atmp, *node=NULL;
   char *token=NULL, *lasttoken=NULL, *saveptr;
 
   /* Parse all the given tokens. */
@@ -267,18 +277,40 @@ arithmetic_init(struct tableparams *p, struct 
arithmetic_token **arith,
         {
           /* Token is a single number.*/
           if( (num=gal_type_string_to_number(token, &ntype)) )
-            node->constant=gal_data_alloc(num, ntype, 1, &one, NULL, 0, -1, 1,
-                                          NULL, NULL, NULL);
+            node->constant=gal_data_alloc(num, ntype, 1, &one, NULL, 0,
+                                          -1, 1, NULL, NULL, NULL);
 
-          /* Token is a column operand (column number or name). */
+          /* This is a 'set-' operator. */
+          else if( !strncmp(token, GAL_ARITHMETIC_SET_PREFIX,
+                            GAL_ARITHMETIC_SET_PREFIX_LENGTH) )
+            {
+              node->num_operands=0;
+              node->operator=ARITHMETIC_TABLE_OP_SET;
+              gal_checkset_allocate_copy(token, &node->name_def);
+            }
+
+          /* Non-pre-defined situation.*/
           else
             {
-              str = ( (token[0]=='$' && isdigit(token[1]))
-                      ? &token[1]   /* Column number (starting with '$'). */
-                      : token );    /* Column name, just add it.          */
-              gal_list_str_add(toread, str, 1);
-              node->index=*totcalled;
-              *totcalled+=1;
+              /* See if this is an already defined name. */
+              for(atmp=*arith; atmp!=NULL; atmp=atmp->next)
+                if( atmp->name_def
+                    && strcmp(token,
+                              ( atmp->name_def
+                                + GAL_ARITHMETIC_SET_PREFIX_LENGTH) )==0 )
+                  gal_checkset_allocate_copy(token, &node->name_use);
+
+              /* If it wasn't found to be a pre-defined name, then its a
+                 column operand (column number or name). */
+              if(node->name_use==NULL)
+                {
+                  str = ( (token[0]=='$' && isdigit(token[1]))
+                          ? &token[1]   /* Column number (starting with '$'). 
*/
+                          : token );    /* Column name, just add it.          
*/
+                  gal_list_str_add(toread, str, 1);
+                  node->index=*totcalled;
+                  *totcalled+=1;
+                }
             }
         }
 
@@ -314,9 +346,9 @@ arithmetic_indexs_final(struct tableparams *p, size_t 
*colmatch)
   for(tmp=p->outcols;tmp!=NULL;tmp=tmp->next)
     {
       /* If we are on an arithmetic operation. */
-      if(tmp->tokens)
+      if(tmp->arith)
         {
-          for(atmp=tmp->tokens;atmp!=NULL;atmp=atmp->next)
+          for(atmp=tmp->arith;atmp!=NULL;atmp=atmp->next)
             if(atmp->index!=GAL_BLANK_SIZE_T)
               {
                 /* Small sanity check. */
@@ -384,6 +416,14 @@ arithmetic_stack_pop(gal_data_t **stack, int operator, 
char *errormsg)
     error(EXIT_FAILURE, 0, "not enough operands for '%s'%s",
           arithmetic_operator_name(operator), errormsg?errormsg:"");
 
+  /* Arithmetic changes the contents of a dataset, so the old name (in the
+     FITS 'EXTNAME' keyword) must not be used beyond this
+     point. Furthermore, in Arithmetic, the 'name' element is used to
+     identify variables (with the 'set-' operator). */
+  if(out->name)    { free(out->name);    out->name=NULL;    }
+  if(out->unit)    { free(out->unit);    out->unit=NULL;    }
+  if(out->comment) { free(out->comment); out->comment=NULL; }
+
   /* Remove the 'next' element to break from the stack and return. */
   out->next=NULL;
   return out;
@@ -393,6 +433,53 @@ arithmetic_stack_pop(gal_data_t **stack, int operator, 
char *errormsg)
 
 
 
+/* Wrapper function to pop operands within the 'set-' operator. */
+static gal_data_t *
+arithmetic_stack_pop_wrapper_set(void *in)
+{
+  struct gal_arithmetic_set_params *tprm
+    = (struct gal_arithmetic_set_params *)in;
+  gal_data_t **stack=(gal_data_t **)tprm->params;
+  return arithmetic_stack_pop(stack, ARITHMETIC_TABLE_OP_SET, NULL);
+}
+
+
+
+
+
+/* For the 'set-' operator. */
+static int
+arithmetic_set_name_used_later(void *in, char *name)
+{
+  struct gal_arithmetic_set_params *p=(struct gal_arithmetic_set_params *)in;
+  struct arithmetic_token *tokens = (struct arithmetic_token *)(p->tokens);
+  struct arithmetic_token *token;
+
+  size_t counter=0;
+
+  /* If the name exists after the current token, then return 1. Note that
+     we have already separated the usage of names set with 'set-' in the
+     'name_use' element of the 'token' structure. */
+  for(token=tokens;token!=NULL;token=token->next)
+    {
+      if( token->name_use
+          && counter > p->tokencounter
+          && strcmp(token->name_use, name)==0 )
+        return 1;
+
+      /* Increment the counter (has to be after the check above because it
+         may not always get to the 'counter' variable). */
+      ++counter;
+    }
+
+  /* If we get to this point, it means that the name doesn't exist. */
+  return 0;
+}
+
+
+
+
+
 /* Set the converted column metadata. */
 static void
 arithmetic_update_metadata(gal_data_t *col, char *name, char *unit,
@@ -855,36 +942,38 @@ arithmetic_placeholder_name(gal_data_t *col)
 
 
 static void
-arithmetic_operator_run(struct tableparams *p, gal_data_t **stack,
-                        int operator, size_t num_operands)
+arithmetic_operator_run(struct tableparams *p,
+                        struct arithmetic_token *token,
+                        struct gal_arithmetic_set_params *setprm,
+                        gal_data_t **stack)
 {
   gal_data_t *d1=NULL, *d2=NULL, *d3=NULL;
   int flags = ( GAL_ARITHMETIC_INPLACE | GAL_ARITHMETIC_FREE
                 | GAL_ARITHMETIC_NUMOK );
 
   /* When 'num_operands!=0', the operator is in the library. */
-  if(num_operands)
+  if(token->num_operands)
     {
       /* Pop the necessary number of operators. Note that the
          operators are poped from a linked list (which is
          last-in-first-out). So for the operators which need a
          specific order, the first poped operand is actally the
          last (right most, in in-fix notation) input operand.*/
-      switch(num_operands)
+      switch(token->num_operands)
         {
         case 1:
-          d1=arithmetic_stack_pop(stack, operator, NULL);
+          d1=arithmetic_stack_pop(stack, token->operator, NULL);
           break;
 
         case 2:
-          d2=arithmetic_stack_pop(stack, operator, NULL);
-          d1=arithmetic_stack_pop(stack, operator, NULL);
+          d2=arithmetic_stack_pop(stack, token->operator, NULL);
+          d1=arithmetic_stack_pop(stack, token->operator, NULL);
           break;
 
         case 3:
-          d3=arithmetic_stack_pop(stack, operator, NULL);
-          d2=arithmetic_stack_pop(stack, operator, NULL);
-          d1=arithmetic_stack_pop(stack, operator, NULL);
+          d3=arithmetic_stack_pop(stack, token->operator, NULL);
+          d2=arithmetic_stack_pop(stack, token->operator, NULL);
+          d1=arithmetic_stack_pop(stack, token->operator, NULL);
           break;
 
         case -1:
@@ -897,7 +986,8 @@ arithmetic_operator_run(struct tableparams *p, gal_data_t 
**stack,
           error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix "
                 "the problem. '%zu' is not recognized as an operand "
                 "counter (with '%s')", __func__, PACKAGE_BUGREPORT,
-                num_operands, arithmetic_operator_name(operator));
+                token->num_operands,
+                arithmetic_operator_name(token->operator));
         }
 
       /* Run the arithmetic operation. Note that 'gal_arithmetic' is a
@@ -905,7 +995,7 @@ arithmetic_operator_run(struct tableparams *p, gal_data_t 
**stack,
          arguments it uses depend on the operator. In other words, when the
          operator doesn't need three operands, the extra arguments will be
          ignored. */
-      gal_list_data_add(stack, gal_arithmetic(operator, p->cp.numthreads,
+      gal_list_data_add(stack, gal_arithmetic(token->operator, 
p->cp.numthreads,
                                               flags, d1, d2, d3) );
 
       /* Reset the meta-data for the element that was just put on the
@@ -916,7 +1006,7 @@ arithmetic_operator_run(struct tableparams *p, gal_data_t 
**stack,
   /* This operator is specific to this program (Table). */
   else
     {
-      switch(operator)
+      switch(token->operator)
         {
         case ARITHMETIC_TABLE_OP_SIN:
         case ARITHMETIC_TABLE_OP_COS:
@@ -931,27 +1021,31 @@ arithmetic_operator_run(struct tableparams *p, 
gal_data_t **stack,
         case ARITHMETIC_TABLE_OP_ACOSH:
         case ARITHMETIC_TABLE_OP_ATANH:
         case ARITHMETIC_TABLE_OP_ATAN2:
-          arithmetic_trig_hyper(p, stack, operator);
+          arithmetic_trig_hyper(p, stack, token->operator);
           break;
 
         case ARITHMETIC_TABLE_OP_WCSTOIMG:
         case ARITHMETIC_TABLE_OP_IMGTOWCS:
-          arithmetic_wcs(p, stack, operator);
+          arithmetic_wcs(p, stack, token->operator);
           break;
 
         case ARITHMETIC_TABLE_OP_DATETOSEC:
-          arithmetic_datetosec(p, stack, operator);
+          arithmetic_datetosec(p, stack, token->operator);
           break;
 
         case ARITHMETIC_TABLE_OP_DISTANCEFLAT:
         case ARITHMETIC_TABLE_OP_DISTANCEONSPHERE:
-          arithmetic_distance(p, stack, operator);
+          arithmetic_distance(p, stack, token->operator);
+          break;
+
+        case ARITHMETIC_TABLE_OP_SET:
+          gal_arithmetic_set_name(setprm, token->name_def);
           break;
 
         default:
           error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to "
                 "fix the problem. The operator code %d is not recognized",
-                __func__, PACKAGE_BUGREPORT, operator);
+                __func__, PACKAGE_BUGREPORT, token->operator);
         }
     }
 }
@@ -964,16 +1058,28 @@ arithmetic_operator_run(struct tableparams *p, 
gal_data_t **stack,
 static void
 arithmetic_reverse_polish(struct tableparams *p, struct column_pack *outpack)
 {
-  gal_data_t *single, *stack=NULL;
   struct arithmetic_token *token;
+  gal_data_t *single, *stack=NULL;
+  struct gal_arithmetic_set_params setprm={0};
+
+  /* Initialize the arithmetic functions/pointers. */
+  setprm.params=&stack;
+  setprm.tokens=outpack->arith;
+  setprm.pop=arithmetic_stack_pop_wrapper_set;
+  setprm.used_later=arithmetic_set_name_used_later;
 
   /* Go through all the tokens given to this element. */
-  for(token=outpack->tokens;token!=NULL;token=token->next)
+  for(token=outpack->arith;token!=NULL;token=token->next)
     {
       /* We are on an operator. */
       if(token->operator!=GAL_ARITHMETIC_OP_INVALID)
-        arithmetic_operator_run(p, &stack, token->operator,
-                                token->num_operands);
+        arithmetic_operator_run(p, token, &setprm, &stack);
+
+      /* We are on a named variable. */
+      else if( token->name_use )
+        gal_list_data_add(&stack,
+                          gal_arithmetic_set_copy_named(&setprm,
+                                                        token->name_use));
 
       /* Constant number: just put it ontop of the stack. */
       else if(token->constant)
@@ -991,6 +1097,9 @@ arithmetic_reverse_polish(struct tableparams *p, struct 
column_pack *outpack)
         error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to "
               "fix the problem. The token can't be identified as an "
               "operator, constant or column", __func__, PACKAGE_BUGREPORT);
+
+      /* Increment the token counter. */
+      ++setprm.tokencounter;
     }
 
   /* Put everything that remains in the stack (reversed) into the final
@@ -1049,16 +1158,16 @@ arithmetic_operate(struct tableparams *p)
   /* From now on, we will be looking for columns from the index in
      'colarray', so to keep things clean, we'll set all the 'next' elements
      to NULL. */
-  for(i=0;i<p->numcolarray;++i) p->colarray[i]->next=NULL;
+  for(i=0; i<p->numcolarray; ++i) p->colarray[i]->next=NULL;
 
   /* We'll also reset the output table pointer, to fill it in as we
      progress. */
   p->table=NULL;
 
   /* Go over each package of columns. */
-  for(outpack=p->outcols;outpack!=NULL;outpack=outpack->next)
+  for(outpack=p->outcols; outpack!=NULL; outpack=outpack->next)
     {
-      if(outpack->tokens)
+      if(outpack->arith)
         arithmetic_reverse_polish(p, outpack);
       else
         {
diff --git a/bin/table/arithmetic.h b/bin/table/arithmetic.h
index 436e07a..06d31ce 100644
--- a/bin/table/arithmetic.h
+++ b/bin/table/arithmetic.h
@@ -35,7 +35,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 /* Operators used for arithmetic on columns. */
 enum arithmetic_operators
 {
-  ARITHMETIC_TABLE_OP_SIN = GAL_ARITHMETIC_OP_LAST_CODE,
+  ARITHMETIC_TABLE_OP_SET = GAL_ARITHMETIC_OP_LAST_CODE,
+  ARITHMETIC_TABLE_OP_SIN,
   ARITHMETIC_TABLE_OP_COS,
   ARITHMETIC_TABLE_OP_TAN,
   ARITHMETIC_TABLE_OP_ASIN,
diff --git a/bin/table/main.h b/bin/table/main.h
index dee83e2..065302a 100644
--- a/bin/table/main.h
+++ b/bin/table/main.h
@@ -28,6 +28,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/data.h>
 
 #include <gnuastro-internal/options.h>
+#include <gnuastro-internal/arithmetic-set.h>
 
 /* Progarm names.  */
 #define PROGRAM_NAME   "Table"         /* Program full name.       */
@@ -65,6 +66,8 @@ struct arithmetic_token
   size_t     num_operands;  /* OPERATOR: Number of required operands.     */
   size_t            index;  /* OPERAND: Index in requested columns.       */
   gal_data_t    *constant;  /* OPERAND: a constant/single number.         */
+  char          *name_def;  /* Name given to the 'set-' operator.         */
+  char          *name_use;  /* If this a usage of a name.                 */
   struct arithmetic_token *next;  /* Pointer to next token.               */
 };
 
@@ -72,7 +75,7 @@ struct column_pack
 {
   size_t                    start; /* Starting ind. in requested columns. */
   size_t                numsimple; /* Number of simple columns.           */
-  struct arithmetic_token *tokens; /* Arithmetic tokens to use.           */
+  struct arithmetic_token  *arith; /* Arithmetic tokens to use.           */
   struct column_pack        *next; /* Next output column.                 */
 };
 
diff --git a/bin/table/ui.c b/bin/table/ui.c
index bf173c3..adbd834 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -465,8 +465,8 @@ ui_outcols_add_new_to_end(struct column_pack **list)
 
   /* Initialize its elements. */
   node->next=NULL;
+  node->arith=NULL;
   node->numsimple=0;
-  node->tokens=NULL;
   node->start=GAL_BLANK_SIZE_T;
 
   /* If the list already has elements, go to the last node in the list and
@@ -493,7 +493,7 @@ ui_outcols_free(struct column_pack *list)
   struct column_pack *tmp;
   while(list!=NULL)
     {
-      arithmetic_token_free(list->tokens);
+      arithmetic_token_free(list->arith);
       tmp=list->next;
       free(list);
       list=tmp;
@@ -624,7 +624,7 @@ ui_columns_prepare(struct tableparams *p)
               /* Add a new column pack, then read all the tokens (while
                  specifying which columns it needs). */
               node=ui_outcols_add_new_to_end(&p->outcols);
-              arithmetic_init(p, &node->tokens, &toread, &totcalled,
+              arithmetic_init(p, &node->arith, &toread, &totcalled,
                               strarr[i]+ARITHMETIC_CALL_LENGTH);
               free(strarr[i]);
             }
@@ -640,7 +640,7 @@ ui_columns_prepare(struct tableparams *p)
                   /* If the previous column package was an arithmetic
                      operation, allocate a new node. */
                   last=ui_outcols_last(p->outcols);
-                  if(last->tokens)
+                  if(last->arith)
                     {
                       node=ui_outcols_add_new_to_end(&p->outcols);
                       node->start=totcalled;
@@ -675,28 +675,29 @@ ui_columns_prepare(struct tableparams *p)
       struct column_pack *tmp;
       struct arithmetic_token *atmp;
       for(tmp=p->outcols;tmp!=NULL;tmp=tmp->next)
-        {
-          if(tmp->tokens)
-            for(atmp=tmp->tokens;atmp!=NULL;atmp=atmp->next)
+        if(tmp->arith)
+          {
+            printf("Arithmetic: \n");
+            for(atmp=tmp->arith;atmp!=NULL;atmp=atmp->next)
               {
-                printf("Arithmetic: ");
-                if(atmp->constant) printf("Constant number\n");
-                else if(atmp->index) printf("Called column: %zu\n",
-                                            atmp->index);
-                else if(atmp->operator!=ARITHMETIC_TABLE_OP_INVALID)
-                  printf("Operator: %d\n", atmp->operator);
-                else
-                  error(EXIT_FAILURE, 0, "%s: UNKNOWN SITUATION!",
-                        __func__);
+                if(atmp->operator!=GAL_ARITHMETIC_OP_INVALID)
+                  {
+                    printf("\tOperator: %d\n", atmp->operator);
+                    if(atmp->name_def)
+                      printf("\t\t(Name definition: %s)\n", atmp->name_def);
+                  }
+                else if(atmp->constant) printf("\tConstant number\n");
+                else if(atmp->name_use) printf("\tName usage: %s\n",
+                                               atmp->name_use);
+                else printf("\tCalled column: %zu\n", atmp->index);
               }
-          else
-            printf("Simple: start: %zu, num: %zu\n", tmp->start,
-                   tmp->numsimple);
-        }
+          }
+        else
+          printf("Simple: start: %zu, num: %zu\n", tmp->start,
+                 tmp->numsimple);
     }
   */
 
-
   /* Delete the old list, then reverse the 'toread' list, and put it into
      'p->columns'. */
   gal_list_str_free(p->columns, 1);
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 02be9c2..02bf075 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -11847,7 +11847,7 @@ $ astarithmetic a.fits b.fits / -g1 –output=div.fits
 @end example
 
 @item %
-Modulo (remainder), so ``@command{3 2 %}'' is equivalent to @mymath{1}.
+Modulo (remainder), so ``@command{3 2 %}'' will return @mymath{1}.
 Note that the modulo operator only works on integer types (see @ref{Numeric 
data types}).
 This operator is therefore not defined for most processed astronomical 
astronomical images that have floating-point value.
 However it is useful in labeled images, for example @ref{Segment output}).
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 7071bf8..5b427c6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -68,11 +68,12 @@ libgnuastro_la_SOURCES = $(MAYBE_WCSDISTORTION) 
arithmetic.c \
   arithmetic-bitor.c arithmetic-bitrsh.c arithmetic-bitxor.c \
   arithmetic-divide.c arithmetic-eq.c arithmetic-ge.c arithmetic-gt.c \
   arithmetic-le.c arithmetic-lt.c arithmetic-minus.c arithmetic-modulo.c \
-  arithmetic-multiply.c arithmetic-ne.c arithmetic-or.c arithmetic-plus.c \
-  array.c binary.c blank.c box.c checkset.c convolve.c cosmology.c data.c \
-  eps.c fits.c git.c interpolate.c jpeg.c kdtree.c label.c list.c match.c \
-  options.c pdf.c permutation.c pointer.c polygon.c qsort.c dimension.c \
-  speclines.c statistics.c table.c tableintern.c threads.c tiff.c tile.c \
+  arithmetic-multiply.c arithmetic-ne.c arithmetic-or.c \
+  arithmetic-plus.c arithmetic-set.c array.c binary.c blank.c box.c \
+  checkset.c convolve.c cosmology.c data.c eps.c fits.c git.c \
+  interpolate.c jpeg.c kdtree.c label.c list.c match.c options.c pdf.c \
+  permutation.c pointer.c polygon.c qsort.c dimension.c speclines.c \
+  statistics.c table.c tableintern.c threads.c tiff.c tile.c \
   tile-internal.c timing.c txt.c type.c units.c wcs.c
 
 
@@ -117,11 +118,11 @@ EXTRA_DIST = gnuastro.pc.in $(headersdir)/README 
$(internaldir)/README \
   $(internaldir)/arithmetic-minus.h $(internaldir)/arithmetic-modulo.h \
   $(internaldir)/arithmetic-multiply.h $(internaldir)/arithmetic-ne.h \
   $(internaldir)/arithmetic-or.h $(internaldir)/arithmetic-plus.h \
-  $(internaldir)/checkset.h $(internaldir)/commonopts.h \
-  $(internaldir)/config.h.in $(internaldir)/fixedstringmacros.h \
-  $(internaldir)/options.h $(internaldir)/tableintern.h \
-  $(internaldir)/tile-internal.h $(internaldir)/timing.h \
-  $(internaldir)/wcsdistortion.h
+  $(internaldir)/arithmetic-set.h $(internaldir)/checkset.h \
+  $(internaldir)/commonopts.h $(internaldir)/config.h.in \
+  $(internaldir)/fixedstringmacros.h $(internaldir)/options.h \
+  $(internaldir)/tableintern.h $(internaldir)/tile-internal.h \
+  $(internaldir)/timing.h $(internaldir)/wcsdistortion.h
 
 
 
diff --git a/lib/arithmetic-set.c b/lib/arithmetic-set.c
new file mode 100644
index 0000000..24da3cb
--- /dev/null
+++ b/lib/arithmetic-set.c
@@ -0,0 +1,193 @@
+/*********************************************************************
+Arithmetic operations on data structures.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Mohammad Akhlaghi <mohammad@akhlaghi.org>
+Contributing author(s):
+Copyright (C) 2021, 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 <string.h>
+
+#include <gnuastro/list.h>
+
+#include <gnuastro-internal/checkset.h>
+#include <gnuastro-internal/arithmetic-set.h>
+
+
+
+
+
+/* Remove a name from the list of names and return the dataset it points
+   to. */
+static gal_data_t *
+arithmetic_set_remove_name(struct gal_arithmetic_set_params *p,
+                           char *name)
+{
+  gal_data_t *tmp, *removed=NULL, *prev=NULL;
+
+  /* Go over all the given names. */
+  for(tmp=p->named;tmp!=NULL;tmp=tmp->next)
+    {
+      if( !strcmp(tmp->name, name) )
+        {
+          removed=tmp;
+          if(prev) prev->next = tmp->next;
+          else     p->named   = tmp->next;
+        }
+
+      /* Set this node as the 'prev' pointer. */
+      prev=tmp;
+    }
+
+  /* A small sanity check. */
+  if(removed==NULL)
+    error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to "
+          "fix the problem. 'removed' must not be NULL at this point",
+          __func__, PACKAGE_BUGREPORT);
+
+  /* Nothing in the list points to it now. So we can safely modify and
+     return it. */
+  free(removed->name);
+  removed->next=NULL;
+  removed->name=NULL;
+  return removed;
+}
+
+
+
+
+
+/* Pop a dataset and keep it in the 'named' list for later use. */
+void
+gal_arithmetic_set_name(struct gal_arithmetic_set_params *p, char *token)
+{
+  gal_data_t *tmp, *tofree;
+  char *varname=&token[ GAL_ARITHMETIC_SET_PREFIX_LENGTH ];
+
+  /* If a dataset with this name already exists, it will be removed/deleted
+     so we can use the name for the newly designated dataset. */
+  for(tmp=p->named; tmp!=NULL; tmp=tmp->next)
+    if( !strcmp(varname, tmp->name) )
+      {
+        tofree=arithmetic_set_remove_name(p, varname);
+        gal_data_free(tofree);
+
+        /* IMPORTANT: we MUST break here! 'tmp' does't point to the right
+           place any more. We can define a 'prev' node and modify it on
+           every attempt, but since there is only one dataset with a given
+           name, that is redundant and will just make the program slow. */
+        break;
+      }
+
+  /* Pop the top operand, then add it to the list of named datasets, but
+     only if it is used in later tokens. If it isn't, free the popped
+     dataset. The latter case (to define a name, but not use it), is
+     obviously a redundant operation, but that is upto the user, we
+     shouldn't worry about it here. We should just have everything in
+     place, so no crashes occur or no extra memory is consumed. */
+  if( p->used_later(p, varname) )
+    {
+      /* Add the top popped operand to the list of names. */
+      gal_list_data_add(&p->named, p->pop(p));
+
+      /* Write the requested name into this dataset. But note that 'name'
+         MUST be already empty. So to be safe, we'll do a sanity check. */
+      if(p->named->name )
+        error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to "
+              "fix the problem. The 'name' element should be NULL at "
+              "this point, but it isn't", __func__, PACKAGE_BUGREPORT);
+      if(p->named->unit)    { free(p->named->unit);    p->named->unit=NULL;    
}
+      if(p->named->comment) { free(p->named->comment); p->named->comment=NULL; 
}
+      gal_checkset_allocate_copy(varname, &p->named->name);
+    }
+  else
+    {
+      /* Pop the top operand, then free it: for example the user has ran
+         'set-i', but forgot to actually use it (happens a lot due to human
+         error!). */
+      tmp=p->pop(p);
+      gal_data_free(tmp);
+    }
+}
+
+
+
+
+
+/* See if a given token is the name of a variable. */
+int
+gal_arithmetic_set_is_name(gal_data_t *named, char *token)
+{
+  gal_data_t *tmp;
+
+  /* Make sure the variable name hasn't been set before. */
+  for(tmp=named; tmp!=NULL; tmp=tmp->next)
+    if( !strcmp(token, tmp->name) )
+      return 1;
+
+  /* If control reaches here, then there was no match*/
+  return 0;
+}
+
+
+
+
+
+/* Return a copy of the named dataset. */
+gal_data_t *
+gal_arithmetic_set_copy_named(struct gal_arithmetic_set_params *p,
+                              char *name)
+{
+  gal_data_t *out=NULL, *tmp;
+
+  /* Find the proper named element to use. */
+  for(tmp=p->named;tmp!=NULL;tmp=tmp->next)
+    {
+    if( !strcmp(tmp->name, name) )
+      {
+        /* If the named operand is used later, then copy it into the
+           output. */
+        if( p->used_later(p, name) )
+          {
+            out=gal_data_copy(tmp);
+            out->next=NULL;
+            if(out->name)    { free(out->name);    out->name=NULL;    }
+            if(out->unit)    { free(out->unit);    out->unit=NULL;    }
+            if(out->comment) { free(out->comment); out->comment=NULL; }
+          }
+
+        /* The named operand is not used any more. Remove it from the list
+           of named datasets and continue. */
+        else out=arithmetic_set_remove_name(p, name);
+      }
+    }
+
+  /* A small sanity check. */
+  if(out==NULL)
+    error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s to fix the "
+          "problem. The requested name '%s' couldn't be found in the list",
+          __func__, PACKAGE_BUGREPORT, name);
+
+  /* Return. */
+  return out;
+}
diff --git a/lib/arithmetic.c b/lib/arithmetic.c
index 097da2d..91acdd6 100644
--- a/lib/arithmetic.c
+++ b/lib/arithmetic.c
@@ -1386,13 +1386,13 @@ arithmetic_multioperand(int operator, int flags, 
gal_data_t *list,
 
       /* Check the types. */
       if(tmp->type!=list->type)
-        error(EXIT_FAILURE, 0, "%s: the types of all operands to the %s "
+        error(EXIT_FAILURE, 0, "%s: the types of all operands to the '%s' "
               "operator must be same", __func__,
               gal_arithmetic_operator_string(operator));
 
       /* Check the sizes. */
       if( gal_dimension_is_different(list, tmp) )
-        error(EXIT_FAILURE, 0, "%s: the sizes of all operands to the %s "
+        error(EXIT_FAILURE, 0, "%s: the sizes of all operands to the '%s' "
               "operator must be same", __func__,
               gal_arithmetic_operator_string(operator));
     }
@@ -1543,8 +1543,8 @@ arithmetic_binary(int operator, int flags, gal_data_t *l, 
gal_data_t *r)
   /* Simple sanity check on the input sizes */
   if( !( (flags & GAL_ARITHMETIC_NUMOK) && (l->size==1 || r->size==1))
       && gal_dimension_is_different(l, r) )
-    error(EXIT_FAILURE, 0, "%s: the non-number inputs to %s don't have the "
-          "same dimension/size", __func__,
+    error(EXIT_FAILURE, 0, "%s: the non-number inputs to '%s' don't "
+          "have the same dimension/size", __func__,
           gal_arithmetic_operator_string(operator));
 
 
@@ -2029,7 +2029,7 @@ gal_arithmetic_operator_string(int operator)
     {
     case GAL_ARITHMETIC_OP_PLUS:            return "+";
     case GAL_ARITHMETIC_OP_MINUS:           return "-";
-    case GAL_ARITHMETIC_OP_MULTIPLY:        return "*";
+    case GAL_ARITHMETIC_OP_MULTIPLY:        return "x";
     case GAL_ARITHMETIC_OP_DIVIDE:          return "/";
     case GAL_ARITHMETIC_OP_MODULO:          return "%";
 
diff --git a/lib/gnuastro-internal/arithmetic-set.h 
b/lib/gnuastro-internal/arithmetic-set.h
new file mode 100644
index 0000000..69ded8b
--- /dev/null
+++ b/lib/gnuastro-internal/arithmetic-set.h
@@ -0,0 +1,51 @@
+/*********************************************************************
+Arithmetic operations on data structures.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Mohammad Akhlaghi <mohammad@akhlaghi.org>
+Contributing author(s):
+Copyright (C) 2021, 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 __ARITHMETIC_SET_H__
+#define __ARITHMETIC_SET_H__
+
+#define GAL_ARITHMETIC_SET_PREFIX         "set-"
+#define GAL_ARITHMETIC_SET_PREFIX_LENGTH  strlen(GAL_ARITHMETIC_SET_PREFIX)
+
+
+struct gal_arithmetic_set_params
+{
+  void               *tokens;   /* Full list of tokens.            */
+  size_t        tokencounter;   /* Counter of current token.       */
+  gal_data_t          *named;   /* List of named datasets.         */
+  void               *params;   /* Internal parameters in caller.  */
+  gal_data_t  * (*pop)(void *in_prm);  /* Function to use.         */
+  int (*used_later)(void *in_prm, char *name); /* Function to use. */
+};
+
+void
+gal_arithmetic_set_name(struct gal_arithmetic_set_params *p,
+                        char *token);
+
+int
+gal_arithmetic_set_is_name(gal_data_t *named, char *token);
+
+gal_data_t *
+gal_arithmetic_set_copy_named(struct gal_arithmetic_set_params *p,
+                              char *name);
+
+#endif



reply via email to

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