gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 5ae5309: Library (arithmetic.h): envseed imple


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 5ae5309: Library (arithmetic.h): envseed implemented as a flag
Date: Sun, 18 Apr 2021 17:33:31 -0400 (EDT)

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

    Library (arithmetic.h): envseed implemented as a flag
    
    Until now the 'envseed' setting was passed to the arithmetic operators that
    needed it as an extra dataset. But this was a very dirty and ugly solution
    for a very simple on-off situation (it needed the allocation of a dataset,
    and the subsequent checking of all the properties).
    
    With this commit, the 'envseed' setting is now defined as a new bit-flag in
    the 'flags' argument of the 'gal_arithmetic' function. This makes the code
    much more elegant, easier to read/parse and debug. I had completely forgot
    about flags when implementing the recently added 'mknoise-*' operators!
    
    In addition to the new 'GAL_ARITHMETIC_FLAG_ENVSEED', I also defined a new
    'GAL_ARITHMETIC_FLAG_QUIET' flag (to pass the '--quiet' option from the
    programs). Thanks to this, the new 'mknoise-*' operators now print the
    random number generator settings by default and this can be disabled with
    the '--quiet' option.
    
    In the process, I also done some better management of the arithmetic
    library flags:
    
     - Until now, the arithmetic flag macros had this format:
       'GAL_ARITHMETIC_*'. So it wasn't immediately clear that they are
       flags. With this commit, they now have this format:
       'GAL_ARITHMETIC_FLAG_*'.
    
     - In a few places, instead of the 'GAL_ARITHMETIC_FLAGS_BASIC', I was
       actually using the three flags that it points to. So to simplify things,
       I am just using the single wrapper macro now.
---
 NEWS                        |  13 ++++-
 bin/arithmetic/arithmetic.c |  20 +++-----
 bin/convertt/convertt.c     |  14 +++---
 bin/convertt/ui.c           |   3 +-
 bin/convolve/ui.c           |   6 ++-
 bin/mkcatalog/ui.c          |   4 +-
 bin/statistics/contour.c    |   2 +-
 bin/statistics/ui.c         |  10 ++--
 bin/table/arithmetic.c      |  19 ++------
 bin/table/table.c           |  10 ++--
 doc/gnuastro.texi           |  70 +++++++++++++++------------
 lib/arithmetic.c            | 113 ++++++++++++++++++++------------------------
 lib/gnuastro/arithmetic.h   |  18 +++----
 lib/options.c               |  10 ++--
 14 files changed, 152 insertions(+), 160 deletions(-)

diff --git a/NEWS b/NEWS
index a8ad81f..ec73b6f 100644
--- a/NEWS
+++ b/NEWS
@@ -141,8 +141,6 @@ See the end of the file for license conditions.
          astquery ned --dataset=extinction --center=49.9507,41.5116
 
   Library:
-   - gal_units_counts_to_mag: Convert counts to magnitudes.
-   - gal_units_counts_to_jy: Convert counts to Janskys.
    - New arithmetic operator macros (for the 'gal_arithmetic' function):
      - GAL_ARITHMETIC_OP_SIN: sine (input in deg).
      - GAL_ARITHMETIC_OP_COS: cosine (input in deg).
@@ -157,7 +155,12 @@ See the end of the file for license conditions.
      - GAL_ARITHMETIC_OP_ASINH: Inverse hyperbolic sine.
      - GAL_ARITHMETIC_OP_ACOSH: Inverse hyperbolic cosine.
      - GAL_ARITHMETIC_OP_ATANH: Inverse hyperbolic tangent.
+     - GAL_ARITHMETIC_OP_MKNOISE_SIGMA: Add fixed-sigma noise.
+     - GAL_ARITHMETIC_OP_MKNOISE_POISSON: Add Poisson noise.
      - GAL_ARITHMETIC_OP_COUNTS_TO_JY: Convert counts to Janskys.
+   - New arithmetic flag macros:
+     - GAL_ARITHMETIC_FLAG_ENVSEED: read random number generator seed from env.
+     - GAL_ARITHMETIC_FLAG_QUIET: don't print any warnings by some operators.
    - WCS coordinate system identifiers:
      - GAL_WCS_COORDSYS_EQB1950: 1950.0 (Besselian-year) equatorial coords.
      - GAL_WCS_COORDSYS_EQJ2000: 2000.0 (Julian-year) equatorial coords.
@@ -165,6 +168,8 @@ See the end of the file for license conditions.
      - GAL_WCS_COORDSYS_ECJ2000: 2000.0 (Julian-year) ecliptic coords.
      - GAL_WCS_COORDSYS_GALACTIC: Galactic coordinates.
      - GAL_WCS_COORDSYS_SUPERGALACTIC: Supergalactic coordinates.
+   - gal_units_counts_to_mag: Convert counts to magnitudes.
+   - gal_units_counts_to_jy: Convert counts to Janskys.
    - gal_wcs_coordsys_from_string: WCS coordinate system from string.
    - gal_wcs_coordsys_identify: Parse WCS struct to find  coordinate system.
    - gal_wcs_coordsys_convert: Convert the coordinate system of the WCS.
@@ -195,6 +200,10 @@ See the end of the file for license conditions.
      'UPNUMBER', 'UPRNGNAM', 'UPRNGSEE', 'UPSCMLTP', 'UPSCTOL'.
 
   Library:
+   - GAL_ARITHMETIC_FLAG_FREE new name for GAL_ARITHMETIC_FREE.
+   - GAL_ARITHMETIC_FLAG_NUMOK new name for GAL_ARITHMETIC_NUMOK.
+   - GAL_ARITHMETIC_FLAG_INPLACE new name for GAL_ARITHMETIC_INPLACE.
+   - GAL_ARITHMETIC_FLAGS_BASIC new name for GAL_ARITHMETIC_FLAGS_ALL.
    - gal_fits_key_write_wcsstr: also takes WCS structure as argument.
    - gal_fits_key_read_from_ptr: providing a numerical datatype for the
      desired keyword's value is no longer mandatory. When not given, the
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index d8c2343..89b6dd4 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -1217,11 +1217,14 @@ static void
 arithmetic_operator_run(struct arithmeticparams *p, int operator,
                         char *operator_string, size_t num_operands)
 {
-  size_t i, one=1;
+  size_t i;
   unsigned int numop;
+  int flags = GAL_ARITHMETIC_FLAGS_BASIC;
   gal_data_t *d1=NULL, *d2=NULL, *d3=NULL;
-  int flags = ( GAL_ARITHMETIC_INPLACE | GAL_ARITHMETIC_FREE
-                | GAL_ARITHMETIC_NUMOK );
+
+  /* Set the operating-mode flags if necessary. */
+  if(p->cp.quiet) flags |= GAL_ARITHMETIC_FLAG_QUIET;
+  if(p->envseed)  flags |= GAL_ARITHMETIC_FLAG_ENVSEED;
 
   /* When 'num_operands!=0', the operator is in the library. */
   if(num_operands)
@@ -1267,17 +1270,6 @@ arithmetic_operator_run(struct arithmeticparams *p, int 
operator,
                 num_operands, operator_string);
         }
 
-      /* Save 'envseed' as third operand if necessary. */
-      switch(operator)
-        {
-        case GAL_ARITHMETIC_OP_MKNOISE_SIGMA:
-        case GAL_ARITHMETIC_OP_MKNOISE_POISSON:
-          d3=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, &one, NULL, 0, -1, 1,
-                            NULL, NULL, NULL);
-          ((uint8_t *)(d3->array))[0]=p->envseed;
-          break;
-        }
-
       /* Run the arithmetic operation. Note that 'gal_arithmetic'
          is a variable argument function (like printf). So the
          number of arguments it uses depend on the operator. So
diff --git a/bin/convertt/convertt.c b/bin/convertt/convertt.c
index 64bdd45..1fa86da 100644
--- a/bin/convertt/convertt.c
+++ b/bin/convertt/convertt.c
@@ -59,9 +59,7 @@ convertt_change(struct converttparams *p)
 {
   gal_data_t *channel, *cond;
   struct change *change, *tmp;
-  unsigned char flags = ( GAL_ARITHMETIC_NUMOK
-                          | GAL_ARITHMETIC_FREE
-                          | GAL_ARITHMETIC_INPLACE );
+  unsigned char flags = GAL_ARITHMETIC_FLAGS_BASIC;
 
   /* In case there is no value to convert. */
   if(p->change==NULL) return;
@@ -72,8 +70,9 @@ convertt_change(struct converttparams *p)
       {
         /* Make a condition array: all pixels with a value equal to
            'change->from' will be set as 1 in this array. */
-        cond=gal_arithmetic(GAL_ARITHMETIC_OP_EQ, 1, GAL_ARITHMETIC_NUMOK,
-                            channel, change->from);
+        cond=gal_arithmetic(GAL_ARITHMETIC_OP_EQ, 1,
+                            GAL_ARITHMETIC_FLAG_NUMOK, channel,
+                            change->from);
 
         /* Now, use the condition array to set the proper values. */
         channel=gal_arithmetic(GAL_ARITHMETIC_OP_WHERE, 1, flags, channel,
@@ -99,12 +98,13 @@ convertt_trunc_function(int operator, gal_data_t *data, 
gal_data_t *value)
 
 
   /* Note that we need the fluxlow and fluxhigh values later. */
-  unsigned char flags = ( GAL_ARITHMETIC_NUMOK | GAL_ARITHMETIC_INPLACE );
+  unsigned char flags = ( GAL_ARITHMETIC_FLAG_NUMOK
+                          | GAL_ARITHMETIC_FLAG_INPLACE );
 
 
   /* Make a condition array: all pixels with a value equal to
      'change->from' will be set as 1 in this array. */
-  cond=gal_arithmetic(operator, 1, GAL_ARITHMETIC_NUMOK, data, value);
+  cond=gal_arithmetic(operator, 1, GAL_ARITHMETIC_FLAG_NUMOK, data, value);
 
 
   /* Now, use the condition array to set the proper values. */
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index 219e39e..3602ffa 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -337,7 +337,8 @@ ui_read_check_only_options(struct converttparams *p)
 
   if(p->fluxhighstr && p->fluxlowstr)
     {
-      cond=gal_arithmetic(GAL_ARITHMETIC_OP_GT, 1, GAL_ARITHMETIC_NUMOK,
+      cond=gal_arithmetic(GAL_ARITHMETIC_OP_GT, 1,
+                          GAL_ARITHMETIC_FLAG_NUMOK,
                           p->fluxhigh, p->fluxlow);
 
       if( *((unsigned char *)cond->array) == 0 )
diff --git a/bin/convolve/ui.c b/bin/convolve/ui.c
index 2c2582f..3fb32db 100644
--- a/bin/convolve/ui.c
+++ b/bin/convolve/ui.c
@@ -580,11 +580,13 @@ ui_preparations(struct convolveparams *p)
           sum=gal_statistics_sum(p->input);
           sum=gal_data_copy_to_new_type_free(sum, GAL_TYPE_FLOAT32);
           p->input = gal_arithmetic(GAL_ARITHMETIC_OP_DIVIDE, 1,
-                                    GAL_ARITHMETIC_FLAGS_ALL, p->input, sum);
+                                    GAL_ARITHMETIC_FLAGS_BASIC, p->input,
+                                    sum);
           sum=gal_statistics_sum(p->kernel);
           sum=gal_data_copy_to_new_type_free(sum, GAL_TYPE_FLOAT32);
           p->kernel = gal_arithmetic(GAL_ARITHMETIC_OP_DIVIDE, 1,
-                                     GAL_ARITHMETIC_FLAGS_ALL, p->kernel, sum);
+                                     GAL_ARITHMETIC_FLAGS_BASIC,
+                                     p->kernel, sum);
         }
     }
 
diff --git a/bin/mkcatalog/ui.c b/bin/mkcatalog/ui.c
index aa88388..c111919 100644
--- a/bin/mkcatalog/ui.c
+++ b/bin/mkcatalog/ui.c
@@ -1389,9 +1389,7 @@ ui_preparations_read_inputs(struct mkcatalogparams *p)
           zero=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, &one, NULL, 1, -1,
                               1, NULL, NULL, NULL);
           p->upmask=gal_arithmetic(GAL_ARITHMETIC_OP_NE, 1,
-                                   ( GAL_ARITHMETIC_INPLACE
-                                     | GAL_ARITHMETIC_FREE
-                                     | GAL_ARITHMETIC_NUMOK ),
+                                   GAL_ARITHMETIC_FLAGS_BASIC,
                                    p->upmask, zero);
         }
     }
diff --git a/bin/statistics/contour.c b/bin/statistics/contour.c
index 991799e..c8ff95b 100644
--- a/bin/statistics/contour.c
+++ b/bin/statistics/contour.c
@@ -43,7 +43,7 @@ contour_pixels(gal_data_t *input, double level, size_t 
minmapsize,
 {
   size_t one=1;
   uint8_t *b, *a, *af;
-  int flags=GAL_ARITHMETIC_NUMOK;
+  int flags=GAL_ARITHMETIC_FLAG_NUMOK;
   gal_data_t *number, *thresh, *eroded;
 
   /* Allocate the single-element dataset to use in arithmetic.*/
diff --git a/bin/statistics/ui.c b/bin/statistics/ui.c
index 7c2b7fc..96232c9 100644
--- a/bin/statistics/ui.c
+++ b/bin/statistics/ui.c
@@ -587,9 +587,9 @@ static void
 ui_out_of_range_to_blank(struct statisticsparams *p)
 {
   size_t one=1;
-  unsigned char flags=GAL_ARITHMETIC_NUMOK;
-  unsigned char flagsor = ( GAL_ARITHMETIC_INPLACE
-                            | GAL_ARITHMETIC_NUMOK );
+  unsigned char flags=GAL_ARITHMETIC_FLAG_NUMOK;
+  unsigned char flagsor = ( GAL_ARITHMETIC_FLAG_INPLACE
+                            | GAL_ARITHMETIC_FLAG_NUMOK );
   gal_data_t *tmp, *tmp2, *cond_g=NULL, *cond_l=NULL, *cond, *blank, *ref;
 
 
@@ -953,13 +953,11 @@ ui_read_columns(struct statisticsparams *p)
 void
 ui_preparations(struct statisticsparams *p)
 {
-  unsigned char flagsor = ( GAL_ARITHMETIC_FREE
-                            | GAL_ARITHMETIC_INPLACE
-                            | GAL_ARITHMETIC_NUMOK );
   int keepinputdir=p->cp.keepinputdir;
   gal_data_t *check, *flag1, *flag2, *flag;
   struct gal_options_common_params *cp=&p->cp;
   struct gal_tile_two_layer_params *tl=&cp->tl;
+  unsigned char flagsor = GAL_ARITHMETIC_FLAGS_BASIC;
   char *checkbasename = p->cp.output ? p->cp.output : p->inputname;
 
   /* Change 'keepinputdir' based on if an output name was given. */
diff --git a/bin/table/arithmetic.c b/bin/table/arithmetic.c
index d06baae..3da9a50 100644
--- a/bin/table/arithmetic.c
+++ b/bin/table/arithmetic.c
@@ -769,10 +769,12 @@ arithmetic_operator_run(struct tableparams *p,
                         struct gal_arithmetic_set_params *setprm,
                         gal_data_t **stack)
 {
-  size_t one=1;
+  int flags=GAL_ARITHMETIC_FLAGS_BASIC;
   gal_data_t *d1=NULL, *d2=NULL, *d3=NULL;
-  int flags = ( GAL_ARITHMETIC_INPLACE | GAL_ARITHMETIC_FREE
-                | GAL_ARITHMETIC_NUMOK );
+
+  /* Set the operating-mode flags if necessary. */
+  if(p->cp.quiet) flags |= GAL_ARITHMETIC_FLAG_QUIET;
+  if(p->envseed)  flags |= GAL_ARITHMETIC_FLAG_ENVSEED;
 
   /* When 'num_operands!=0', the operator is in the library. */
   if(token->num_operands)
@@ -813,17 +815,6 @@ arithmetic_operator_run(struct tableparams *p,
                 arithmetic_operator_name(token->operator));
         }
 
-      /* Save 'envseed' as third operand if necessary. */
-      switch(token->operator)
-        {
-        case GAL_ARITHMETIC_OP_MKNOISE_SIGMA:
-        case GAL_ARITHMETIC_OP_MKNOISE_POISSON:
-          d3=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, &one, NULL, 0, -1, 1,
-                            NULL, NULL, NULL);
-          ((uint8_t *)(d3->array))[0]=p->envseed;
-          break;
-        }
-
       /* Run the arithmetic operation. Note that 'gal_arithmetic' is a
          variable argument function (like printf). So the number of
          arguments it uses depend on the operator. In other words, when the
diff --git a/bin/table/table.c b/bin/table/table.c
index 912e408..6e48ab1 100644
--- a/bin/table/table.c
+++ b/bin/table/table.c
@@ -133,8 +133,8 @@ table_selection_range(struct tableparams *p, gal_data_t 
*col)
 {
   size_t one=1;
   double *darr;
-  int numok=GAL_ARITHMETIC_NUMOK;
-  int inplace=GAL_ARITHMETIC_INPLACE;
+  int numok=GAL_ARITHMETIC_FLAG_NUMOK;
+  int inplace=GAL_ARITHMETIC_FLAG_INPLACE;
   gal_data_t *min=NULL, *max=NULL, *tmp, *ltmin, *gemax=NULL;
 
   /* First, make sure everything is OK. */
@@ -304,8 +304,8 @@ table_selection_equal_or_notequal(struct tableparams *p, 
gal_data_t *col,
   void *varr;
   char **strarr;
   size_t i, one=1;
-  int numok=GAL_ARITHMETIC_NUMOK;
-  int inplace=GAL_ARITHMETIC_INPLACE;
+  int numok=GAL_ARITHMETIC_FLAG_NUMOK;
+  int inplace=GAL_ARITHMETIC_FLAG_INPLACE;
   gal_data_t *eq, *out=NULL, *value=NULL;
   gal_data_t *arg = e0n1 ? p->notequal : p->equal;
 
@@ -395,7 +395,7 @@ table_select_by_value(struct tableparams *p)
   struct list_select *tmp;
   uint8_t *u, *uf, *ustart;
   size_t i, *s, ngood=0;
-  int inplace=GAL_ARITHMETIC_INPLACE;
+  int inplace=GAL_ARITHMETIC_FLAG_INPLACE;
   gal_data_t *mask, *blmask, *addmask=NULL;
 
   /* Allocate datasets for the necessary numbers and write them in. */
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 55d6002..7a7bf2d 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -26177,33 +26177,40 @@ It can take an arbitrary number of arguments as 
operands (depending on the opera
 Its first two arguments are integers specifying the flags and operator.
 So first we will review the constants for the recognized flags and operators 
and discuss them, then introduce the actual function.
 
-@deffn  Macro GAL_ARITHMETIC_INPLACE
-@deffnx Macro GAL_ARITHMETIC_FREE
-@deffnx Macro GAL_ARITHMETIC_NUMOK
-@deffnx Macro GAL_ARITHMETIC_FLAGS_ALL
+@deffn  Macro GAL_ARITHMETIC_FLAG_INPLACE
+@deffnx Macro GAL_ARITHMETIC_FLAG_FREE
+@deffnx Macro GAL_ARITHMETIC_FLAG_NUMOK
+@deffnx Macro GAL_ARITHMETIC_FLAG_ENVSEED
+@deffnx Macro GAL_ARITHMETIC_FLAG_QUIET
+@deffnx Macro GAL_ARITHMETIC_FLAGS_BASIC
 @cindex Bitwise Or
-Bit-wise flags to pass onto @code{gal_arithmetic} (see below). To pass
-multiple flags, use the bitwise-or operator, for example
-@code{GAL_ARITHMETIC_INPLACE |
-GAL_ARITHMETIC_FREE}. @code{GAL_ARITHMETIC_FLAGS_ALL} is a combination of
-all flags to shorten your code if you want all flags activated. Each flag
-is described below:
+Bit-wise flags to pass onto @code{gal_arithmetic} (see below).
+To pass multiple flags, use the bitwise-or operator, for example 
@code{GAL_ARITHMETIC_FLAG_INPLACE | GAL_ARITHMETIC_FLAG_NUMOK}.
+Each flag is described below:
+
 @table @code
-@item GAL_ARITHMETIC_INPLACE
-Do the operation in-place (in the input dataset, thus modifying it) to
-improve CPU and memory usage. If this flag is used, after
-@code{gal_arithmetic} finishes, the input dataset will be modified. It is
-thus useful if you have no more need for the input after the operation.
-
-@item GAL_ARITHMETIC_FREE
-Free (all the) input dataset(s) after the operation is done. Hence the
-inputs are no longer usable after @code{gal_arithmetic}.
-
-@item GAL_ARITHMETIC_NUMOK
-It is acceptable to use a number and an array together. For example if you
-want to add all the pixels in an image with a single number you can pass
-this flag to avoid having to allocate a constant array the size of the
-image (with all the pixels having the same number).
+@item GAL_ARITHMETIC_FLAG_INPLACE
+Do the operation in-place (in the input dataset, thus modifying it) to improve 
CPU and memory usage. If this flag is used, after @code{gal_arithmetic} 
finishes, the input dataset will be modified. It is thus useful if you have no 
more need for the input after the operation.
+
+@item GAL_ARITHMETIC_FLAG_FREE
+Free (all the) input dataset(s) after the operation is done.
+Hence the inputs are no longer usable after @code{gal_arithmetic}.
+
+@item GAL_ARITHMETIC_FLAG_NUMOK
+It is acceptable to use a number and an array together.
+For example if you want to add all the pixels in an image with a single number 
you can pass this flag to avoid having to allocate a constant array the size of 
the image (with all the pixels having the same number).
+
+@item GAL_ARITHMETIC_FLAG_ENVSEED
+Use the pre-defined environment variable for setting the random number 
generator seed when an operator needs it (for example @code{mknoise-sigma}).
+For more on random number generation in Gnuastro see @ref{Generating random 
numbers}.
+
+@item GAL_ARITHMETIC_FLAG_QUIET
+Don't print any warnings or messages for operators that may benefit from it.
+For example by default the @code{mknoise-sigma} operator prints the random 
number generator function and seed that it used (in case the user wants to 
reproduce this result later).
+By activating this bit flag to the call, that extra information is not printed 
on the command-line.
+
+@item GAL_ARITHMETIC_FLAGS_BASIC
+A wrapper for activating all three of @code{GAL_ARITHMETIC_FLAG_INPLACE}, 
@code{GAL_ARITHMETIC_FLAG_FREE} and @code{GAL_ARITHMETIC_FLAG_NUMOK}.
 @end table
 @end deffn
 
@@ -26384,10 +26391,15 @@ for the rest it will be @code{GAL_TYPE_FLOAT32}.
 @deffn  Macro GAL_ARITHMETIC_OP_MKNOISE_SIGMA
 @deffnx Macro GAL_ARITHMETIC_OP_MKNOISE_POISSON
 Add noise to the input dataset.
-Both operators take three arguments: the first is the input data set (can have 
any dimensionality or number of elements.
+Both operators take two arguments: the first is the input data set (can have 
any dimensionality or number of elements.
 The second argument is the noise specifier (a single element, of any type): 
for a fixed-sigma noise, it is the Gaussian standard deviation, for the Poisson 
noise, it is the background (see @ref{Photon counting noise}).
-The third argument should a dataset with only one element, a 
@code{GAL_TYPE_UINT8} type and only two acceptable values 0 (to signifiy that 
the random number generator, RNG, seed can be automatically set for each run) 
and 1 (to signify that the RNG seed should be read from the @code{GAL_RNG_SEED} 
environment variable for a reproducible result).
-For more on setting the RNG seed, see @ref{Generating random numbers}.
+
+By default, a separate random number generator seed will be used on each 
separate run of these operators.
+Therefore two identical runs on the same input will produce different results.
+You can get reproducible results by setting the @code{GAL_RNG_SEED} 
environment variable and activating the @code{GAL_ARITHMETIC_FLAG_ENVSEED} flag.
+For more on random number generation in Gnuastro, see @ref{Generating random 
numbers}.
+
+By default these operators will print the random number generator function and 
seed (in case the user wants to reproduce the result later), but this can be 
disabled by activating the bit-flag @code{GAL_ARITHMETIC_FLAG_QUIET} described 
above.
 @end deffn
 
 @deffn Macro GAL_ARITHMETIC_OP_SIZE
@@ -26462,7 +26474,7 @@ multiple threads, the number of threads can be 
specified with
 @code{numthreads}. When the operator is single-threaded, @code{numthreads}
 will be ignored. Special conditions can also be specified with the
 @code{flag} operator (a bit-flag with bits described above, for example
-@code{GAL_ARITHMETIC_INPLACE} or @code{GAL_ARITHMETIC_FREE}). The
+@code{GAL_ARITHMETIC_FLAG_INPLACE} or @code{GAL_ARITHMETIC_FLAG_FREE}). The
 acceptable values for @code{operator} are also defined in the macros above.
 
 @code{gal_arithmetic} is a multi-argument function (like C's
diff --git a/lib/arithmetic.c b/lib/arithmetic.c
index cae5345..6ee39e6 100644
--- a/lib/arithmetic.c
+++ b/lib/arithmetic.c
@@ -157,7 +157,7 @@ arithmetic_change_type(gal_data_t *data, int operator, int 
flags)
   out=gal_data_copy_to_new_type(data, type);
 
   /* Delete the input structure if the user asked for it. */
-  if(flags & GAL_ARITHMETIC_FREE)
+  if(flags & GAL_ARITHMETIC_FLAG_FREE)
     gal_data_free(data);
 
   /* Return */
@@ -212,7 +212,7 @@ arithmetic_not(gal_data_t *data, int flags)
     }
 
   /* Delete the input structure if the user asked for it. */
-  if(flags & GAL_ARITHMETIC_FREE)
+  if(flags & GAL_ARITHMETIC_FLAG_FREE)
     gal_data_free(data);
 
   /* Return */
@@ -248,7 +248,7 @@ arithmetic_bitwise_not(int flags, gal_data_t *in)
 
   /* If we want inplace output, set the output pointer to the input
      pointer, for every pixel, the operation will be independent. */
-  if(flags & GAL_ARITHMETIC_INPLACE)
+  if(flags & GAL_ARITHMETIC_FLAG_INPLACE)
     o = in;
   else
     o = gal_data_alloc(NULL, in->type, in->ndim, in->dsize, in->wcs,
@@ -288,7 +288,7 @@ arithmetic_bitwise_not(int flags, gal_data_t *in)
 
 
   /* Clean up (if necessary). */
-  if( (flags & GAL_ARITHMETIC_FREE) && o!=in)
+  if( (flags & GAL_ARITHMETIC_FLAG_FREE) && o!=in)
     gal_data_free(in);
 
   /* Return */
@@ -313,7 +313,7 @@ arithmetic_abs(int flags, gal_data_t *in)
   gal_data_t *out;
 
   /* Set the output array. */
-  if(flags & GAL_ARITHMETIC_INPLACE)
+  if(flags & GAL_ARITHMETIC_FLAG_INPLACE)
     out=in;
   else
     out = gal_data_alloc(NULL, in->type, in->ndim, in->dsize,
@@ -348,7 +348,7 @@ arithmetic_abs(int flags, gal_data_t *in)
     }
 
   /* Clean up and return */
-  if( (flags & GAL_ARITHMETIC_FREE) && out!=in)
+  if( (flags & GAL_ARITHMETIC_FLAG_FREE) && out!=in)
     gal_data_free(in);
   return out;
 }
@@ -505,7 +505,7 @@ arithmetic_function_unary(int operator, int flags, 
gal_data_t *in)
      operators is defined in the floating point space. So even if the input
      is integer type and user requested inplace opereation, if its not a
      floating point type, it will not be in-place. */
-  if( (flags & GAL_ARITHMETIC_INPLACE)
+  if( (flags & GAL_ARITHMETIC_FLAG_INPLACE)
       && ( in->type==GAL_TYPE_FLOAT32 || in->type==GAL_TYPE_FLOAT64 )
       && ( operator != GAL_ARITHMETIC_OP_RA_TO_DEGREE
       &&   operator != GAL_ARITHMETIC_OP_DEC_TO_DEGREE
@@ -597,7 +597,7 @@ arithmetic_function_unary(int operator, int flags, 
gal_data_t *in)
      types weren't compiled for binary operations, we can tell this from
      the pointers: if they are different from the original pointers, they
      were allocated. */
-  if( (flags & GAL_ARITHMETIC_FREE) && o!=in)
+  if( (flags & GAL_ARITHMETIC_FLAG_FREE) && o!=in)
     gal_data_free(in);
 
   /* Return */
@@ -613,7 +613,7 @@ static gal_data_t *
 arithmetic_from_statistics(int operator, int flags, gal_data_t *input)
 {
   gal_data_t *out=NULL;
-  int ip=(flags & GAL_ARITHMETIC_INPLACE) || (flags & GAL_ARITHMETIC_FREE);
+  int ip=(flags & GAL_ARITHMETIC_FLAG_INPLACE) || (flags & 
GAL_ARITHMETIC_FLAG_FREE);
 
   switch(operator)
     {
@@ -631,7 +631,7 @@ arithmetic_from_statistics(int operator, int flags, 
gal_data_t *input)
     }
 
   /* If the input is to be freed, then do so and return the output. */
-  if( flags & GAL_ARITHMETIC_FREE ) gal_data_free(input);
+  if( flags & GAL_ARITHMETIC_FLAG_FREE ) gal_data_free(input);
   return out;
 }
 
@@ -660,17 +660,14 @@ arithmetic_from_statistics(int operator, int flags, 
gal_data_t *input)
 
 /* The size operator. Reports the size along a given dimension. */
 static gal_data_t *
-arithmetic_mknoise(int operator, int flags, gal_data_t *in, gal_data_t *arg,
-                   gal_data_t *envseed_in)
+arithmetic_mknoise(int operator, int flags, gal_data_t *in, gal_data_t *arg)
 {
   gsl_rng *rng;
-  uint8_t *envseed;
   const char *rng_name;
   double *d, *df, arg_v;
   unsigned long rng_seed;
   gal_data_t *out, *targ;
 
-
   /* Sanity checks. */
   if(arg->size!=1)
     error(EXIT_FAILURE, 0, "the first popped operand to the '%s' "
@@ -679,30 +676,11 @@ arithmetic_mknoise(int operator, int flags, gal_data_t 
*in, gal_data_t *arg,
           "has %zu elements, in %zu dimension(s)",
           gal_arithmetic_operator_string(operator), arg->size,
           arg->ndim);
-  if(envseed_in->size!=1)
-    error(EXIT_FAILURE, 0, "the third popped operand to the '%s' "
-          "operator should be a single number (with a value of 0 "
-          "or 1, specifying if the environment should be used for "
-          "the random number generator settings), but it has %zu "
-          "elements, in %zu dimension(s)",
-          gal_arithmetic_operator_string(operator), arg->size,
-          arg->ndim);
-  if(envseed_in->type!=GAL_TYPE_UINT8)
-    error(EXIT_FAILURE, 0, "the third popped operand to the '%s' "
-          "operator should have a type of 'uint8' (with "
-          "a value of 0 or 1, specifying if the environment should "
-          "be used for the random number generator settings), but "
-          "it has a type of '%s'",
-          gal_arithmetic_operator_string(operator),
-          gal_type_name(envseed_in->type, 1));
-  envseed=envseed_in->array;
-  if( *envseed>1 )
-    error(EXIT_FAILURE, 0, "the third popped operand to the '%s' "
-          "operator should only have a value of 0 or 1 (specifying "
-          "if the environment should be used for the random number "
-          "generator settings), but it has a value of %u",
-          gal_arithmetic_operator_string(operator), *envseed);
-
+  if(in->type==GAL_TYPE_STRING)
+    error(EXIT_FAILURE, 0, "the input dataset to the '%s' operator "
+          "should have a numerical data type (integer or float), but "
+          "it has a string type",
+          gal_arithmetic_operator_string(operator));
 
   /* Convert the input and argument into 'double' (and immediately free it
      if it is no longer necessary). */
@@ -710,24 +688,38 @@ arithmetic_mknoise(int operator, int flags, gal_data_t 
*in, gal_data_t *arg,
   else
     {
       out=gal_data_copy_to_new_type(in, GAL_TYPE_FLOAT64);
-      if(flags & GAL_ARITHMETIC_FREE)
+      if(flags & GAL_ARITHMETIC_FLAG_FREE)
         { gal_data_free(in); in=NULL; }
     }
   targ=gal_data_copy_to_new_type(arg, GAL_TYPE_FLOAT64);
   arg_v=((double *)(targ->array))[0];
   gal_data_free(targ);
 
-
   /* Make sure the noise identifier is positive. */
   if(arg_v<0)
     error(EXIT_FAILURE, 0, "the noise identifier (sigma for "
           "'mknoise-sigma' or background for 'mknoise-poisson') must "
           "be positive (it is %g)", arg_v);
 
-
-  /* Setup the random number generator. */
-  rng=gal_checkset_gsl_rng(*envseed, &rng_name, &rng_seed);
-
+  /* Setup the random number generator. For 'envseed', we want to pass a
+     boolean value: either 0 or 1. However, when we say 'flags &
+     GAL_ARITHMETIC_ENVSEED', the returned value is the integer positioning
+     of the envseed bit (for example if its on the fourth bit, the value
+     will be 8). This can cause problems if it is on the 8th bit (or any
+     multiple of 8). So to avoid issues with the bit-positioning of the
+     'ENVSEED', we will return the conditional to see if the result of the
+     bit-wise '&' is larger than 0 or not (binary). */
+  rng=gal_checkset_gsl_rng( (flags & GAL_ARITHMETIC_FLAG_ENVSEED)>0,
+                            &rng_name, &rng_seed);
+
+  /* Print the basic RNG information if requested. */
+  if( (flags & GAL_ARITHMETIC_FLAG_QUIET)==0 )
+    {
+      printf(" - Parameters used for '%s':\n",
+             gal_arithmetic_operator_string(operator));
+      printf("   - Random number generator name: %s\n", rng_name);
+      printf("   - Random number generator seed: %lu\n", rng_seed);
+    }
 
   /* Add the noise. */
   df=(d=out->array)+out->size;
@@ -748,11 +740,7 @@ arithmetic_mknoise(int operator, int flags, gal_data_t 
*in, gal_data_t *arg,
     }
 
   /* Clean up and return */
-  if(flags & GAL_ARITHMETIC_FREE)
-    {
-      gal_data_free(arg);
-      gal_data_free(envseed_in);
-    }
+  if(flags & GAL_ARITHMETIC_FLAG_FREE) gal_data_free(arg);
   return out;
 }
 
@@ -798,7 +786,7 @@ arithmetic_size(int operator, int flags, gal_data_t *in, 
gal_data_t *arg)
   /* Convert 'arg' to 'size_t' and read it. Note that we can only free the
      'arg' array (while changing its type), when the freeing flag has been
      set. */
-  if(flags & GAL_ARITHMETIC_FREE)
+  if(flags & GAL_ARITHMETIC_FLAG_FREE)
     {
       arg=gal_data_copy_to_new_type_free(arg, GAL_TYPE_SIZE_T);
       arg_val=*(size_t *)(arg->array);
@@ -833,7 +821,7 @@ arithmetic_size(int operator, int flags, gal_data_t *in, 
gal_data_t *arg)
 
 
   /* Clean up and return */
-  if(flags & GAL_ARITHMETIC_FREE)
+  if(flags & GAL_ARITHMETIC_FLAG_FREE)
     gal_data_free(in);
   return out;
 }
@@ -950,7 +938,7 @@ arithmetic_where(int flags, gal_data_t *out, gal_data_t 
*cond,
     }
 
   /* Clean up if necessary. */
-  if(flags & GAL_ARITHMETIC_FREE)
+  if(flags & GAL_ARITHMETIC_FLAG_FREE)
     {
       gal_data_free(cond);
       gal_data_free(iftrue);
@@ -1558,7 +1546,7 @@ arithmetic_multioperand(int operator, int flags, 
gal_data_t *list,
 
 
   /* Set the output data structure. */
-  if( (flags & GAL_ARITHMETIC_INPLACE) && otype==list->type)
+  if( (flags & GAL_ARITHMETIC_FLAG_INPLACE) && otype==list->type)
     out = list;                 /* The top element in the list. */
   else
     out = gal_data_alloc(NULL, otype, list->ndim, list->dsize,
@@ -1592,7 +1580,7 @@ arithmetic_multioperand(int operator, int flags, 
gal_data_t *list,
      before freeing each data structure. If we are on the designated output
      dataset, we should set its 'next' pointer to NULL so it isn't treated
      as a list any more by future functions. */
-  if(flags & GAL_ARITHMETIC_FREE)
+  if(flags & GAL_ARITHMETIC_FLAG_FREE)
     {
       tmp=list;
       while(tmp!=NULL)
@@ -1685,7 +1673,7 @@ 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))
+  if( !( (flags & GAL_ARITHMETIC_FLAG_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__,
@@ -1709,7 +1697,7 @@ arithmetic_binary(int operator, int flags, gal_data_t *l, 
gal_data_t *r)
 
   /* 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_ARITHMETIC_INPLACE)
+  if(flags & GAL_ARITHMETIC_FLAG_INPLACE)
     {
       if     (l->type==otype && out_size==l->size)   o = l;
       else if(r->type==otype && out_size==r->size)   o = r;
@@ -1763,7 +1751,7 @@ arithmetic_binary(int operator, int flags, gal_data_t *l, 
gal_data_t *r)
 
   /* Clean up if necessary. Note that if the operation was requested to be
      in place, then the output might be one of the inputs. */
-  if(flags & GAL_ARITHMETIC_FREE)
+  if(flags & GAL_ARITHMETIC_FLAG_FREE)
     {
       if     (o==l)       gal_data_free(r);
       else if(o==r)       gal_data_free(l);
@@ -1845,7 +1833,7 @@ arithmetic_function_binary_flt(int operator, int flags, 
gal_data_t *il,
   int quietmmap=il->quietmmap && ir->quietmmap;
 
   /* Simple sanity check on the input sizes */
-  if( !( (flags & GAL_ARITHMETIC_NUMOK) && (il->size==1 || ir->size==1))
+  if( !( (flags & GAL_ARITHMETIC_FLAG_NUMOK) && (il->size==1 || ir->size==1))
       && gal_dimension_is_different(il, ir) )
     error(EXIT_FAILURE, 0, "%s: the input datasets don't have the same "
           "dimension/size", __func__);
@@ -1872,7 +1860,7 @@ arithmetic_function_binary_flt(int operator, int flags, 
gal_data_t *il,
 
   /* 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_ARITHMETIC_INPLACE)
+  if(flags & GAL_ARITHMETIC_FLAG_INPLACE)
     {
       if     (l->type==final_otype && out_size==l->size)   o = l;
       else if(r->type==final_otype && out_size==r->size)   o = r;
@@ -1918,7 +1906,7 @@ arithmetic_function_binary_flt(int operator, int flags, 
gal_data_t *il,
      types weren't compiled for binary operations, we can tell this from
      the pointers: if they are different from the original pointers, they
      were allocated. */
-  if(flags & GAL_ARITHMETIC_FREE)
+  if(flags & GAL_ARITHMETIC_FLAG_FREE)
     {
       /* Clean the main used (temporarily allocated) datasets. */
       if     (o==l)       gal_data_free(r);
@@ -2359,7 +2347,7 @@ gal_arithmetic(int operator, size_t numthreads, int 
flags, ...)
     case GAL_ARITHMETIC_OP_ISBLANK:
       d1 = va_arg(va, gal_data_t *);
       out = gal_blank_flag(d1);
-      if(flags & GAL_ARITHMETIC_FREE) gal_data_free(d1);
+      if(flags & GAL_ARITHMETIC_FLAG_FREE) gal_data_free(d1);
       break;
 
     case GAL_ARITHMETIC_OP_WHERE:
@@ -2462,8 +2450,7 @@ gal_arithmetic(int operator, size_t numthreads, int 
flags, ...)
     case GAL_ARITHMETIC_OP_MKNOISE_POISSON:
       d1 = va_arg(va, gal_data_t *);
       d2 = va_arg(va, gal_data_t *);
-      d3 = va_arg(va, gal_data_t *);
-      out=arithmetic_mknoise(operator, flags, d1, d2, d3);
+      out=arithmetic_mknoise(operator, flags, d1, d2);
       break;
 
     /* Size operator */
diff --git a/lib/gnuastro/arithmetic.h b/lib/gnuastro/arithmetic.h
index ebe4e55..d8922f9 100644
--- a/lib/gnuastro/arithmetic.h
+++ b/lib/gnuastro/arithmetic.h
@@ -60,14 +60,16 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 
 
 
-/* Arithmetic flags. */
-#define GAL_ARITHMETIC_INPLACE  0x1
-#define GAL_ARITHMETIC_FREE     0x2
-#define GAL_ARITHMETIC_NUMOK    0x4
-
-#define GAL_ARITHMETIC_FLAGS_ALL ( GAL_ARITHMETIC_INPLACE        \
-                                   | GAL_ARITHMETIC_FREE         \
-                                   | GAL_ARITHMETIC_NUMOK )
+/* Arithmetic on-off bit flags (have to be powers of 2).  */
+#define GAL_ARITHMETIC_FLAG_INPLACE  1
+#define GAL_ARITHMETIC_FLAG_FREE     2
+#define GAL_ARITHMETIC_FLAG_NUMOK    4
+#define GAL_ARITHMETIC_FLAG_ENVSEED  8
+#define GAL_ARITHMETIC_FLAG_QUIET    16
+
+#define GAL_ARITHMETIC_FLAGS_BASIC ( GAL_ARITHMETIC_FLAG_INPLACE   \
+                                     | GAL_ARITHMETIC_FLAG_FREE    \
+                                     | GAL_ARITHMETIC_FLAG_NUMOK )
 
 
 /* Identifiers for each operator. */
diff --git a/lib/options.c b/lib/options.c
index ba51988..2ee3ab2 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -1575,13 +1575,11 @@ options_sanity_check(struct argp_option *option, char 
*arg,
 {
   size_t dsize=1;
   char *message=NULL;
+  int mcflag=GAL_ARITHMETIC_FLAGS_BASIC;
   int operator1=GAL_ARITHMETIC_OP_INVALID;
   int operator2=GAL_ARITHMETIC_OP_INVALID;
   int multicheckop=GAL_ARITHMETIC_OP_INVALID;
   gal_data_t *value, *ref1=NULL, *ref2=NULL, *check1, *check2;
-  int mcflag = ( GAL_ARITHMETIC_NUMOK
-                 | GAL_ARITHMETIC_FREE
-                 | GAL_ARITHMETIC_INPLACE );
 
   /* Currently, this function is only for numeric types, so if the value is
      string type, or its 'range' field is 'GAL_OPTIONS_RANGE_ANY', then
@@ -1719,10 +1717,12 @@ options_sanity_check(struct argp_option *option, char 
*arg,
      'GAL_ARITHMETIC_INPLACE' flags. But we will do this when there are
      multiple checks so from the two check data structures, we only have
      one remaining. */
-  check1=gal_arithmetic(operator1, 1, GAL_ARITHMETIC_NUMOK, value, ref1);
+  check1=gal_arithmetic(operator1, 1, GAL_ARITHMETIC_FLAG_NUMOK,
+                        value, ref1);
   if(ref2)
     {
-      check2=gal_arithmetic(operator2, 1, GAL_ARITHMETIC_NUMOK, value, ref2);
+      check2=gal_arithmetic(operator2, 1, GAL_ARITHMETIC_FLAG_NUMOK,
+                            value, ref2);
       check1=gal_arithmetic(multicheckop, 1, mcflag, check1, check2);
     }
 



reply via email to

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