gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master c368d8a: Linkedlist library changed to list un


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master c368d8a: Linkedlist library changed to list unified function names
Date: Thu, 27 Apr 2017 23:05:08 -0400 (EDT)

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

    Linkedlist library changed to list unified function names
    
    Set of linked list functions were added over time and based on necessity,
    so the weren't really too homogeous and for each type, the names were
    different. Also the functions to treat `gal_data_t' as a linked list were
    in the `data.h' header, not the linked list header. So with this commit,
    all linked list operations have been moved to the new `list.h' header (and
    `list.c' source file), and their names are now in the format of
    `gal_list_TYPE_ACTION' which is much more easier to remember/manage than
    the previous format of `gal_linkedlist_ACTION_CRYPTICTYPE' (since the type
    was short and not very clear).
    
    The old two-element double linked list has been removed with this
    commit. It was only used in reading polygon vertices in Crop (in
    `crop_polygonparser'), but now the same job is done more cleanly with an
    ordinary `double' type singly linked list. The Linked list section of the
    book/manual still needs some work, but the general context has been mostly
    done.
    
    Thanks to Guillaume Mahler, several warnings that showed up on Apple LLVM
    version 8.1.0 (clang-802.0.42), mainly to do with printing (u)int64, were
    also corrected in this commit. To solve it, we used the `inttypes.h'
    header, so it is now also imported from Gnulib.
    
    To parse over a tile, the `GAL_TILE_PARSE_OPERATE' works on all types. But
    in some situations, the type is already known, so to avoid compiler errors
    about, we are now directly using `GAL_TILE_PO_OISET'. This macro is now
    corrected to be self-sufficient (not rely on variables in the calling
    macro).
---
 bin/TEMPLATE/main.h             |    2 +-
 bin/arithmetic/arithmetic.c     |    6 +-
 bin/arithmetic/main.h           |    6 +-
 bin/arithmetic/operands.c       |    2 +-
 bin/arithmetic/ui.c             |    9 +-
 bin/convertt/jpeg.c             |    5 +-
 bin/convertt/main.h             |    6 +-
 bin/convertt/ui.c               |   29 +-
 bin/crop/crop.c                 |    6 +-
 bin/crop/main.h                 |    2 +-
 bin/crop/onecrop.c              |   31 +-
 bin/crop/ui.c                   |   37 +-
 bin/fits/fits.c                 |   33 +-
 bin/fits/keywords.c             |    4 +-
 bin/fits/main.h                 |   31 +-
 bin/fits/ui.c                   |    5 +-
 bin/mkcatalog/columns.c         |   23 +-
 bin/mkcatalog/main.h            |    4 +-
 bin/mkcatalog/mkcatalog.c       |   68 +-
 bin/mkcatalog/ui.c              |   13 +-
 bin/mknoise/ui.c                |    3 +-
 bin/mkprof/mkprof.c             |    6 +-
 bin/mkprof/oneprofile.c         |   17 +-
 bin/mkprof/ui.c                 |   56 +-
 bin/noisechisel/clumps.c        |   47 +-
 bin/noisechisel/detection.c     |   20 +-
 bin/noisechisel/segmentation.c  |   14 +-
 bin/noisechisel/threshold.c     |    6 +-
 bin/noisechisel/threshold.h     |    2 +-
 bin/statistics/main.h           |    4 +-
 bin/statistics/statistics.c     |   14 +-
 bin/statistics/ui.c             |   31 +-
 bin/table/main.h                |    2 +-
 bin/table/ui.c                  |    8 +-
 bin/warp/ui.c                   |    4 +-
 bootstrap.conf                  |    2 +
 doc/gnuastro.texi               | 1065 ++++++++++++++++++-------------
 lib/Makefile.am                 |   20 +-
 lib/arithmetic.c                |   45 +-
 lib/binary.c                    |   24 +-
 lib/blank.c                     |   49 +-
 lib/convolve.c                  |    3 +-
 lib/data.c                      |  216 +------
 lib/dimension.c                 |    2 +-
 lib/fits.c                      |   25 +-
 lib/gnuastro-internal/options.h |    9 +-
 lib/gnuastro/data.h             |   30 -
 lib/gnuastro/fits.h             |    6 +-
 lib/gnuastro/linkedlist.h       |  325 ----------
 lib/gnuastro/list.h             |  338 ++++++++++
 lib/gnuastro/table.h            |   10 +-
 lib/gnuastro/tile.h             |   18 +-
 lib/gnuastro/txt.h              |    9 +-
 lib/interpolate.c               |   48 +-
 lib/linkedlist.c                | 1197 -----------------------------------
 lib/list.c                      | 1307 +++++++++++++++++++++++++++++++++++++++
 lib/options.c                   |   56 +-
 lib/table.c                     |   38 +-
 lib/tile.c                      |    4 +-
 lib/txt.c                       |   35 +-
 lib/wcs.c                       |    6 +-
 tests/crop/wcspolygon.sh        |   16 +-
 tests/mkcatalog/simple.sh       |    3 +-
 63 files changed, 2821 insertions(+), 2641 deletions(-)

diff --git a/bin/TEMPLATE/main.h b/bin/TEMPLATE/main.h
index 469e3b1..ef81396 100644
--- a/bin/TEMPLATE/main.h
+++ b/bin/TEMPLATE/main.h
@@ -44,7 +44,7 @@ struct TEMPLATEparams
 {
   /* From command-line */
   struct gal_options_common_params     cp; /* Common parameters.        */
-  struct gal_linkedlist_strll *multivalue; /* Pointer to multivalue.    */
+  gal_list_str_t  *multivalue; /* Pointer to multivalue.    */
   char             *inputname;  /* Input filename.                      */
   uint8_t              *onoff;  /* How to store on/off options.         */
 
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index 71a65cc..7be6317 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -133,7 +133,7 @@ reversepolish(struct imgarithparams *p)
 {
   int op=0, nop=0;
   unsigned int numop, i;
-  struct gal_linkedlist_stll *token;
+  gal_list_str_t *token;
   gal_data_t *d1=NULL, *d2=NULL, *d3=NULL;
   unsigned char flags = ( GAL_ARITHMETIC_INPLACE | GAL_ARITHMETIC_FREE
                           | GAL_ARITHMETIC_NUMOK );
@@ -310,7 +310,7 @@ reversepolish(struct imgarithparams *p)
               numop=set_number_of_operands(p, pop_operand(p, token->v),
                                            token->v);
               for(i=0;i<numop;++i)
-                gal_data_add_existing_to_ll(&d1, pop_operand(p, token->v));
+                gal_list_data_add(&d1, pop_operand(p, token->v));
               break;
 
             default:
@@ -367,7 +367,7 @@ reversepolish(struct imgarithparams *p)
   /* Clean up. Note that the tokens were taken from the command-line
      arguments, so the string within each token linked list must not be
      freed. */
-  gal_linkedlist_free_stll(p->tokens, 0);
+  gal_list_str_free(p->tokens, 0);
   free(p->operands);
 }
 
diff --git a/bin/arithmetic/main.h b/bin/arithmetic/main.h
index df69d0c..a81347e 100644
--- a/bin/arithmetic/main.h
+++ b/bin/arithmetic/main.h
@@ -24,7 +24,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #define MAIN_H
 
 #include <gnuastro/fits.h>
-#include <gnuastro/linkedlist.h>
+#include <gnuastro/list.h>
 
 #include <gnuastro-internal/options.h>
 
@@ -68,8 +68,8 @@ struct imgarithparams
   struct gal_options_common_params cp;  /* Common parameters.           */
 
   /* Input: */
-  struct gal_linkedlist_stll   *hdus; /* List of all given HDU strings. */
-  struct gal_linkedlist_stll *tokens; /* List of all arithmetic tokens. */
+  gal_list_str_t     *hdus; /* List of all given HDU strings. */
+  gal_list_str_t   *tokens; /* List of all arithmetic tokens. */
   size_t        addcounter;  /* The number of FITS images added.        */
   size_t        popcounter;  /* The number of FITS images popped.       */
   gal_data_t       refdata;  /* Container for information of the data.  */
diff --git a/bin/arithmetic/operands.c b/bin/arithmetic/operands.c
index 15de9bb..6dbf876 100644
--- a/bin/arithmetic/operands.c
+++ b/bin/arithmetic/operands.c
@@ -79,7 +79,7 @@ add_operand(struct imgarithparams *p, char *filename, 
gal_data_t *data)
       if(filename != NULL && gal_fits_name_is_fits(filename))
         {
           /* Set the HDU for this filename. */
-          gal_linkedlist_pop_from_stll(&p->hdus, &newnode->hdu);
+          newnode->hdu=gal_list_str_pop(&p->hdus);
 
           /* Increment the FITS counter. */
           ++p->addcounter;
diff --git a/bin/arithmetic/ui.c b/bin/arithmetic/ui.c
index f44ee51..b6c6459 100644
--- a/bin/arithmetic/ui.c
+++ b/bin/arithmetic/ui.c
@@ -27,6 +27,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <error.h>
 #include <stdio.h>
 
+#include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/table.h>
 #include <gnuastro/linkedlist.h>
@@ -187,7 +188,7 @@ parse_opt(int key, char *arg, struct argp_state *state)
 
     /* Read the non-option tokens (arguments): */
     case ARGP_KEY_ARG:
-      gal_linkedlist_add_to_stll(&p->tokens, arg, 0);
+      gal_list_str_add(&p->tokens, arg, 0);
       break;
 
 
@@ -229,13 +230,13 @@ ui_check_options_and_arguments(struct imgarithparams *p)
 {
   int output_checked=0;
   size_t numfits=0, numhdus=0;
-  struct gal_linkedlist_stll *token, *hdu;
+  gal_list_str_t *token, *hdu;
 
   /* The input tokens are put in a lastin-firstout (simple) linked list, so
      change them to the correct order so the order we pop a token is the
      same order that the user input a value. Note that for the options this
      was done in `gal_options_read_config_set'. */
-  gal_linkedlist_reverse_stll(&p->tokens);
+  gal_list_str_reverse(&p->tokens);
 
   /* Set the output file name (if any is needed). Note that since the
      lists are already reversed, the first FITS file encountered, is
@@ -386,7 +387,7 @@ freeandreport(struct imgarithparams *p, struct timeval *t1)
   /* If there are any remaining HDUs in the hdus linked list, then
      free them. */
   if(p->hdus)
-    gal_linkedlist_free_stll(p->hdus, 1);
+    gal_list_str_free(p->hdus, 1);
 
   /* Report the duration of the job */
   if(!p->cp.quiet)
diff --git a/bin/convertt/jpeg.c b/bin/convertt/jpeg.c
index e3c1252..b4742a9 100644
--- a/bin/convertt/jpeg.c
+++ b/bin/convertt/jpeg.c
@@ -32,6 +32,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
   #include <jpeglib.h>
 #endif
 
+#include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 
 #include "main.h"
@@ -259,8 +260,8 @@ jpeg_read_to_ll(char *filename, gal_data_t **list, size_t 
minmapsize)
       dsize[0]=s0;
       dsize[1]=s1;
       asprintf(&name, "JPEG_CH_%zu", i+1);
-      gal_data_add_to_ll(list, allcolors[i], GAL_TYPE_UINT8, ndim,
-                         dsize, NULL, 0, minmapsize, name, NULL, NULL);
+      gal_list_data_add_alloc(list, allcolors[i], GAL_TYPE_UINT8, ndim,
+                              dsize, NULL, 0, minmapsize, name, NULL, NULL);
       free(name);
     }
 
diff --git a/bin/convertt/main.h b/bin/convertt/main.h
index ea48dc7..51ada58 100644
--- a/bin/convertt/main.h
+++ b/bin/convertt/main.h
@@ -67,9 +67,9 @@ struct change
 struct converttparams
 {
   /* From command-line */
-  struct gal_options_common_params cp;    /* Common parameters.        */
-  struct gal_linkedlist_stll *inputnames; /* The names of input files. */
-  struct gal_linkedlist_stll *hdus;       /* The names of input hdus.  */
+  struct gal_options_common_params cp;   /* Common parameters.         */
+  gal_list_str_t          *inputnames;   /* The names of input files.  */
+  gal_list_str_t                *hdus;   /* The names of input hdus.   */
   uint8_t           quality;  /* Quality of JPEG image.                */
   float           widthincm;  /* Width in centimeters.                 */
   uint32_t      borderwidth;  /* Width of border in PostScript points. */
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index f32372b..17fd946 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -30,6 +30,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/txt.h>
 #include <gnuastro/wcs.h>
+#include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/table.h>
 #include <gnuastro/arithmetic.h>
@@ -198,7 +199,7 @@ parse_opt(int key, char *arg, struct argp_state *state)
 
     /* Read the non-option tokens (arguments): */
     case ARGP_KEY_ARG:
-      gal_linkedlist_add_to_stll(&p->inputnames, arg, 0);
+      gal_list_str_add(&p->inputnames, arg, 0);
       break;
 
 
@@ -283,7 +284,7 @@ ui_check_options_and_arguments(struct converttparams *p)
 
   /* Reverse the `inputnames' linked list, note that the `hdu' linked list
      was reversed during option parsing.*/
-  gal_linkedlist_reverse_stll(&p->inputnames);
+  gal_list_str_reverse(&p->inputnames);
 
 }
 
@@ -400,10 +401,10 @@ ui_make_change_struct(char *arg)
 static void
 ui_make_channels_ll(struct converttparams *p)
 {
-  char *hdu;
+  char *hdu=NULL;
   size_t dsize=0;
   gal_data_t *data;
-  struct gal_linkedlist_stll *name;
+  gal_list_str_t *name;
 
   /* Go through the input files and add the channel(s). */
   p->numch=0;
@@ -424,7 +425,7 @@ ui_make_channels_ll(struct converttparams *p)
         {
           /* Get the HDU value for this channel. */
           if(p->hdus)
-            gal_linkedlist_pop_from_stll(&p->hdus, &hdu);
+            hdu=gal_list_str_pop(&p->hdus);
           else
             error(EXIT_FAILURE, 0, "not enough HDUs. Every input FITS image "
                   "needs a HDU, you can use the `--hdu' (`-h') option once "
@@ -433,7 +434,7 @@ ui_make_channels_ll(struct converttparams *p)
           /* Read in the array and its WCS information. */
           data=gal_fits_img_read(name->v, hdu, p->cp.minmapsize);
           gal_wcs_read(name->v, hdu, 0, 0, &data->nwcs, &data->wcs);
-          gal_data_add_existing_to_ll(&p->chll, data);
+          gal_list_data_add(&p->chll, data);
 
           /* A FITS file only has one channel. */
           ++p->numch;
@@ -460,9 +461,9 @@ ui_make_channels_ll(struct converttparams *p)
       /* Blank: */
       else if(strcmp(name->v, BLANK_CHANNEL_NAME)==0)
         {
-          gal_data_add_to_ll(&p->chll, NULL, GAL_TYPE_INVALID, 0,
-                             &dsize, NULL, 0, p->cp.minmapsize, "blank",
-                             NULL, NULL);
+          gal_list_data_add_alloc(&p->chll, NULL, GAL_TYPE_INVALID, 0,
+                                  &dsize, NULL, 0, p->cp.minmapsize,
+                                  "blank", NULL, NULL);
           ++p->numch;
         }
 
@@ -487,14 +488,14 @@ ui_make_channels_ll(struct converttparams *p)
       else
         {
           data=gal_txt_image_read(name->v, p->cp.minmapsize);
-          gal_data_add_existing_to_ll(&p->chll, data);
+          gal_list_data_add(&p->chll, data);
           ++p->numch;
         }
     }
 
 
   /* Reverse the list of channels into the input order. */
-  gal_data_reverse_ll(&p->chll);
+  gal_list_data_reverse(&p->chll);
 }
 
 
@@ -609,7 +610,7 @@ ui_prepare_input_channels(struct converttparams *p)
 void
 ui_add_dot_use_automatic_output(struct converttparams *p)
 {
-  struct gal_linkedlist_stll *stll;
+  gal_list_str_t *stll;
   char *tmp, *firstname="output.txt", *suffix=p->cp.output;
 
   /* Find the first non-blank file name in the input(s). */
@@ -847,7 +848,7 @@ ui_free_report(struct converttparams *p)
   /* Free the allocated spaces */
   gal_data_free(p->fluxlow);
   gal_data_free(p->fluxhigh);
+  gal_list_str_free(p->hdus, 1);
   if(p->cp.output) free(p->cp.output);
-  gal_linkedlist_free_stll(p->hdus, 1);
-  gal_linkedlist_free_stll(p->inputnames, 0);
+  gal_list_str_free(p->inputnames, 0);
 }
diff --git a/bin/crop/crop.c b/bin/crop/crop.c
index 9a86588..6e7b576 100644
--- a/bin/crop/crop.c
+++ b/bin/crop/crop.c
@@ -386,9 +386,9 @@ crop(struct cropparams *p)
   pthread_barrier_t b;
   struct onecropparams *crp;
   size_t i, *indexs, thrdcols;
+  gal_list_str_t *comments=NULL;
   size_t nt=p->cp.numthreads, nb;
   void *(*modefunction)(void *)=NULL;
-  struct gal_linkedlist_stll *comments=NULL;
 
 
   /* Set the function to run: */
@@ -454,11 +454,11 @@ crop(struct cropparams *p)
         {
           asprintf(&tmp, "Width of central check box: %zu",
                    p->checkcenter);
-          gal_linkedlist_add_to_stll(&comments, tmp, 0);
+          gal_list_str_add(&comments, tmp, 0);
         }
       gal_table_write_log(p->log, PROGRAM_STRING, &p->rawtime, comments,
                           LOGFILENAME, p->cp.dontdelete, p->cp.quiet);
-      gal_linkedlist_free_stll(comments, 1);
+      gal_list_str_free(comments, 1);
     }
 
   /* Print the final verbose info, save log, and clean up: */
diff --git a/bin/crop/main.h b/bin/crop/main.h
index c53b3ec..48fd6ed 100644
--- a/bin/crop/main.h
+++ b/bin/crop/main.h
@@ -81,7 +81,7 @@ struct cropparams
 {
   /* Directly from command-line */
   struct gal_options_common_params cp;  /* Common parameters.             */
-  struct gal_linkedlist_stll  *inputs;  /* All input FITS files.          */
+  struct gal_list_str_t       *inputs;  /* All input FITS files.          */
   size_t             hstartwcs;  /* Header keyword No. to start read WCS. */
   size_t               hendwcs;  /* Header keyword No. to end read WCS.   */
   uint8_t       zeroisnotblank;  /* ==1: In float or double, keep 0.0.    */
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index cd97e7b..3b818d0 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -180,9 +180,9 @@ crop_polygonparser(struct cropparams *p)
 {
   size_t dim=0;
   char *tailptr;
-  double read[2], *array;
-  struct gal_linkedlist_tdll *gal_linkedlist_tdll=NULL;
   char *pt=p->polygon;
+  double read, *array;
+  gal_list_f64_t *vertices=NULL;
 
   /* If control reached here, then the cropped region is not defined by its
      center. So it makes no sense to check if the center is blank. */
@@ -220,10 +220,10 @@ crop_polygonparser(struct cropparams *p)
       else
         {
           /* Read the number: */
-          read[dim]=strtod(pt, &tailptr);
+          read=strtod(pt, &tailptr);
 
           /* Check if there actually was a number.
-          printf("\n\n------\n%zu: %f (%s)\n", dim, read[dim], tailptr);
+          printf("\n\n------\n%zu: %f (%s)\n", dim, read, tailptr);
           */
 
           /* Make sure if a number was read at all? */
@@ -243,36 +243,37 @@ crop_polygonparser(struct cropparams *p)
                   "sequence in the value to the `--polygon' option, error "
                   "detected at '%s'", pt, tailptr);
 
-          /* If this was the second dimension, then put the values
-             into the linked list: */
-          if(dim==1)
-            gal_linkedlist_add_to_tdll(&gal_linkedlist_tdll, read[0],
-                                       read[1]);
+          /* Add the read coordinate to the list of coordinates. */
+          gal_list_f64_add(&vertices, read);
 
           /* The job here is done, start from tailptr */
           pt=tailptr;
         }
     }
 
-  /* Convert the linked list to an array: */
-  gal_linkedlist_tdll_to_array_inv(gal_linkedlist_tdll, &array,
-                                   &p->nvertices);
+  /* Put the coordinates into an array while reversing their order so they
+     correspond to the user's order, then put it in the right place.*/
+  array=gal_list_f64_to_array(vertices, 1, &p->nvertices);
   if(p->mode==IMGCROP_MODE_IMG) { p->ipolygon=array; p->wpolygon=NULL;  }
   else                          { p->ipolygon=NULL;  p->wpolygon=array; }
 
-  /* Put them in the proper order in WCS mode: */
+  /* The number of vertices is actually the number of nodes in the list
+     divided by the dimension of the dataset (note that we were counting
+     the dimension from 0. */
+  p->nvertices/=(dim+1);
 
   /* For a check:
   {
     size_t i;
-    double *polygon=p->imgmode?p->ipolygon:p->wpolygon;
+    double *polygon=p->mode==IMGCROP_MODE_IMG?p->ipolygon:p->wpolygon;
     for(i=0;i<p->nvertices;++i)
       printf("(%f, %f)\n", polygon[i*2], polygon[i*2+1]);
   }
+  exit(0);
   */
 
   /* Clean up: */
-  gal_linkedlist_free_tdll(gal_linkedlist_tdll);
+  gal_list_f64_free(vertices);
 }
 
 
diff --git a/bin/crop/ui.c b/bin/crop/ui.c
index 5b80d0a..0142e9b 100644
--- a/bin/crop/ui.c
+++ b/bin/crop/ui.c
@@ -29,6 +29,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <string.h>
 
 #include <gnuastro/wcs.h>
+#include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/blank.h>
 #include <gnuastro/table.h>
@@ -200,7 +201,7 @@ parse_opt(int key, char *arg, struct argp_state *state)
 
     /* Read the non-option tokens (arguments): */
     case ARGP_KEY_ARG:
-      gal_linkedlist_add_to_stll(&p->inputs, arg, 0);
+      gal_list_str_add(&p->inputs, arg, 0);
       ++p->numin;
       break;
 
@@ -480,16 +481,16 @@ ui_read_cols(struct cropparams *p)
   char *colname;
   size_t counter=0;
   int toomanycols=0;
+  gal_list_str_t *colstrs=NULL;
   gal_data_t *cols, *tmp, *corrtype=NULL;
-  struct gal_linkedlist_stll *colstrs=NULL;
   char *ax1col = p->mode==IMGCROP_MODE_IMG ? p->xcol : p->racol;
   char *ax2col = p->mode==IMGCROP_MODE_IMG ? p->ycol : p->deccol;
 
   /* Specify the order of columns. */
   if(p->namecol)
-    gal_linkedlist_add_to_stll(&colstrs, p->namecol, 0);
-  gal_linkedlist_add_to_stll(&colstrs, ax1col, 0);
-  gal_linkedlist_add_to_stll(&colstrs, ax2col, 0);
+    gal_list_str_add(&colstrs, p->namecol, 0);
+  gal_list_str_add(&colstrs, ax1col, 0);
+  gal_list_str_add(&colstrs, ax2col, 0);
 
   /* Read the desired columns from the file. */
   cols=gal_table_read(p->catname, p->cathdu, colstrs, p->cp.searchin,
@@ -503,7 +504,7 @@ ui_read_cols(struct cropparams *p)
   while(cols!=NULL)
     {
       /* Pop out the top node. */
-      tmp=gal_data_pop_from_ll(&cols);
+      tmp=gal_list_data_pop(&cols);
 
       /* Note that the input was a linked list, so the output order is the
          inverse of the input order. For the position, we will store the
@@ -595,20 +596,20 @@ ui_make_log(struct cropparams *p)
   /* If central pixels are filled. */
   asprintf(&comment, "Are the central pixels filled? (1: yes, 0: no, "
            "%u: not checked)", GAL_BLANK_UINT8);
-  gal_data_add_to_ll(&p->log, NULL, GAL_TYPE_UINT8, 1, &p->numout,
-                     NULL, 1, p->cp.minmapsize, "CENTER_FILLED", "bool",
-                     comment);
+  gal_list_data_add_alloc(&p->log, NULL, GAL_TYPE_UINT8, 1, &p->numout,
+                          NULL, 1, p->cp.minmapsize, "CENTER_FILLED",
+                          "bool", comment);
   free(comment);
 
   /* Number of images used. */
-  gal_data_add_to_ll(&p->log, NULL, GAL_TYPE_UINT16, 1, &p->numout,
-                     NULL, 1, p->cp.minmapsize, "NUM_INPUTS", "count",
-                     "Number of input images used to make this crop.");
+  gal_list_data_add_alloc(&p->log, NULL, GAL_TYPE_UINT16, 1, &p->numout,
+                          NULL, 1, p->cp.minmapsize, "NUM_INPUTS", "count",
+                          "Number of input images used to make this crop.");
 
   /* Row number in input catalog. */
-  gal_data_add_to_ll(&p->log, NULL, GAL_TYPE_STRING, 1, &p->numout,
-                     NULL, 1, p->cp.minmapsize, "CROP_NAME", "name",
-                     "File name of crop.");
+  gal_list_data_add_alloc(&p->log, NULL, GAL_TYPE_STRING, 1, &p->numout,
+                          NULL, 1, p->cp.minmapsize, "CROP_NAME", "name",
+                          "File name of crop.");
 }
 
 
@@ -673,7 +674,7 @@ ui_preparations(struct cropparams *p)
       /* Pop from the list of input images and get the info. */
       status=0;
       img=&p->imgs[--input_counter];
-      gal_linkedlist_pop_from_stll(&p->inputs, &img->name);
+      img->name=gal_list_str_pop(&p->inputs);
       tmpfits=gal_fits_hdu_open_type(img->name, p->cp.hdu, 0);
       gal_fits_img_info(tmpfits, &p->type, &img->ndim, &img->dsize);
       gal_wcs_read_from_fitsptr(tmpfits, &img->nwcs, &img->wcs,
@@ -845,7 +846,7 @@ ui_free_report(struct cropparams *p, struct timeval *t1)
   if(p->catname) free(p->catname);
 
   /* The arguments (note that the values were not allocated). */
-  gal_linkedlist_free_stll(p->inputs, 0);
+  gal_list_str_free(p->inputs, 0);
 
   /* Free the name/ array.  */
   if(p->name)
@@ -856,7 +857,7 @@ ui_free_report(struct cropparams *p, struct timeval *t1)
     }
 
   /* Free the log information. */
-  if(p->cp.log) gal_data_free_ll(p->log);
+  if(p->cp.log) gal_list_data_free(p->log);
 
   /* Print the final message. */
   if(!p->cp.quiet)
diff --git a/bin/fits/fits.c b/bin/fits/fits.c
index e612e0e..4518b81 100644
--- a/bin/fits/fits.c
+++ b/bin/fits/fits.c
@@ -26,6 +26,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <error.h>
 #include <string.h>
 
+#include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/blank.h>
 
@@ -106,18 +107,18 @@ fits_print_extension_info(struct fitsparams *p)
 
   /* Allocate all the columns (in reverse order, since this is a simple
      linked list). */
-  gal_data_add_to_ll(&cols, NULL, GAL_TYPE_STRING, 1, &numext, NULL, 1,
-                     p->cp.minmapsize, "HDU_SIZE", "name",
-                     "Size of image or table number of rows and columns.");
-  gal_data_add_to_ll(&cols, NULL, GAL_TYPE_STRING, 1, &numext, NULL, 1,
-                     p->cp.minmapsize, "HDU_TYPE", "name",
-                     "Image data type or `table' format (ASCII or binary).");
-  gal_data_add_to_ll(&cols, NULL, GAL_TYPE_STRING, 1, &numext, NULL, 1,
-                     p->cp.minmapsize, "EXTNAME", "name",
-                     "Extension name of this HDU (EXTNAME in FITS).");
-  gal_data_add_to_ll(&cols, NULL, GAL_TYPE_UINT16, 1, &numext, NULL, 1,
-                     p->cp.minmapsize, "HDU_INDEX", "count",
-                     "Index (starting from zero) of each HDU (extension).");
+  gal_list_data_add_alloc(&cols, NULL, GAL_TYPE_STRING, 1, &numext, NULL, 1,
+                          p->cp.minmapsize, "HDU_SIZE", "name", "Size of "
+                          "image or table number of rows and columns.");
+  gal_list_data_add_alloc(&cols, NULL, GAL_TYPE_STRING, 1, &numext, NULL, 1,
+                          p->cp.minmapsize, "HDU_TYPE", "name", "Image "
+                          "data type or `table' format (ASCII or binary).");
+  gal_list_data_add_alloc(&cols, NULL, GAL_TYPE_STRING, 1, &numext, NULL, 1,
+                          p->cp.minmapsize, "EXTNAME", "name",
+                          "Extension name of this HDU (EXTNAME in FITS).");
+  gal_list_data_add_alloc(&cols, NULL, GAL_TYPE_UINT16, 1, &numext, NULL, 1,
+                          p->cp.minmapsize, "HDU_INDEX", "count", "Index "
+                          "(starting from zero) of each HDU (extension).");
 
 
   /* Keep pointers to the array of each column for easy writing. */
@@ -232,7 +233,7 @@ fits_print_extension_info(struct fitsparams *p)
       printf("-----\n");
     }
   gal_table_write(cols, NULL, GAL_TABLE_FORMAT_TXT, NULL, 0);
-  gal_data_free_ll(cols);
+  gal_list_data_free(cols);
 }
 
 
@@ -249,7 +250,7 @@ fits_hdu_remove(struct fitsparams *p, int *r)
   while(p->remove)
     {
       /* Pop-out the top element. */
-      gal_linkedlist_pop_from_stll(&p->remove, &hdu);
+      hdu=gal_list_str_pop(&p->remove);
 
       /* Open the FITS file at the specified HDU. */
       fptr=gal_fits_hdu_open(p->filename, hdu, READWRITE);
@@ -273,7 +274,7 @@ fits_hdu_copy(struct fitsparams *p, int cut1_copy0, int *r)
   char *hdu;
   fitsfile *in, *out;
   int status=0, hdutype;
-  struct gal_linkedlist_stll *list = cut1_copy0 ? p->cut : p->copy;
+  gal_list_str_t *list = cut1_copy0 ? p->cut : p->copy;
 
   /* Open the output file. */
   out=gal_fits_open_to_write(p->cp.output);
@@ -282,7 +283,7 @@ fits_hdu_copy(struct fitsparams *p, int cut1_copy0, int *r)
   while(list)
     {
       /* Pop-out the top element. */
-      gal_linkedlist_pop_from_stll(&list, &hdu);
+      hdu=gal_list_str_pop(&list);
 
       /* Open the FITS file at the specified HDU. */
       in=gal_fits_hdu_open(p->filename, hdu, READWRITE);
diff --git a/bin/fits/keywords.c b/bin/fits/keywords.c
index d97c985..ac507f1 100644
--- a/bin/fits/keywords.c
+++ b/bin/fits/keywords.c
@@ -89,7 +89,7 @@ keywords_rename_keys(struct fitsparams *p, fitsfile **fptr, 
int *r)
   while(p->rename!=NULL)
     {
       /* Pop out the top element. */
-      gal_linkedlist_pop_from_stll(&p->rename, &str);
+      str=gal_list_str_pop(&p->rename);
 
       /* Take a copy of the input string for error reporting, because
          `strtok' will write into the array. */
@@ -264,7 +264,7 @@ keywords(struct fitsparams *p)
   int status=0;
   int r=EXIT_SUCCESS;
   fitsfile *fptr=NULL;
-  struct gal_linkedlist_stll *tstll;
+  gal_list_str_t *tstll;
 
 
   /* Delete the requested keywords. */
diff --git a/bin/fits/main.h b/bin/fits/main.h
index 13f1405..851479b 100644
--- a/bin/fits/main.h
+++ b/bin/fits/main.h
@@ -23,6 +23,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #ifndef MAIN_H
 #define MAIN_H
 
+#include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 
 #include <gnuastro-internal/options.h>
@@ -52,21 +53,21 @@ enum fits_mode
 struct fitsparams
 {
   /* From the environment. */
-  struct gal_options_common_params cp;  /* Common parameters.              */
-  char                      *filename;  /* Name of input file.             */
-  struct gal_linkedlist_stll  *remove;  /* Remove extensions from a file.  */
-  struct gal_linkedlist_stll    *copy;  /* Copy extensions to output.      */
-  struct gal_linkedlist_stll     *cut;  /* Copy ext. to output and remove. */
-  uint8_t                printallkeys;  /* Print all the header keywords.  */
-  uint8_t                        date;  /* Set DATE to current time.       */
-  char                       *comment;  /* COMMENT value.                  */
-  char                       *history;  /* HISTORY value.                  */
-  struct gal_linkedlist_stll    *asis;  /* Strings to write asis.          */
-  struct gal_linkedlist_stll  *delete;  /* Keywords to remove.             */
-  struct gal_linkedlist_stll  *rename;  /* Rename a keyword.               */
-  struct gal_linkedlist_stll  *update;  /* For keywords to update.         */
-  struct gal_linkedlist_stll   *write;  /* Full arg. for keywords to add.  */
-  uint8_t                 quitonerror;  /* Quit if an error occurs.        */
+  struct gal_options_common_params cp;  /* Common parameters.     */
+  char          *filename;     /* Name of input file.             */
+  gal_list_str_t  *remove;     /* Remove extensions from a file.  */
+  gal_list_str_t    *copy;     /* Copy extensions to output.      */
+  gal_list_str_t     *cut;     /* Copy ext. to output and remove. */
+  uint8_t    printallkeys;     /* Print all the header keywords.  */
+  uint8_t            date;     /* Set DATE to current time.       */
+  char           *comment;     /* COMMENT value.                  */
+  char           *history;     /* HISTORY value.                  */
+  gal_list_str_t    *asis;     /* Strings to write asis.          */
+  gal_list_str_t  *delete;     /* Keywords to remove.             */
+  gal_list_str_t  *rename;     /* Rename a keyword.               */
+  gal_list_str_t  *update;     /* For keywords to update.         */
+  gal_list_str_t   *write;     /* Full arg. for keywords to add.  */
+  uint8_t     quitonerror;     /* Quit if an error occurs.        */
 
   /* Internal: */
   int                            mode;  /* Operating on HDUs or keywords.  */
diff --git a/bin/fits/ui.c b/bin/fits/ui.c
index 4359455..99fdb96 100644
--- a/bin/fits/ui.c
+++ b/bin/fits/ui.c
@@ -308,15 +308,14 @@ ui_check_options_and_arguments(struct fitsparams *p)
    keyword, so here, we tokenize them and put them into a `gal_fits_key_ll'
    list. */
 static void
-ui_fill_fits_headerll(struct gal_linkedlist_stll *input,
-                          struct gal_fits_key_ll **output)
+ui_fill_fits_headerll(gal_list_str_t *input, struct gal_fits_key_ll **output)
 {
   long l, *lp;
   void *fvalue;
   double d, *dp;
+  gal_list_str_t *tmp;
   int i=0, type, vfree;
   char *c, *cf, *start, *tailptr;
-  struct gal_linkedlist_stll *tmp;
   char *original, *keyname, *value, *comment, *unit;
 
   for(tmp=input; tmp!=NULL; tmp=tmp->next)
diff --git a/bin/mkcatalog/columns.c b/bin/mkcatalog/columns.c
index 68f75ea..a5ad6e0 100644
--- a/bin/mkcatalog/columns.c
+++ b/bin/mkcatalog/columns.c
@@ -193,9 +193,9 @@ columns_alloc_clumpsgeoradec(struct mkcatalogparams *p)
 void
 columns_define_alloc(struct mkcatalogparams *p)
 {
-  struct gal_linkedlist_ill *colcode;
+  gal_list_i32_t *colcode;
+  gal_list_str_t *strtmp, *noclumpimg=NULL;
   int disp_fmt=0, disp_width=0, disp_precision=0;
-  struct gal_linkedlist_stll *strtmp, *noclumpimg=NULL;
   char *name=NULL, *unit=NULL, *ocomment=NULL, *ccomment=NULL;
   uint8_t otype=GAL_TYPE_INVALID, ctype=GAL_TYPE_INVALID, *oiflag, *ciflag;
 
@@ -878,8 +878,9 @@ columns_define_alloc(struct mkcatalogparams *p)
          for the columns. */
       if(otype!=GAL_TYPE_INVALID)
         {
-          gal_data_add_to_ll(&p->objectcols, NULL, otype, 1, &p->numobjects,
-                             NULL, 0, p->cp.minmapsize, name, unit, ocomment);
+          gal_list_data_add_alloc(&p->objectcols, NULL, otype, 1,
+                                  &p->numobjects, NULL, 0, p->cp.minmapsize,
+                                  name, unit, ocomment);
           p->objectcols->status         = colcode->v;
           p->objectcols->disp_fmt       = disp_fmt;
           p->objectcols->disp_width     = disp_width;
@@ -896,9 +897,9 @@ columns_define_alloc(struct mkcatalogparams *p)
              column. */
           if(p->clumps)
             {
-              gal_data_add_to_ll(&p->clumpcols, NULL, ctype, 1, &p->numclumps,
-                                 NULL, 0, p->cp.minmapsize, name, unit,
-                                 ccomment);
+              gal_list_data_add_alloc(&p->clumpcols, NULL, ctype, 1,
+                                      &p->numclumps, NULL, 0,
+                                      p->cp.minmapsize, name, unit, ccomment);
               p->clumpcols->status         = colcode->v;
               p->clumpcols->disp_fmt       = disp_fmt;
               p->clumpcols->disp_width     = disp_width;
@@ -910,7 +911,7 @@ columns_define_alloc(struct mkcatalogparams *p)
              given. Add the column to the list of similar columns to inform
              the user. */
           else if(otype==GAL_TYPE_INVALID)
-            gal_linkedlist_add_to_stll(&noclumpimg, name, 1);
+            gal_list_str_add(&noclumpimg, name, 1);
         }
     }
 
@@ -919,7 +920,7 @@ columns_define_alloc(struct mkcatalogparams *p)
      the warning. */
   if(noclumpimg)
     {
-      gal_linkedlist_reverse_stll(&noclumpimg);
+      gal_list_str_reverse(&noclumpimg);
       fprintf(stderr, "\n-------\n"
               "WARNING: the following column(s) are unique to "
               "clumps (not objects), but the objects image doesn't have "
@@ -927,14 +928,14 @@ columns_define_alloc(struct mkcatalogparams *p)
               "ignored.\n\n");
       for(strtmp=noclumpimg; strtmp!=NULL; strtmp=strtmp->next)
         fprintf(stderr, "\t%s\n", strtmp->v);
-      gal_linkedlist_free_stll(noclumpimg, 1);
+      gal_list_str_free(noclumpimg, 1);
       fprintf(stderr, "\n-------\n");
     }
 
 
   /* Free the general columns information because it is no longe needed,
      we'll set it back to NULL afterwards so it is not mistakenly used. */
-  gal_linkedlist_free_ill(p->columnids);
+  gal_list_i32_free(p->columnids);
   p->columnids=NULL;
 }
 
diff --git a/bin/mkcatalog/main.h b/bin/mkcatalog/main.h
index 9fbd5dc..3f7f287 100644
--- a/bin/mkcatalog/main.h
+++ b/bin/mkcatalog/main.h
@@ -132,7 +132,7 @@ struct mkcatalogparams
 {
   /* From command-line */
   struct gal_options_common_params cp; /* Common parameters.            */
-  struct gal_linkedlist_ill  *columnids; /* The desired column codes.   */
+  gal_list_i32_t   *columnids; /* The desired column codes.   */
   char             *inputname;  /* Input filename.                      */
   char           *objectsfile;  /* File name of objects file.           */
   char            *objectshdu;  /* HDU of objects image.                */
@@ -180,7 +180,7 @@ struct mkcatalogparams
   pthread_mutex_t       mutex;  /* Mutex to change the total numbers.   */
   size_t      clumprowsfilled;  /* No. filled clump rows at this moment.*/
   gsl_rng                *rng;  /* Main random number generator.        */
-  unsigned long          seed;  /* Random number generator seed.        */
+  uint64_t               seed;  /* Random number generator seed.        */
   const char         *rngname;  /* Name of random number generator.     */
 
   double              **rd_vo;  /* Object RA-Dec flux weighted X, Y.    */
diff --git a/bin/mkcatalog/mkcatalog.c b/bin/mkcatalog/mkcatalog.c
index 0344beb..1e074a0 100644
--- a/bin/mkcatalog/mkcatalog.c
+++ b/bin/mkcatalog/mkcatalog.c
@@ -642,88 +642,88 @@ mkcatalog_wcs_conversion(struct mkcatalogparams *p)
 
 
 /* Write the similar information. */
-static struct gal_linkedlist_stll *
+static gal_list_str_t *
 mkcatalog_outputs_same_start(struct mkcatalogparams *p, int o0c1,
                              char *ObjClump)
 {
   char *str;
   float snlim;
-  struct gal_linkedlist_stll *comments=NULL;
+  gal_list_str_t *comments=NULL;
   char *skyfile=p->skyfile ? p->skyfile : p->inputname;
   char *stdfile=p->stdfile ? p->stdfile : p->inputname;
   char *clumpsfile=p->clumpsfile ? p->clumpsfile : p->inputname;
   char *objectsfile=p->objectsfile ? p->objectsfile : p->inputname;
 
   asprintf(&str, "%s %s catalog.", PROGRAM_STRING, o0c1 ? "object" : "clump");
-  gal_linkedlist_add_to_stll(&comments, str, 0);
+  gal_list_str_add(&comments, str, 0);
 
   /* If in a Git controlled directory and output isn't a FITS file (in
      FITS, this will be automatically included). */
   if(p->cp.tableformat==GAL_TABLE_FORMAT_TXT && gal_git_describe())
     {
       asprintf(&str, "# Directory commit %s\n", gal_git_describe());
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   asprintf(&str, "%s started on %s", PROGRAM_NAME, ctime(&p->rawtime));
-  gal_linkedlist_add_to_stll(&comments, str, 0);
+  gal_list_str_add(&comments, str, 0);
 
 
   if(p->cp.tableformat==GAL_TABLE_FORMAT_TXT)
     {
       asprintf(&str, "--------- Input files ---------");
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   asprintf(&str, "Values:  %s (hdu: %s).", p->inputname, p->cp.hdu);
-  gal_linkedlist_add_to_stll(&comments, str, 0);
+  gal_list_str_add(&comments, str, 0);
 
   asprintf(&str, "Objects: %s (hdu: %s).", objectsfile, p->objectshdu);
-  gal_linkedlist_add_to_stll(&comments, str, 0);
+  gal_list_str_add(&comments, str, 0);
 
   if(p->clumps)
     {
       asprintf(&str, "Clumps:  %s (hdu: %s).", clumpsfile, p->clumpshdu);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   asprintf(&str, "Sky:     %s (hdu: %s).", skyfile, p->skyhdu);
-  gal_linkedlist_add_to_stll(&comments, str, 0);
+  gal_list_str_add(&comments, str, 0);
 
   asprintf(&str, "Sky STD: %s (hdu: %s).", stdfile, p->stdhdu);
-  gal_linkedlist_add_to_stll(&comments, str, 0);
+  gal_list_str_add(&comments, str, 0);
 
   if(p->upmaskfile)
     {
       asprintf(&str, "Upperlimit mask: %s (hdu: %s).", p->upmaskfile,
                p->upmaskhdu);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   if(p->cp.tableformat==GAL_TABLE_FORMAT_TXT)
     {
       asprintf(&str, "--------- Supplimentary information ---------");
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   if(p->input->wcs)
     {
       asprintf(&str, "Pixel area (arcsec^2): %g",
                gal_wcs_pixel_area_arcsec2(p->input->wcs));
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   if(p->hasmag)
     {
       asprintf(&str, "Zeropoint magnitude: %.4f", p->zeropoint);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   if( !isnan(p->zeropoint) )
     {
       asprintf(&str, "Pixel %g sigma surface brightness (magnitude): %.3f",
                p->nsigmag, -2.5f*log10(p->nsigmag*p->medstd)+p->zeropoint);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   snlim = o0c1 ? p->clumpsn : p->detsn;
@@ -731,27 +731,27 @@ mkcatalog_outputs_same_start(struct mkcatalogparams *p, 
int o0c1,
     {
       asprintf(&str, "%s limiting signal-to-noise ratio: %.3f", ObjClump,
                snlim);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   if(o0c1==0)
     {
       asprintf(&str, "(NOTE: S/N limit above is for pseudo-detections, "
                "not objects.)");
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   if(p->cpscorr>1.0f)
     {
       asprintf(&str, "Counts-per-second correction: %.3f", p->cpscorr);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   if( !isnan(p->threshold) )
     {
       asprintf(&str, "**IMPORTANT** Pixel threshold (multiple of local "
                "std): %.3f", p->threshold);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
 
@@ -760,21 +760,21 @@ mkcatalog_outputs_same_start(struct mkcatalogparams *p, 
int o0c1,
       if(p->cp.tableformat==GAL_TABLE_FORMAT_TXT)
         {
           asprintf(&str, "--------- Upper-limit measurement ---------");
-          gal_linkedlist_add_to_stll(&comments, str, 0);
+          gal_list_str_add(&comments, str, 0);
         }
 
       asprintf(&str, "Number of random samples: %zu", p->upnum);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
 
       asprintf(&str, "Random number generator name: %s", p->rngname);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
 
       asprintf(&str, "Random number generator seed: %lu", p->seed);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
 
       asprintf(&str, "Multiple of STD used for sigma-clipping: %.3f",
                p->upsigmaclip[0]);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
 
       if(p->upsigmaclip[1]>=1.0f)
         asprintf(&str, "Number of clips for sigma-clipping: %.0f",
@@ -782,11 +782,11 @@ mkcatalog_outputs_same_start(struct mkcatalogparams *p, 
int o0c1,
       else
         asprintf(&str, "Tolerance level to sigma-clipping: %.3f",
                  p->upsigmaclip[1]);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
 
       asprintf(&str, "Multiple of sigma-clipped STD for upper-limit: %.3f",
                p->upnsigma);
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
 
@@ -794,10 +794,10 @@ mkcatalog_outputs_same_start(struct mkcatalogparams *p, 
int o0c1,
   if(p->cp.tableformat==GAL_TABLE_FORMAT_TXT)
     {
       asprintf(&str, "-------------------------------------------\n");
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
 
       asprintf(&str, "--------- Table columns ---------");
-      gal_linkedlist_add_to_stll(&comments, str, 0);
+      gal_list_str_add(&comments, str, 0);
     }
 
   /* Return the comments. */
@@ -813,7 +813,7 @@ static void
 mkcatalog_write_outputs(struct mkcatalogparams *p)
 {
   /*char *str;*/
-  struct gal_linkedlist_stll *comments;
+  gal_list_str_t *comments;
 
 
   /* OBJECT CATALOG
@@ -826,10 +826,10 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
 
      Reverse the comments list (so it is printed in the same order here),
      write the objects catalog and free the comments. */
-  gal_linkedlist_reverse_stll(&comments);
+  gal_list_str_reverse(&comments);
   gal_table_write(p->objectcols, comments, p->cp.tableformat, p->objectsout,
                   p->cp.dontdelete);
-  gal_linkedlist_free_stll(comments, 1);
+  gal_list_str_free(comments, 1);
 
 
 
@@ -846,10 +846,10 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
 
          Reverse the comments list (so it is printed in the same order here),
          write the objects catalog and free the comments. */
-      gal_linkedlist_reverse_stll(&comments);
+      gal_list_str_reverse(&comments);
       gal_table_write(p->clumpcols, comments, p->cp.tableformat,
                       p->clumpsout, p->cp.dontdelete);
-      gal_linkedlist_free_stll(comments, 1);
+      gal_list_str_free(comments, 1);
     }
 }
 
diff --git a/bin/mkcatalog/ui.c b/bin/mkcatalog/ui.c
index 1cad0d1..1541bd1 100644
--- a/bin/mkcatalog/ui.c
+++ b/bin/mkcatalog/ui.c
@@ -27,6 +27,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <error.h>
 #include <stdio.h>
 #include <string.h>
+#include <inttypes.h>
 
 #include <gnuastro/wcs.h>
 #include <gnuastro/fits.h>
@@ -240,12 +241,12 @@ ui_column_codes_ll(struct argp_option *option, char *arg,
      column means three columns. */
   if(option->key==UI_KEY_IDS)
     {
-      gal_linkedlist_add_to_ill(&p->columnids, UI_KEY_OBJID);
-      gal_linkedlist_add_to_ill(&p->columnids, UI_KEY_HOSTOBJID);
-      gal_linkedlist_add_to_ill(&p->columnids, UI_KEY_IDINHOSTOBJ);
+      gal_list_i32_add(&p->columnids, UI_KEY_OBJID);
+      gal_list_i32_add(&p->columnids, UI_KEY_HOSTOBJID);
+      gal_list_i32_add(&p->columnids, UI_KEY_IDINHOSTOBJ);
     }
   else
-    gal_linkedlist_add_to_ill(&p->columnids, option->key);
+    gal_list_i32_add(&p->columnids, option->key);
 
   /* Return NULL */
   return NULL;
@@ -328,8 +329,8 @@ static void
 ui_preparations_read_inputs(struct mkcatalogparams *p)
 {
   size_t one;
+  gal_list_i32_t *tmp;
   int readclumps=0, readwcs=0;
-  struct gal_linkedlist_ill *tmp;
   char *namestypes, **strarr=NULL;
   gal_data_t *zero, *key=gal_data_array_calloc(1);
   char *skyfile=p->skyfile ? p->skyfile : p->inputname;
@@ -909,7 +910,7 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
mkcatalogparams *p)
       if(p->upperlimit)
         {
           printf("  - Random number generator name: %s\n", p->rngname);
-          printf("  - Random number generator seed: %lu\n", p->seed);
+          printf("  - Random number generator seed: %"PRIu64"\n", p->seed);
         }
     }
 }
diff --git a/bin/mknoise/ui.c b/bin/mknoise/ui.c
index a8429b8..5e41eb3 100644
--- a/bin/mknoise/ui.c
+++ b/bin/mknoise/ui.c
@@ -26,6 +26,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <errno.h>
 #include <error.h>
 #include <stdio.h>
+#include <inttypes.h>
 
 #include <gnuastro/wcs.h>
 #include <gnuastro/fits.h>
@@ -386,7 +387,7 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
mknoiseparams *p)
       sprintf(message, "Random number generator type: %s",
               gsl_rng_name(p->rng));
       gal_timing_report(NULL, message, 1);
-      sprintf(message, "Random number generator seed: %ld", p->rng_seed);
+      sprintf(message, "Random number generator seed: %"PRId64, p->rng_seed);
       gal_timing_report(NULL, message, 1);
     }
 }
diff --git a/bin/mkprof/mkprof.c b/bin/mkprof/mkprof.c
index 7317e22..4ca9da2 100644
--- a/bin/mkprof/mkprof.c
+++ b/bin/mkprof/mkprof.c
@@ -564,9 +564,9 @@ mkprof(struct mkprofparams *p)
   pthread_barrier_t b;
   struct mkonthread *mkp;
   size_t i, *indexs, thrdcols;
+  gal_list_str_t *comments=NULL;
   size_t nt=p->cp.numthreads, nb;
   long onaxes[2], os=p->oversample;
-  struct gal_linkedlist_stll *comments=NULL;
 
 
   /* Allocate the arrays to keep the thread and parameters for each
@@ -634,10 +634,10 @@ mkprof(struct mkprofparams *p)
   if(p->cp.log)
     {
       asprintf(&tmp, "Zeropoint: %g", p->zeropoint);
-      gal_linkedlist_add_to_stll(&comments, tmp, 0);
+      gal_list_str_add(&comments, tmp, 0);
       gal_table_write_log(p->log, PROGRAM_STRING, &p->rawtime, comments,
                           LOGFILENAME, p->cp.dontdelete, p->cp.quiet);
-      gal_linkedlist_free_stll(comments, 1);
+      gal_list_str_free(comments, 1);
     }
 
   /* If numthreads>1, then wait for all the jobs to finish and destroy
diff --git a/bin/mkprof/oneprofile.c b/bin/mkprof/oneprofile.c
index a423871..5fdd9ff 100644
--- a/bin/mkprof/oneprofile.c
+++ b/bin/mkprof/oneprofile.c
@@ -227,10 +227,10 @@ makepixbypix(struct mkonthread *mkp)
   size_t ndim=2, dsize[2]={mkp->width[1], mkp->width[0]};
 
   uint8_t *byt;
+  gal_list_sizet_t *Q=NULL;
   int use_rand_points=1, ispeak=1;
   struct builtqueue *ibq=mkp->ibq;
   float circ_r, *img=mkp->ibq->img;
-  struct gal_linkedlist_sll *Q=NULL;
   size_t *dinc=gal_dimension_increment(ndim, dsize);
   double tolerance=mkp->p->tolerance, pixfrac, junk;
   double (*profile)(struct mkonthread *)=mkp->profile;
@@ -239,7 +239,7 @@ makepixbypix(struct mkonthread *mkp)
   double truncr=mkp->truncr, approx, hp=0.5f/mkp->p->oversample;
 
   /* lQ: Largest. sQ: Smallest in queue */
-  struct gal_linkedlist_tosll *lQ=NULL, *sQ;
+  gal_list_tosizet_t *lQ=NULL, *sQ;
 
   /* Find the nearest pixel to the profile center and add it to the
      queue. */
@@ -258,7 +258,7 @@ makepixbypix(struct mkonthread *mkp)
 
   /* Start the queue: */
   byt[p]=1;
-  gal_linkedlist_add_to_tosll_end( &lQ, &sQ, p, r_circle(p, mkp) );
+  gal_list_tosizet_add( &lQ, &sQ, p, r_circle(p, mkp) );
 
   /* If random points are necessary, then do it: */
   if(mkp->func==PROFILE_SERSIC || mkp->func==PROFILE_MOFFAT
@@ -276,7 +276,7 @@ makepixbypix(struct mkonthread *mkp)
              over sampled image. But all the profile parameters are in the
              non-oversampled image. So we divide the distance by os
              (p->oversample in double type) */
-          gal_linkedlist_pop_from_tosll_start(&lQ, &sQ, &p, &circ_r);
+          gal_list_tosizet_pop_smallest(&lQ, &sQ, &p, &circ_r);
           mkp->x=(p/is1-xc)/os;
           mkp->y=(p%is1-yc)/os;
           r_el(mkp);
@@ -312,8 +312,7 @@ makepixbypix(struct mkonthread *mkp)
               if(byt[nind]==0)
                 {
                   byt[nind]=1;
-                  gal_linkedlist_add_to_tosll_end( &lQ, &sQ, nind,
-                                                   r_circle(nind, mkp) );
+                  gal_list_tosizet_add( &lQ, &sQ, nind, r_circle(nind, mkp) );
                 }
             } );
 
@@ -324,13 +323,13 @@ makepixbypix(struct mkonthread *mkp)
 
   /* All the pixels that required integration or random points are now
      done, so we don't need an ordered array any more. */
-  gal_linkedlist_tosll_into_sll(lQ, &Q);
+  gal_list_tosizet_to_sizet(lQ, &Q);
 
 
   /* Order doesn't matter any more, add all the pixels you find. */
   while(Q)
     {
-      gal_linkedlist_pop_from_sll(&Q, &p);
+      p=gal_list_sizet_pop(&Q);
       mkp->x=(p/is1-xc)/os;
       mkp->y=(p%is1-yc)/os;
       r_el(mkp);
@@ -356,7 +355,7 @@ makepixbypix(struct mkonthread *mkp)
           if(byt[nind]==0)
             {
               byt[nind]=1;
-              gal_linkedlist_add_to_sll(&Q, nind);
+              gal_list_sizet_add(&Q, nind);
             }
         } );
     }
diff --git a/bin/mkprof/ui.c b/bin/mkprof/ui.c
index 8dab859..3c1071e 100644
--- a/bin/mkprof/ui.c
+++ b/bin/mkprof/ui.c
@@ -377,21 +377,21 @@ ui_read_cols(struct mkprofparams *p)
   int checkblank;
   char *colname=NULL;
   size_t counter=0, i;
+  gal_list_str_t *colstrs=NULL;
   gal_data_t *cols, *tmp, *corrtype=NULL;
   char *ax1col=p->racol?p->racol:p->xcol;
   char *ax2col=p->deccol?p->deccol:p->ycol;
-  struct gal_linkedlist_stll *colstrs=NULL;
 
   /* Specify the order of columns. */
-  gal_linkedlist_add_to_stll(&colstrs, ax1col, 0);
-  gal_linkedlist_add_to_stll(&colstrs, ax2col, 0);
-  gal_linkedlist_add_to_stll(&colstrs, p->fcol, 0);
-  gal_linkedlist_add_to_stll(&colstrs, p->rcol, 0);
-  gal_linkedlist_add_to_stll(&colstrs, p->ncol, 0);
-  gal_linkedlist_add_to_stll(&colstrs, p->pcol, 0);
-  gal_linkedlist_add_to_stll(&colstrs, p->qcol, 0);
-  gal_linkedlist_add_to_stll(&colstrs, p->mcol, 0);
-  gal_linkedlist_add_to_stll(&colstrs, p->tcol, 0);
+  gal_list_str_add(&colstrs, ax1col, 0);
+  gal_list_str_add(&colstrs, ax2col, 0);
+  gal_list_str_add(&colstrs, p->fcol, 0);
+  gal_list_str_add(&colstrs, p->rcol, 0);
+  gal_list_str_add(&colstrs, p->ncol, 0);
+  gal_list_str_add(&colstrs, p->pcol, 0);
+  gal_list_str_add(&colstrs, p->qcol, 0);
+  gal_list_str_add(&colstrs, p->mcol, 0);
+  gal_list_str_add(&colstrs, p->tcol, 0);
 
   /* Read the desired columns from the file. */
   cols=gal_table_read(p->catname, p->cp.hdu, colstrs, p->cp.searchin,
@@ -405,7 +405,7 @@ ui_read_cols(struct mkprofparams *p)
   while(cols!=NULL)
     {
       /* Pop out the top column. */
-      tmp=gal_data_pop_from_ll(&cols);
+      tmp=gal_list_data_pop(&cols);
 
       /* By default check if the column has blank values, but it can be
          turned off for some columns. */
@@ -806,31 +806,33 @@ ui_make_log(struct mkprofparams *p)
   if(p->cp.log==0) return;
 
   /* Individual created. */
-  gal_data_add_to_ll(&p->log, NULL, GAL_TYPE_UINT8, 1, &p->num, NULL,
-                     1, p->cp.minmapsize, "INDIV_CREATED", "bool",
-                     "If an individual image was made (1) or not (0).");
+  gal_list_data_add_alloc(&p->log, NULL, GAL_TYPE_UINT8, 1, &p->num, NULL,
+                          1, p->cp.minmapsize, "INDIV_CREATED", "bool",
+                          "If an individual image was made (1) or not (0).");
 
   /* Fraction of monte-carlo. */
-  gal_data_add_to_ll(&p->log, NULL, GAL_TYPE_FLOAT32, 1, &p->num, NULL,
-                     1, p->cp.minmapsize, "FRAC_MONTECARLO", "frac",
-                     "Fraction of brightness in Monte-carlo integrated "
-                     "pixels.");
+  gal_list_data_add_alloc(&p->log, NULL, GAL_TYPE_FLOAT32, 1, &p->num, NULL,
+                          1, p->cp.minmapsize, "FRAC_MONTECARLO", "frac",
+                          "Fraction of brightness in Monte-carlo integrated "
+                          "pixels.");
 
   /* Number of monte-carlo. */
-  gal_data_add_to_ll(&p->log, NULL, GAL_TYPE_UINT64, 1, &p->num, NULL,
-                     1, p->cp.minmapsize, "NUM_MONTECARLO", "count",
-                     "Number of Monte Carlo integrated pixels.");
+  gal_list_data_add_alloc(&p->log, NULL, GAL_TYPE_UINT64, 1, &p->num, NULL,
+                          1, p->cp.minmapsize, "NUM_MONTECARLO", "count",
+                          "Number of Monte Carlo integrated pixels.");
 
   /* Magnitude of profile overlap. */
-  gal_data_add_to_ll(&p->log, NULL, GAL_TYPE_FLOAT32, 1, &p->num, NULL,
-                     1, p->cp.minmapsize, "MAG_OVERLAP", "mag",
-                     "Magnitude of profile's overlap with merged image.");
+  gal_list_data_add_alloc(&p->log, NULL, GAL_TYPE_FLOAT32, 1, &p->num, NULL,
+                          1, p->cp.minmapsize, "MAG_OVERLAP", "mag",
+                          "Magnitude of profile's overlap with merged "
+                          "image.");
 
   /* Row number in input catalog. */
   name=gal_fits_name_save_as_string(p->catname, p->cp.hdu);
   asprintf(&comment, "Row number of profile in %s.", name);
-  gal_data_add_to_ll(&p->log, NULL, GAL_TYPE_UINT64, 1, &p->num, NULL,
-                     1, p->cp.minmapsize, "INPUT_ROW_NO", "count", comment);
+  gal_list_data_add_alloc(&p->log, NULL, GAL_TYPE_UINT64, 1, &p->num, NULL,
+                          1, p->cp.minmapsize, "INPUT_ROW_NO", "count",
+                          comment);
   free(comment);
   free(name);
 }
@@ -1035,7 +1037,7 @@ ui_free_report(struct mkprofparams *p, struct timeval *t1)
 
   /* Free the log file information. */
   if(p->cp.log)
-    gal_data_free_ll(p->log);
+    gal_list_data_free(p->log);
 
   /* Report the duration of the job */
   if(!p->cp.quiet)
diff --git a/bin/noisechisel/clumps.c b/bin/noisechisel/clumps.c
index 613f7b5..164c503 100644
--- a/bin/noisechisel/clumps.c
+++ b/bin/noisechisel/clumps.c
@@ -73,8 +73,8 @@ clumps_oversegment(struct clumps_thread_params *cltprm)
 
   float *arr=p->conv->array;
   gal_data_t *indexs=cltprm->indexs;
+  gal_list_sizet_t *Q=NULL, *cleanup=NULL;
   size_t *a, *af, ind, *dsize=p->input->dsize;
-  struct gal_linkedlist_sll *Q=NULL, *cleanup=NULL;
   size_t *dinc=gal_dimension_increment(ndim, dsize);
   int32_t n1, nlab, rlab, curlab=1, *clabel=p->clabel->array;
 
@@ -153,8 +153,8 @@ clumps_oversegment(struct clumps_thread_params *cltprm)
                     "flux regions they aren't", PACKAGE_BUGREPORT);
 
             /* Add this pixel to a queue. */
-            gal_linkedlist_add_to_sll(&Q, *a);
-            gal_linkedlist_add_to_sll(&cleanup, *a);
+            gal_list_sizet_add(&Q, *a);
+            gal_list_sizet_add(&cleanup, *a);
             clabel[*a] = CLUMPS_TMPCHECK;
 
             /* Find all the pixels that have the same flux and are
@@ -162,7 +162,7 @@ clumps_oversegment(struct clumps_thread_params *cltprm)
             while(Q!=NULL)
               {
                 /* Pop an element from the queue. */
-                gal_linkedlist_pop_from_sll(&Q, &ind);
+                ind=gal_list_sizet_pop(&Q);
 
                 /* Look at the neighbors and see if we already have a
                    label. */
@@ -184,8 +184,8 @@ clumps_oversegment(struct clumps_thread_params *cltprm)
                              if( nlab==CLUMPS_INIT && arr[nind]==arr[*a] )
                                {
                                  clabel[nind]=CLUMPS_TMPCHECK;
-                                 gal_linkedlist_add_to_sll(&Q, nind);
-                                 gal_linkedlist_add_to_sll(&cleanup, nind);
+                                 gal_list_sizet_add(&Q, nind);
+                                 gal_list_sizet_add(&cleanup, nind);
                                }
                              else
                                n1=( nlab>0
@@ -246,7 +246,7 @@ clumps_oversegment(struct clumps_thread_params *cltprm)
                the image and were a river pixel. */
             while(cleanup!=NULL)
               {
-                gal_linkedlist_pop_from_sll(&cleanup, &ind);
+                ind=gal_list_sizet_pop(&cleanup);
                 /* If it was on the sides of the image, it has been
                    changed to a river pixel. */
                 if( clabel[ ind ]==CLUMPS_TMPCHECK ) clabel[ ind ]=rlab;
@@ -1057,10 +1057,16 @@ clumps_find_make_sn_table(void *in_prm)
                                                          p->clabel->type),
                                        ndim, dsize, scoord);
 
-          /* Add the index of every sky element to the array of indexs. */
+          /* Add the index of every sky element to the array of
+             indexs. Note that since we know the array is always of type
+             `int32_t', we can call the `GAL_TILE_PO_OISET' macro to avoid
+             having to deal with multiple possible types in
+             `GAL_TILE_PARSE_OPERATE'. Since the OUT macro-variable is
+             NULL, the `int' is just a place-holder, it will not be
+             used. */
           c=0;
           indarr=cltprm.indexs->array;
-          GAL_TILE_PARSE_OPERATE({
+          GAL_TILE_PO_OISET(int32_t, int, {
               /* This pixel's index over all the image. */
               ind = (int32_t *)i - (int32_t *)(p->clabel->array);
               gal_dimension_index_to_coord(ind, ndim, dsize, icoord);
@@ -1110,8 +1116,9 @@ clumps_find_make_sn_table(void *in_prm)
 
           /* Set all river pixels to CLUMPS_INIT (to be distinguishable
              from the detected regions). */
-          GAL_TILE_PARSE_OPERATE({if(*i==CLUMPS_RIVER) *i=CLUMPS_INIT;},
-                                 tile, NULL, 0, 1);
+          GAL_TILE_PO_OISET(int32_t, int,
+                            {if(*i==CLUMPS_RIVER) *i=CLUMPS_INIT;},
+                            tile, NULL, 0, 1);
 
           /* For a check, the step variable will be set. */
           if(clprm->step==1)
@@ -1170,7 +1177,7 @@ clumps_true_find_sn_thresh(struct noisechiselparams *p)
   struct timeval t1;
   size_t i, j, c, numsn=0;
   struct clumps_params clprm;
-  struct gal_linkedlist_stll *comments=NULL;
+  gal_list_str_t *comments=NULL;
   gal_data_t *sn, *snind, *quant, *claborig;
 
   /* Get starting time for later reporting if necessary. */
@@ -1305,16 +1312,14 @@ clumps_true_find_sn_thresh(struct noisechiselparams *p)
     {
       /* Make the comments, then write the table and free the comments. */
       if(p->cp.numthreads>1)
-        gal_linkedlist_add_to_stll(&comments, "NOTE: In multi-threaded mode, "
-                                   "clump IDs differ in each run and are not "
-                                   "sorted.", 1);
-      gal_linkedlist_add_to_stll(&comments, "See also: `SKY_CLUMPS_FOR_SN' "
-                                 "HDU of output with `--checksegmentation'.",
-                                 1);
-      gal_linkedlist_add_to_stll(&comments, "S/N of clumps over undetected "
-                                 "regions.", 1);
+        gal_list_str_add(&comments, "NOTE: In multi-threaded mode, clump "
+                         "IDs differ in each run and are not sorted.", 1);
+      gal_list_str_add(&comments, "See also: `SKY_CLUMPS_FOR_SN' HDU of "
+                       "output with `--checksegmentation'.", 1);
+      gal_list_str_add(&comments, "S/N of clumps over undetected regions.",
+                       1);
       threshold_write_sn_table(p, sn, snind, p->clumpsn_s_name, comments);
-      gal_linkedlist_free_stll(comments, 1);
+      gal_list_str_free(comments, 1);
     }
 
 
diff --git a/bin/noisechisel/detection.c b/bin/noisechisel/detection.c
index 76b8250..37de617 100644
--- a/bin/noisechisel/detection.c
+++ b/bin/noisechisel/detection.c
@@ -392,13 +392,13 @@ detection_sn_write_to_file(struct noisechiselparams *p, 
gal_data_t *sn,
                            gal_data_t *snind, int s0d1D2)
 {
   char *str;
-  struct gal_linkedlist_stll *comments=NULL;
+  gal_list_str_t *comments=NULL;
 
   /* Comment for extension on further explanation. */
   asprintf(&str, "See also: `%s' HDU of output with "
            "`--checkdetection'", ( s0d1D2<2
                                    ? "PSEUDOS-FOR-SN": "DILATED" ));
-  gal_linkedlist_add_to_stll(&comments, str, 0);
+  gal_list_str_add(&comments, str, 0);
 
 
   /* Description comment. */
@@ -407,7 +407,7 @@ detection_sn_write_to_file(struct noisechiselparams *p, 
gal_data_t *sn,
               ? "S/N of dilated detections."
               : "Pseudo-detection S/N over initial detections." )
           : "Pseudo-detection S/N over initial undetections.");
-  gal_linkedlist_add_to_stll(&comments, str, 1);
+  gal_list_str_add(&comments, str, 1);
 
 
   /* Set the file name. */
@@ -415,7 +415,7 @@ detection_sn_write_to_file(struct noisechiselparams *p, 
gal_data_t *sn,
           ? ( s0d1D2==2 ? p->detsn_D_name : p->detsn_d_name )
           : p->detsn_s_name );
   threshold_write_sn_table(p, sn, snind, str, comments);
-  gal_linkedlist_free_stll(comments, 1);
+  gal_list_str_free(comments, 1);
 
 
   /* Abort NoiseChisel if the user asked for it. */
@@ -735,7 +735,7 @@ detection_final_remove_small_sn(struct noisechiselparams 
*p, size_t num)
   float *snarr;
   gal_data_t *sn, *snind;
   int32_t *l, *lf, curlab=1;
-  struct gal_linkedlist_stll *comments=NULL;
+  gal_list_str_t *comments=NULL;
   int32_t *newlabs=gal_data_calloc_array(GAL_TYPE_INT32, num+1);
 
 
@@ -780,14 +780,14 @@ detection_final_remove_small_sn(struct noisechiselparams 
*p, size_t num)
       for(i=0;i<num;++i) { l[i]=i+1; snarr[i]=snarr[i+1]; }
 
       /* Make the comments, then write the table. */
-      gal_linkedlist_add_to_stll(&comments, "See also: `DILATED' "
-                                 "HDU of output with `--checkdetection'.", 1);
-      gal_linkedlist_add_to_stll(&comments, "S/N of finally dilated "
-                                 "detections.", 1);
+      gal_list_str_add(&comments, "See also: `DILATED' "
+                       "HDU of output with `--checkdetection'.", 1);
+      gal_list_str_add(&comments, "S/N of finally dilated "
+                       "detections.", 1);
 
 
       threshold_write_sn_table(p, sn, snind, p->detsn_D_name, comments);
-      gal_linkedlist_free_stll(comments, 1);
+      gal_list_str_free(comments, 1);
 
     }
 
diff --git a/bin/noisechisel/segmentation.c b/bin/noisechisel/segmentation.c
index 74b7697..782a3ab 100644
--- a/bin/noisechisel/segmentation.c
+++ b/bin/noisechisel/segmentation.c
@@ -511,10 +511,10 @@ segmentation_save_sn_table(struct clumps_params *clprm)
   char *msg;
   float *sarr;
   int32_t *oiarr, *cioarr;
+  gal_list_str_t *comments=NULL;
   size_t i, j, c=0, totclumps=0;
   gal_data_t *sn, *objind, *clumpinobj;
   struct noisechiselparams *p=clprm->p;
-  struct gal_linkedlist_stll *comments=NULL;
 
 
   /* Find the total number of clumps in all the initial detections. Recall
@@ -550,14 +550,12 @@ segmentation_save_sn_table(struct clumps_params *clprm)
 
 
   /* Write the comments. */
-  gal_linkedlist_add_to_stll(&comments, "See also: `CLUMPS_ALL_DET' HDU of "
-                             "output with `--checksegmentation'.", 1);
+  gal_list_str_add(&comments, "See also: `CLUMPS_ALL_DET' HDU of "
+                   "output with `--checksegmentation'.", 1);
   asprintf(&msg, "S/N values of `nan': clumps smaller than `--segsnminarea' "
            "of %zu.", p->segsnminarea);
-  gal_linkedlist_add_to_stll(&comments, msg, 1);
-  free(msg);
-  gal_linkedlist_add_to_stll(&comments, "S/N of clumps over detected "
-                             "regions.", 1);
+  gal_list_str_add(&comments, msg, 0);
+  gal_list_str_add(&comments, "S/N of clumps over detected regions.", 1);
   gal_table_comments_add_intro(&comments, PROGRAM_STRING, &p->rawtime);
 
 
@@ -571,7 +569,7 @@ segmentation_save_sn_table(struct clumps_params *clprm)
   gal_data_free(sn);
   gal_data_free(objind);
   gal_data_free(clumpinobj);
-  gal_linkedlist_free_stll(comments, 1);
+  gal_list_str_free(comments, 1);
 
 
   /* Abort NoiseChisel if necessary. */
diff --git a/bin/noisechisel/threshold.c b/bin/noisechisel/threshold.c
index 0ec6258..a765553 100644
--- a/bin/noisechisel/threshold.c
+++ b/bin/noisechisel/threshold.c
@@ -110,7 +110,7 @@ threshold_apply_on_thread(void *in_prm)
              will help in efficiency, because the compiler can move this
              check out of the loop and only check for NaN values when we
              know the tile has blank pixels. */
-          GAL_TILE_PARSE_OPERATE({
+          GAL_TILE_PO_OISET(float, uint8_t, {
               *o = ( *i > value1[tid]
                      ? ( *i > value2[tid] ? THRESHOLD_NO_ERODE_VALUE : 1 )
                      : ( (tile->flag & GAL_DATA_FLAG_HASBLANK) && !(*i==*i)
@@ -127,7 +127,7 @@ threshold_apply_on_thread(void *in_prm)
 
           /* See the explanation above the same step in the quantile
              threshold for an explanation. */
-          GAL_TILE_PARSE_OPERATE({
+          GAL_TILE_PO_OISET(float, uint8_t, {
               *o = ( ( *i - value1[tid] > p->dthresh * value2[tid] )
                      ? 1
                      : ( (tile->flag & GAL_DATA_FLAG_HASBLANK) && !(*i==*i)
@@ -187,7 +187,7 @@ threshold_apply(struct noisechiselparams *p, float *value1,
 void
 threshold_write_sn_table(struct noisechiselparams *p, gal_data_t *insn,
                          gal_data_t *inind, char *filename,
-                         struct gal_linkedlist_stll *comments)
+                         gal_list_str_t *comments)
 {
   gal_data_t *sn, *ind, *cols;
 
diff --git a/bin/noisechisel/threshold.h b/bin/noisechisel/threshold.h
index 606dddd..75f88c0 100644
--- a/bin/noisechisel/threshold.h
+++ b/bin/noisechisel/threshold.h
@@ -40,7 +40,7 @@ threshold_apply(struct noisechiselparams *p, float *value1, 
float *value2,
 void
 threshold_write_sn_table(struct noisechiselparams *p, gal_data_t *sntable,
                          gal_data_t *snind, char *filename,
-                         struct gal_linkedlist_stll *comments);
+                         gal_list_str_t *comments);
 
 void
 threshold_interp_smooth(struct noisechiselparams *p, gal_data_t **first,
diff --git a/bin/statistics/main.h b/bin/statistics/main.h
index 8761a9b..5c115dd 100644
--- a/bin/statistics/main.h
+++ b/bin/statistics/main.h
@@ -55,8 +55,8 @@ struct statisticsparams
 {
   /* From command-line */
   struct gal_options_common_params cp; /* Common parameters.             */
-  struct gal_linkedlist_ill  *singlevalue; /* Single value calculations. */
-  struct gal_linkedlist_dll  *tp_args; /* Arguments for printing.        */
+  gal_list_i32_t         *singlevalue; /* Single value calculations.     */
+  gal_list_f64_t  *tp_args;  /* Arguments for printing.                  */
   char          *inputname;  /* Input filename.                          */
   char             *column;  /* Column name or number if input is table. */
   char             *refcol;  /* Reference column name or number.         */
diff --git a/bin/statistics/statistics.c b/bin/statistics/statistics.c
index be8af9f..3636d84 100644
--- a/bin/statistics/statistics.c
+++ b/bin/statistics/statistics.c
@@ -77,7 +77,7 @@ statistics_read_check_args(struct statisticsparams *p)
           "requested single measurement options. Please contact "
           "us at %s so we can address the problem",
           PACKAGE_BUGREPORT);
-  gal_linkedlist_pop_from_dll(&p->tp_args, &d);
+  d=gal_list_f64_pop(&p->tp_args);
   return d;
 }
 
@@ -92,7 +92,7 @@ statistics_print_one_row(struct statisticsparams *p)
   char *toprint;
   size_t dsize=1;
   double arg, *d;
-  struct gal_linkedlist_ill *tmp;
+  gal_list_i32_t *tmp;
   gal_data_t *tmpv, *out=NULL, *num=NULL, *min=NULL, *max=NULL;
   gal_data_t *sum=NULL, *med=NULL, *meanstd=NULL, *modearr=NULL;
 
@@ -264,10 +264,10 @@ static void
 statistics_on_tile(struct statisticsparams *p)
 {
   double arg=0;
+  gal_list_i32_t *operation;
   gal_data_t *tile, *values;
   size_t tind, dsize=1, mind=-1;
   uint8_t type=GAL_TYPE_INVALID;
-  struct gal_linkedlist_ill *operation;
   gal_data_t *tmp=NULL, *tmpv=NULL, *ttmp;
   struct gal_options_common_params *cp=&p->cp;
   struct gal_tile_two_layer_params *tl=&p->cp.tl;
@@ -523,7 +523,7 @@ write_output_table(struct statisticsparams *p, gal_data_t 
*table,
   char *output;
   int use_auto_output=0;
   char *fix, *suffix=NULL, *tmp;
-  struct gal_linkedlist_stll *comments=NULL;
+  gal_list_str_t *comments=NULL;
 
 
   /* Automatic output should be used when no output name was specified or
@@ -551,10 +551,10 @@ write_output_table(struct statisticsparams *p, gal_data_t 
*table,
      the order we want them. They will later be freed as part of the list's
      freeing.*/
   tmp=gal_fits_name_save_as_string(p->inputname, p->cp.hdu);
-  gal_linkedlist_add_to_stll(&comments, tmp, 0);
+  gal_list_str_add(&comments, tmp, 0);
 
   asprintf(&tmp, "%s created from:", contents);
-  gal_linkedlist_add_to_stll(&comments, tmp, 0);
+  gal_list_str_add(&comments, tmp, 0);
 
   if(strcmp(fix, "fits"))  /* The intro info will be in FITS files anyway.*/
     gal_table_comments_add_intro(&comments, PROGRAM_STRING, &p->rawtime);
@@ -572,8 +572,8 @@ write_output_table(struct statisticsparams *p, gal_data_t 
*table,
 
   /* Clean up. */
   if(suffix) free(suffix);
+  gal_list_str_free(comments, 1);
   if(output!=p->cp.output) free(output);
-  gal_linkedlist_free_stll(comments, 1);
 }
 
 
diff --git a/bin/statistics/ui.c b/bin/statistics/ui.c
index ce414ef..b6b6607 100644
--- a/bin/statistics/ui.c
+++ b/bin/statistics/ui.c
@@ -248,7 +248,7 @@ ui_add_to_single_value(struct argp_option *option, char 
*arg,
         }
 
       /* Add this option to the print list. */
-      gal_linkedlist_add_to_ill(&p->singlevalue, option->key);
+      gal_list_i32_add(&p->singlevalue, option->key);
     }
   else
     {
@@ -271,8 +271,8 @@ ui_add_to_single_value(struct argp_option *option, char 
*arg,
                               "to `--quantile' (`-u') must be between 0 "
                               "and 1, you had asked for %g (read from `%s')",
                               d[i], arg);
-              gal_linkedlist_add_to_dll(&p->tp_args, d[i]);
-              gal_linkedlist_add_to_ill(&p->singlevalue, option->key);
+              gal_list_f64_add(&p->tp_args, d[i]);
+              gal_list_i32_add(&p->singlevalue, option->key);
             }
           break;
 
@@ -374,7 +374,7 @@ ui_read_quantile_range(struct argp_option *option, char 
*arg,
 static void
 ui_read_check_only_options(struct statisticsparams *p)
 {
-  struct gal_linkedlist_ill *tmp;
+  gal_list_i32_t *tmp;
   struct gal_tile_two_layer_params *tl=&p->cp.tl;
 
   /* Check if the format of the output table is valid, given the type of
@@ -495,8 +495,8 @@ ui_read_check_only_options(struct statisticsparams *p)
 
   /* Reverse the list of statistics to print in one row and also the
      arguments, so it has the same order the user wanted. */
-  gal_linkedlist_reverse_ill(&p->singlevalue);
-  gal_linkedlist_reverse_dll(&p->tp_args);
+  gal_list_f64_reverse(&p->tp_args);
+  gal_list_i32_reverse(&p->singlevalue);
 }
 
 
@@ -672,7 +672,7 @@ static void
 ui_make_sorted_if_necessary(struct statisticsparams *p)
 {
   int is_necessary=0;
-  struct gal_linkedlist_ill *tmp;
+  gal_list_i32_t *tmp;
 
   /* Check in the one-row outputs. */
   for(tmp=p->singlevalue; tmp!=NULL; tmp=tmp->next)
@@ -716,13 +716,13 @@ ui_read_columns(struct statisticsparams *p)
   int toomanycols=0;
   size_t size, counter=0;
   gal_data_t *cols, *tmp;
-  struct gal_linkedlist_stll *column=NULL;
+  gal_list_str_t *column=NULL;
 
   /* Define the columns that we want, note that they should be added to the
      list in reverse. */
   if(p->refcol)
-    gal_linkedlist_add_to_stll(&column, p->refcol, 0);
-  gal_linkedlist_add_to_stll(&column, p->column, 0);
+    gal_list_str_add(&column, p->refcol, 0);
+  gal_list_str_add(&column, p->column, 0);
 
   /* Read the desired column(s). */
   cols=gal_table_read(p->inputname, p->cp.hdu, column, p->cp.searchin,
@@ -733,7 +733,7 @@ ui_read_columns(struct statisticsparams *p)
   while(cols!=NULL)
     {
       /* Pop out the top column. */
-      tmp=gal_data_pop_from_ll(&cols);
+      tmp=gal_list_data_pop(&cols);
 
       /* Make sure it has the proper size. */
       if(tmp->size!=size)
@@ -771,7 +771,7 @@ ui_read_columns(struct statisticsparams *p)
     }
 
   /* Clean up. */
-  gal_linkedlist_free_stll(column, 0);
+  gal_list_str_free(column, 0);
 }
 
 
@@ -961,11 +961,10 @@ ui_free_report(struct statisticsparams *p)
   /* Free the allocated arrays: */
   free(p->cp.hdu);
   free(p->cp.output);
-  if(p->sorted!=p->input)
-    gal_data_free(p->sorted);
   gal_data_free(p->input);
   gal_data_free(p->reference);
-  gal_linkedlist_free_dll(p->tp_args);
+  gal_list_f64_free(p->tp_args);
+  gal_list_i32_free(p->singlevalue);
   gal_tile_full_free_contents(&p->cp.tl);
-  gal_linkedlist_free_ill(p->singlevalue);
+  if(p->sorted!=p->input) gal_data_free(p->sorted);
 }
diff --git a/bin/table/main.h b/bin/table/main.h
index 9bbbf42..76ad9a4 100644
--- a/bin/table/main.h
+++ b/bin/table/main.h
@@ -45,7 +45,7 @@ struct tableparams
   /* From command-line */
   struct gal_options_common_params cp; /* Common parameters.            */
   char              *filename;  /* Input filename.                      */
-  struct gal_linkedlist_stll *columns; /* List of given columns.        */
+  gal_list_str_t     *columns;  /* List of given columns.               */
   uint8_t         information;  /* ==1, only print FITS information.    */
 
   /* Output: */
diff --git a/bin/table/ui.c b/bin/table/ui.c
index 00c2167..f8977aa 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -317,7 +317,7 @@ ui_preparations(struct tableparams *p)
         for(i=1;i<=numcols;++i)
           {
             asprintf(&tmp, "%zu", i);
-            gal_linkedlist_add_to_stll(&p->columns, tmp, 0);
+            gal_list_str_add(&p->columns, tmp, 0);
           }
     }
 
@@ -325,7 +325,7 @@ ui_preparations(struct tableparams *p)
      (since this is a last-in-first-out linked list, the order that
      elements were added to the list is the reverse of the order that they
      will be popped). */
-  gal_linkedlist_reverse_stll(&p->columns);
+  gal_list_str_reverse(&p->columns);
   p->table=gal_table_read(p->filename, cp->hdu, p->columns, cp->searchin,
                           cp->ignorecase, cp->minmapsize);
 
@@ -337,7 +337,7 @@ ui_preparations(struct tableparams *p)
 
   /* Now that the data columns are ready, we can free the string linked
      list. */
-  gal_linkedlist_free_stll(p->columns, 1);
+  gal_list_str_free(p->columns, 1);
 }
 
 
@@ -442,5 +442,5 @@ ui_free_report(struct tableparams *p)
   /* Free the allocated arrays: */
   free(p->cp.hdu);
   free(p->cp.output);
-  gal_data_free_ll(p->table);
+  gal_list_data_free(p->table);
 }
diff --git a/bin/warp/ui.c b/bin/warp/ui.c
index 2d82578..755fd66 100644
--- a/bin/warp/ui.c
+++ b/bin/warp/ui.c
@@ -588,7 +588,7 @@ ui_matrix_from_modular(struct warpparams *p)
 
   /* Reverse the list of modular warpings to be in the same order as the
      user specified.*/
-  gal_data_reverse_ll(&p->modularll);
+  gal_list_data_reverse(&p->modularll);
 
   /* Allocate space for the final matrix. */
   p->matrix=gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 2, dsize, NULL, 0,
@@ -604,7 +604,7 @@ ui_matrix_from_modular(struct warpparams *p)
   while(p->modularll)
     {
       /* Pop the top element. */
-      pop=gal_data_pop_from_ll(&p->modularll);
+      pop=gal_list_data_pop(&p->modularll);
 
       /* Set the (possibly) two values given for this warp. */
       v1 = pop->ndim   ? ((double *)(pop->array))[0] : 0.0f;
diff --git a/bootstrap.conf b/bootstrap.conf
index 364efbd..d98e28e 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -217,11 +217,13 @@ gnulib_modules="
     regex
     error
     nproc
+    stdint
     strtod
     getline
     strcase
     gendocs
     mbstok_r
+    inttypes
     git-version-gen
 "
 
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 5273526..386b08d 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -196,7 +196,7 @@ sub-component to a title is present.
 * Data analysis::               Analyze images.
 * Modeling and fittings::       Make and fit models.
 * High-level calculations::     Physical calculations.
-* Libraries::                   Use Gnuastro in your own code.
+* Library::                     Gnuastro's library of useful functions.
 * Developing::                  The development environment.
 * Gnuastro programs list::      List and short summary of Gnuastro.
 * Other useful software::       Installing other useful software.
@@ -512,7 +512,7 @@ CosmicCalculator
 * Extending distance concepts to 3D::  Going to 3D (our real universe).
 * Invoking astcosmiccal::       How to run CosmicCalculator
 
-Libraries
+Library
 
 * Review of library fundamentals::  Guide on libraries and linking.
 * Gnuastro library::            Description of all library functions.
@@ -528,8 +528,10 @@ Review of library fundamentals
 Gnuastro library
 
 * Configuration information::   General information about library config.
-* Library data container::
 * Library data types::
+* Library blank values::
+* Library data container::
+* Linked lists::                Various types of linked lists.
 * Table input output::
 * Arithmetic on datasets::
 * Tessellation library::
@@ -537,7 +539,6 @@ Gnuastro library
 * FITS files::                  Working with FITS data.
 * Text files::
 * Git wrappers::                Wrappers for functions in libgit2.
-* Linked lists::                Various types of linked lists.
 * Polygons::                    Working with the vertices of a polygon.
 * Qsort functions::             Helper functions for Qsort.
 * Statistical operations::      Functions for basic statistics.
@@ -547,7 +548,17 @@ Gnuastro library
 Data container (@file{data.h})
 
 * Generic data container::
-* Basic dataset functions::
+* Dataset size and allocation::
+* Arrays of datasets::
+
+Linked lists (@file{linkedlist.h})
+
+* List of strings::
+* List of int32_t::
+* List of size_t::
+* Ordered list of size_t::
+* Two way list of ordered size_t::
+* List of gal_data_t::
 
 FITS files (@file{fits.h})
 
@@ -15408,7 +15419,7 @@ were of integer types.
 
 
 
address@hidden High-level calculations, Libraries, Modeling and fittings, Top
address@hidden High-level calculations, Library, Modeling and fittings, Top
 @chapter High-level calculations
 
 After the reduction of raw data (for example with the programs in @ref{Data
@@ -15818,8 +15829,8 @@ of options and how to effectively use them.
 
 
 
address@hidden Libraries, Developing, High-level calculations, Top
address@hidden Libraries
address@hidden Library, Developing, High-level calculations, Top
address@hidden Library
 
 Each program in Gnuastro that was discussed in the prior chapters (or any
 program in general) is a collection of functions that is compiled into one
@@ -15857,7 +15868,7 @@ program} to easily define your own programs(s).
 * Library demo programs::
 @end menu
 
address@hidden Review of library fundamentals, Gnuastro library, Libraries, 
Libraries
address@hidden Review of library fundamentals, Gnuastro library, Library, 
Library
 @section Review of library fundamentals
 
 Gnuastro's libraries are written in the C programming language. In @ref{Why
@@ -16484,7 +16495,7 @@ $ gnuastro-gcc myprog && ./myprog
 @end example
 
 
address@hidden Gnuastro library, Library demo programs, Review of library 
fundamentals, Libraries
address@hidden Gnuastro library, Library demo programs, Review of library 
fundamentals, Library
 @section Gnuastro library
 
 Gnuastro library's programming constructs (function declarations, macros,
@@ -16537,8 +16548,10 @@ documentation will correspond to your installed 
version.
 
 @menu
 * Configuration information::   General information about library config.
-* Library data container::
 * Library data types::
+* Library blank values::
+* Library data container::
+* Linked lists::                Various types of linked lists.
 * Table input output::
 * Arithmetic on datasets::
 * Tessellation library::
@@ -16546,7 +16559,6 @@ documentation will correspond to your installed version.
 * FITS files::                  Working with FITS data.
 * Text files::
 * Git wrappers::                Wrappers for functions in libgit2.
-* Linked lists::                Various types of linked lists.
 * Polygons::                    Working with the vertices of a polygon.
 * Qsort functions::             Helper functions for Qsort.
 * Statistical operations::      Functions for basic statistics.
@@ -16554,7 +16566,7 @@ documentation will correspond to your installed version.
 * World Coordinate System::     Dealing with the world coordinate system.
 @end menu
 
address@hidden Configuration information, Library data container, Gnuastro 
library, Gnuastro library
address@hidden Configuration information, Library data types, Gnuastro library, 
Gnuastro library
 @subsection Configuration information (@file{config.h})
 
 The @file{gnuastro/config.h} header contains information about the full
@@ -16640,7 +16652,37 @@ with the expression address@hidden size_t}' without 
having to include this
 header.
 @end deffn
 
address@hidden Library data container, Library data types, Configuration 
information, Gnuastro library
address@hidden Library data types, Library blank values, Configuration 
information, Gnuastro library
address@hidden Library data types (@file{type.h})
+
+This header defines basic type identifiers and functions relating to the
+different types.
+
address@hidden Library blank values, Library data container, Library data 
types, Gnuastro library
address@hidden Library blank values (@file{blank.h})
+When the position of an element in a dataset is important (for example a
+pixel in an image), a place-holder is necessary for the element if we don't
+have a value to fill it with (for example the CCD cannot read those
+pixels). We cannot simply shift all the other pixels to fill in the one we
+have no value for. In other cases, it often occurs that the field of sky
+that you are studying is not a clean rectangle. You need a way to separate
+the pixels outside your scientific field from those inside it. Blank values
+are these place holders.
+
address@hidden NaN
+Every type needs a corresponding blank value (see @ref{Numeric data types}
+and @ref{Library data types}). Floating point types have a unique value
+identified by IEEE known as Not-a-Number (or NaN) which is a unique value
+that is recognized by the compiler. However, integer and string types don't
+have any standard value. For integers, in Gnuastro we take an extremum of
+the given type: for signed types (that allow negatives), the minimum
+possible value is used as blank and for unsigned types (that only accept
+positives), the maximum possible value is used. To be generic and easy to
+read/write we define a macro for these blank values and strongly encourage
+you tonly use these. Never make any assumption on the value of a type's
+blank value.
+
address@hidden Library data container, Linked lists, Library blank values, 
Gnuastro library
 @subsection Data container (@file{data.h})
 
 Astronomical datasets have various dimensions, for example 1D spectra or
@@ -16655,10 +16697,11 @@ generic dataset, Gnuastro defines the 
@code{gal_data_t} as input or output.
 
 @menu
 * Generic data container::
-* Basic dataset functions::
+* Dataset size and allocation::
+* Arrays of datasets::
 @end menu
 
address@hidden Generic data container, Basic dataset functions, Library data 
container, Library data container
address@hidden Generic data container, Dataset size and allocation, Library 
data container, Library data container
 @subsubsection Generic data container (@code{gal_data_t})
 
 To be able to deal with any dataset (various dimensions, numeric data
@@ -16983,14 +17026,14 @@ Scientific Library (GSL) does it in its ``Vectors and 
Matrices'' chapter.
 @end table
 
 
address@hidden Basic dataset functions,  , Generic data container, Library data 
container
address@hidden Basic dataset functions
address@hidden Dataset size and allocation, Arrays of datasets, Generic data 
container, Library data container
address@hidden Dataset size and allocation
 
-Gnuastro's main data container was defined in @ref{Generic data container},
-the functions listed in this section describe the most basic operations on
address@hidden, operations related to the size, allocation,
-initializations, copying, changing types and etc. The first class of
-functions discussed below are for size, allocation and initialization.
+Gnuastro's main data container was defined in @ref{Generic data container}.
+The functions listed in this section describe the most basic operations on
address@hidden: those related to the size, pointers, allocation and
+freeing. These functions are declared in @file{gnuastro/data.h} which is
+also visible from the function names (see @ref{Gnuastro library}).
 
 @deftypefun int gal_data_dsize_is_different (gal_data_t @code{*first}, 
gal_data_t @code{*second})
 Return @code{1} (one) if the two datasets don't have the same size along
@@ -17080,18 +17123,30 @@ Free all the address@hidden pointers in 
@code{gal_data_t}, then free the
 actual data structure.
 @end deftypefun
 
address@hidden is a very versatile structure that can be used in many
-higher-level contexts. For example you can have an array of
address@hidden structures when several @code{gal_data_t}s are
-related. The functions below are defined to create a cleared array of data
-structures and to free them.
address@hidden Arrays of datasets,  , Dataset size and allocation, Library data 
container
address@hidden Arrays of datasets
+
+Gnuastro's generic data container (@code{gal_data_t}) is a very versatile
+structure that can be used in many higher-level contexts. One such
+higher-level construct is an array of @code{gal_data_t} structures to
+simplify the allocation (and later clearning) of several @code{gal_data_t}s
+that are related.
+
+For example, each column in a table is usually represented by one
address@hidden (so it has its own name, numeric data type, units and
+etc). A table (with many columns) can be seen as an array of
address@hidden (when the number of columns is known a-priori). The
+functions below are defined to create a cleared array of data structures
+and to free them in the end. These functions are declared in
address@hidden/data.h} which is also visible from the function names (see
address@hidden library}).
 
 @deftypefun {gal_data_t *} gal_data_array_calloc (size_t @code{size})
 Allocate an array of @code{gal_data_t} with @code{size} elements. This
 function will also initialize all the values (@code{NULL} for pointers and
 0 for other types). You can use @code{gal_data_initialize} to fill each
-element of the array. The following code snippet is one example of using
-arrays of @code{gal_data_t}.
+element of the array afterwards. The following code snippet is one example
+of doing this.
 
 @example
 size_t i;
@@ -17110,13 +17165,550 @@ element of all the datasets will also be freed, see 
@ref{Generic data
 container}.
 @end deftypefun
 
address@hidden Library data types, Table input output, Library data container, 
Gnuastro library
address@hidden Library data types (@file{type.h})
address@hidden Linked lists, Table input output, Library data container, 
Gnuastro library
address@hidden Linked lists (@file{linkedlist.h})
+
address@hidden Array
address@hidden Linked list
+An array is a contiguous region of memory that is very efficient and easy
+to use for recording and later accessing any random element as fast as any
+other. This makes array the primary data container when you have many
+elements (for example an image which has millions of pixels). One major
+problem with an array is that the number of elements that go into it must
+be known in advance and adding or removing an element will require a re-set
+of all the other elements. For example if you want to remove the 3rd
+element in a 1000 element array, all 997 subsequent elements have to pulled
+back by one position, the reverse will happen if you need to add an
+element.
+
+In many contexts such situations never come up, for example you don't want
+to shift all the pixels in an image by one or two pixels from some random
+position in the image: their positions have scientific value. But in other
+contexts you will find your self frequently adding/removing an a-priori
+unknown of elements. Linked lists (or @emph{lists} for short) are the
+data-container of choice in such situations. As in a chain, each
address@hidden in a list is an independent C structure, keeping its own data
+along with pointer(s) to its immediate neighbor(s). Below, you can see one
+simple linked list node structure along with an ASCII art schematic of how
+we can use the @code{next} pointer to add any number of elements to the
+list that we want. By convension, a list is terminated when @code{next} is
+the @code{NULL} pointer.
+
address@hidden The second and last lines lines are pushed line space forward, 
because
address@hidden the address@hidden' at the start of the line is only seen as `{' 
in the book.
address@hidden
+struct list_float          /*     ---------    ---------           */
address@hidden                          /*     | Value |    | Value |           
*/
+  float             value; /*     |  ---  |    |  ---  |           */
+  struct list_float *next; /*     |  next-|--> |  next-|--> NULL   */
address@hidden                          /*     ---------    ---------           
*/
address@hidden example
+
+The schematic shows another great advantage of linked lists: it is very
+easy to add or remove/pop a node anywhere in the list. If you want to
+modify the first node, you just have to change one pointer. If it is in the
+middle, you just have to change two. You initially define a variable of
+this type with a @code{NULL} pointer as shown below:
+
address@hidden
+struct list_float *mylist=NULL
address@hidden example
+
address@hidden
+then you use functions provided for that the respective type in the
+sections below to add elements to add or remove/pop an element from the
+list.
+
address@hidden last-in-first-out
address@hidden first-in-first-out
address@hidden
+When you add an element to the list, it is conventionally added to the
+``top'' of the list: the general list pointer will point to the newly
+created node, which will point to the previously created node and so on. So
+when you ``pop'' from the top of the list, you are actually retrieving the
+last value you put in and changing the list pointer to the next youngest
+node. This is thus known as a ``last-in-first-out'' list. This is the most
+efficient type of linked list (easier to implement and faster to
+process). Alternatively, you can add each newly created node at the end of
+the list. If you do that, you will get a ``first-in-first-out'' list. But
+that will force you to go through the whole list for each new element that
+is created (this will slow down the processing)@footnote{A better way to
+get a first-in-first-out is to first keep the data as last-in-first-out
+until they are all read. Afterwards, pop each node and immediately add it
+to the new list: practically reversing the last-in-first-out list to a
+first-in-first-out one. All the list types discussed in this chapter have a
address@hidden function.}.
+
+The node example above creates the simplest kind of a list. We can define
+each node with two pointers to both the next and previous neighbors, this
+is called a ``Doubly linked list''. In general, lists are very powerful and
+simple constructs that can be very useful. But going into more detail would
+be out of the scope of this short introduction in this
+book. @url{https://en.wikipedia.org/wiki/Linked_list, Wikipedia} has a nice
+and more thorough discussion of the various types of lists. To
+appreciate/use the beauty and elegance of these powerful constructs even
+further, see Chapter 2 (Information Structures, in volume 1) of Donald
+Knuth's ``The art of computer programming''.
+
+In this section we will review the functions and structures that are
+available in Gnuastro for working on lists. They differ by the type of data
+that each node can keep. For each linked-list node structure, we will first
+introduce the structure, then the functions for working on the
+structure. All these structures and functions are defined and declared in
address@hidden/list.h}.
+
+
address@hidden
+* List of strings::
+* List of int32_t::
+* List of size_t::
+* Ordered list of size_t::
+* Two way list of ordered size_t::
+* List of gal_data_t::
address@hidden menu
+
address@hidden List of strings, List of int32_t, Linked lists, Linked lists
address@hidden List of strings
+
+Probably one of the most common lists you will be using are lists of
+strings. They are the best tools when you are reading the user's inputs, or
+when adding comments to the output files. Below you can see Gnuastro's
+string list type and several functions to help in adding, removing/popping,
+reversing and freeing the list.
+
address@hidden {Type (C @code{struct})} gal_list_str_t
+A single node in a list containing a string of characters.
address@hidden
+typedef struct gal_list_str_t
address@hidden
+  char *v;
+  struct gal_list_str_t *next;
address@hidden gal_list_str_t;
address@hidden example
address@hidden deftp
+
address@hidden void gal_list_str_add (gal_list_str_t @code{**list}, char 
@code{*value}, int @code{allocate})
+Add a new node to the list of strings (@code{list}) and update it. The new
+node will contain the string @code{value}. If @code{allocate} is not zero,
+space will be allocated specifically for the string of the new node and the
+contents of @code{value} will be copied into it. This can be useful when
+your string may be changed later in the program, but you want your list to
+remain. Here is one short/simple example of initializing and adding
+elements to a string list:
+
address@hidden
+gal_list_str_t *strlist=NULL;
+gal_list_str_add(&strlist, "bottom of list.");
+gal_list_str_add(&strlist, "second last element of list.");
address@hidden example
+
address@hidden deftypefun
+
address@hidden {char *} gal_list_str_pop (gal_list_str_t @code{**list})
+Pop the top element of @code{list}, change @code{list} to point to the next
+node in the list, and return the string that was in the popped node. If
address@hidden, then this function will also return a @code{NULL}
+pointer.
address@hidden deftypefun
+
address@hidden size_t gal_list_str_number (gal_list_str_t @code{*list})
+Return the number of nodes in @code{list}.
address@hidden deftypefun
+
address@hidden void gal_list_str_print (gal_list_str_t @code{*list})
+Print the strings within each node of @code{*list} on the standard output
+in the same order that they are stored. Each string is printed on one
+line. This function is mainly good for checking/debugging your program. For
+program outputs, its best to make your own implementation with a better,
+more user-friendly, format. For example the following code snippet.
+
address@hidden
+size_t i;
+gal_list_str_t *tmp=NULL;
+for(tmp=list; tmp!=NULL; tmp=tmp->next)
+  printf("String %zu: %s\n", i, tmp->v);
address@hidden example
address@hidden deftypefun
+
address@hidden void gal_list_str_reverse (gal_list_str_t @code{**list})
+Reverse the order of the list such that the top node in the list before
+calling this function becomes the bottom node after it.
address@hidden deftypefun
+
address@hidden void gal_list_str_free (gal_list_str_t @code{*list}, int 
@code{freevalue})
+Free each node in @code{list}. If @code{freevalue} is not zero, also free
+the string within the nodes.
address@hidden deftypefun
+
+
+
+
address@hidden List of int32_t, List of size_t, List of strings, Linked lists
address@hidden List of @code{int32_t}
+
+Signed integers are the best types when you are dealing with a positive or
+negative integers. The are generally useful in many contexts, for example
+when you want to keep the order of a series of states (each state stored as
+a given number in an @code{enum} for example).
+
address@hidden {Type (C @code{struct})} gal_list_i32_t
+A single node in a list containing a 32-bit signed integers (see
address@hidden data types}).
address@hidden
+typedef struct gal_list_i32_t
address@hidden
+  int32_t *v;
+  struct gal_list_i32_t *next;
address@hidden gal_list_i32_t;
address@hidden example
address@hidden deftp
+
+
address@hidden void gal_list_i32_add (gal_list_i32_t @code{**list}, int32_t 
@code{*value})
+Add a new node (containing @code{value}) to the list of integers
+(@code{list}) and update it.  Here is one short example of initializing and
+adding elements to a string list:
+
address@hidden
+gal_list_i32_t *i32list=NULL;
+gal_list_i32_add(&i32list, 52);
+gal_list_i32_add(&i32list, -4);
address@hidden example
+
address@hidden deftypefun
+
address@hidden {int32_t} gal_list_i32_pop (gal_list_i32_t @code{**list})
+Pop the top element of @code{list} and return the value. This function will
+also change @code{list} to point to the next node in the list. If
address@hidden, then this function will also return
address@hidden (see @ref{Library blank values}).
address@hidden deftypefun
+
address@hidden size_t gal_list_i32_number (gal_list_i32_t @code{*list})
+Return the number of nodes in @code{list}.
address@hidden deftypefun
+
address@hidden void gal_list_i32_print (gal_list_i32_t @code{*list})
+Print the integers within each node of @code{*list} on the standard output
+in the same order that they are stored. Each integer is printed on one
+line. This function is mainly good for checking/debugging your program. For
+program outputs, its best to make your own implementation with a better,
+more user-friendly format. For example the following code snippet. You can
+also modify it to print all values in one line, and etc, depending on the
+context of your program.
+
address@hidden
+size_t i;
+gal_list_i32_t *tmp=NULL;
+for(tmp=list; tmp!=NULL; tmp=tmp->next)
+  printf("String %zu: %s\n", i, tmp->v);
address@hidden example
address@hidden deftypefun
+
address@hidden void gal_list_i32_reverse (gal_list_i32_t @code{**list})
+Reverse the order of the list such that the top node in the list before
+calling this function becomes the bottom node after it.
address@hidden deftypefun
+
address@hidden void gal_list_i32_free (gal_list_i32_t @code{*list})
+Free each node in @code{list}.
address@hidden deftypefun
+
+
+
address@hidden List of size_t, Ordered list of size_t, List of int32_t, Linked 
lists
address@hidden List of @code{size_t}
+
+The @code{size_t} type is a unique type in C: as the name suggests it is
+defined to store sizes, or more accurately, the distances between memory
+locations. Hence it is always positive (an @code{unsigned} type) and it is
+directly related to the address-able spaces on the host system: on 32-bit
+and 64-bit systems it is an alias for @code{uint32_t} and @code{uint64_t},
+respectively (see @ref{Numeric data types}).
+
address@hidden is the default compiler type to index an array (recall that
+an array index in C is just a pointer increment of a given
address@hidden). Since it is unsigned, its a great type for counting (where
+negative is not defined), you are always sure it will never exceed the
+system's (virtual) memory and since its name has the word ``size'' inside
+it, it provides a good level of address@hidden you know that a
+variable of this type is not used to store some generic state for
+example.}. In Gnuastro, we do all counting and array indexing with this
+type, so this list is very handy.
+
address@hidden {Type (C @code{struct})} gal_list_sizet_t
+A single node in a list containing a @code{size_t} values: either
address@hidden or @code{uint64_t} depending on the host system, see
address@hidden data types}.
address@hidden
+typedef struct gal_list_sizet_t
address@hidden
+  size_t *v;
+  struct gal_list_sizet_t *next;
address@hidden gal_list_sizet_t;
address@hidden example
address@hidden deftp
 
-This header defines basic type identifiers and functions relating to the
-different types.
 
address@hidden Table input output, Arithmetic on datasets, Library data types, 
Gnuastro library
address@hidden void gal_list_sizet_add (gal_list_sizet_t @code{**list}, size_t 
@code{*value})
+Add a new node (containing @code{value}) to the list of @code{size_t}s
+(@code{list}) and update it.  Here is one short example of initializing and
+adding elements to a string list:
+
address@hidden
+gal_list_sizet_t *slist=NULL;
+gal_list_sizet_add(&slist, 45493);
+gal_list_sizet_add(&slist, 930484);
address@hidden example
+
address@hidden deftypefun
+
address@hidden {sizet_t} gal_list_sizet_pop (gal_list_sizet_t @code{**list})
+Pop the top element of @code{list} and return the value. This function will
+also change @code{list} to point to the next node in the list. If
address@hidden, then this function will also return
address@hidden (see @ref{Library blank values}).
address@hidden deftypefun
+
address@hidden size_t gal_list_sizet_number (gal_list_sizet_t @code{*list})
+Return the number of nodes in @code{list}.
address@hidden deftypefun
+
address@hidden void gal_list_sizet_print (gal_list_sizet_t @code{*list})
+Print the values within each node of @code{*list} on the standard output in
+the same order that they are stored. Each integer is printed on one
+line. This function is mainly good for checking/debugging your program. For
+program outputs, its best to make your own implementation with a better,
+more user-friendly format. For example, the following code snippet. You can
+also modify it to print all values in one line, and etc, depending on the
+context of your program.
+
address@hidden
+size_t i;
+gal_list_sizet_t *tmp=NULL;
+for(tmp=list; tmp!=NULL; tmp=tmp->next)
+  printf("String %zu: %zu\n", i, tmp->v);
address@hidden example
address@hidden deftypefun
+
address@hidden void gal_list_sizet_reverse (gal_list_sizet_t @code{**list})
+Reverse the order of the list such that the top node in the list before
+calling this function becomes the bottom node after it.
address@hidden deftypefun
+
address@hidden void gal_list_sizet_free (gal_list_sizet_t @code{*list})
+Free each node in @code{list}.
address@hidden deftypefun
+
+
+
+
+
+
address@hidden Ordered list of size_t, Two way list of ordered size_t, List of 
size_t, Linked lists
address@hidden Ordered list of size_t
+
address@hidden Structure gal_linkedlist_osll
address@hidden @code{size_t}
+Ordered @code{size_t} linked list (@code{osll}. Each node in this
+singly-linked list contains a @code{size_t} value and a floating point
+value. The floating point value is used as a reference to add new nodes in
+a sorted manner. At any moment, the first popped node in this list will
+have the smallest @code{tosort} value, and subsequent nodes will have
+larger to values.
address@hidden deftp
address@hidden
+struct gal_linkedlist_osll
address@hidden
+  size_t                         v;
+  float                          s;
+  struct gal_linkedlist_osll *next;
address@hidden;
address@hidden example
+
address@hidden void gal_linkedlist_add_to_osll (struct gal_linkedlist_osll 
@code{**list}, size_t @code{value}, float @code{tosort})
+Allocate space for a new node in @code{list}, and store @code{value} into
+it. The new node will be added to the list based on the @code{tosort}
+value.
address@hidden deftypefun
+
address@hidden void gal_linkedlist_pop_from_osll (struct gal_linkedlist_osll 
@code{**list}, size_t @code{*value}, float @code{*sortvalue})
+Pop a node from the top of @code{list}, put its value in @code{value} and
+its sort value in @code{sortvalue}. This function will also free the
+allocated space for the popped node and after this function, @code{list}
+will point to the next node (which has a larger @code{tosort} element).
address@hidden deftypefun
+
address@hidden void gal_linkedlist_osll_into_sll (struct gal_linkedlist_osll 
@code{*in}, struct gal_linkedlist_sll @code{**out})
+Convert the orderd @code{size_t} linked list into an ordinary @code{size_t}
+linked list (no longer sorted). This can be useful when all the elements
+have been added and you just need to pop-out elements.
address@hidden deftypefun
+
+
address@hidden Two way list of ordered size_t, List of gal_data_t, Ordered list 
of size_t, Linked lists
address@hidden Two way list of ordered @code{size_t}
address@hidden Structure gal_linkedlist_tosll
address@hidden @code{size_t}
+
+Two-way, ordered @code{size_t} linked list (@code{tosll}. Each node in this
+Doubly-linked list contains a @code{size_t} value and a floating point
+value. The floating point value is used as a reference to add new nodes in
+a sorted manner. In the functions here, this linked list can be pointed to
+by two pointers (largest and smallest) with the following format:
address@hidden
+            largest pointer
+            |
+   NULL <-- (v0,s0) <--> (v1,s1) <--> ... (vn,sn) --> NULL
+                                          |
+                           smallest pointer
address@hidden example
+At any moment, the two pointers will point the nodes containing the
+``largest'' and ``smallest'' values and the rest of the nodes will be
+sorted. This is useful when an unknown number of nodes are being added
+continuously and during the operations it is important to have the nodes in
+a sorted format.
address@hidden deftp
address@hidden
+struct gal_linkedlist_tosll
address@hidden
+  size_t                          v;
+  float                           s;
+  struct gal_linkedlist_tosll *prev;
+  struct gal_linkedlist_tosll *next;
address@hidden;
address@hidden example
+
address@hidden void gal_linkedlist_print_tosll (struct gal_linkedlist_tosll 
@code{*largest}, struct gal_linkedlist_tosll @code{*smallest})
+Print all the values within the linked list to the output terminal. This
+can be used for inspecting the status of the list during development.
address@hidden deftypefun
+
address@hidden void gal_linkedlist_add_to_tosll_end (struct 
gal_linkedlist_tosll @code{**largest}, struct gal_linkedlist_tosll 
@code{**smallest}, size_t @code{value}, float @code{tosort})
+Allocate space for a new node in @code{list}, and store @code{value} into
+it. The new node will be added to the list based on the @code{s} value as
+described in the description of @code{gal_linkedlist_tosll}. If this is the
+first node to be added to the list, both the @code{largest} and
address@hidden pointers can be @code{NULL}.
address@hidden deftypefun
+
address@hidden void gal_linkedlist_pop_from_tosll_start (struct 
gal_linkedlist_tosll @code{**lartest}, struct gal_linkedlist_tosll 
@code{**smallest}, size_t @code{*value}, float @code{*tosort})
+Pop the node with the smallest @code{s} of @code{list}, then put its value
+in @code{value} and its sort value in @code{sortvalue}. This function will
+also free the allocated space for the popped node and after this function,
address@hidden and @code{smallest} will be modified respectively. Note that
+even though only the smallest pointer will be popped, when there was only
+one node in the list, the @code{largest} pointer also has to change, so we
+need both.
address@hidden deftypefun
+
address@hidden void gal_linkedlist_smallest_tosll (struct gal_linkedlist_tosll 
@code{*largest}, struct gal_linkedlist_tosll @code{**smallest})
+Given the @code{largest} pointer, set @code{smallest} as described in
address@hidden
address@hidden deftypefun
+
address@hidden void gal_linkedlist_tosll_into_sll (struct gal_linkedlist_tosll 
@code{*in}, struct gal_linkedlist_sll @code{**out})
+Convert the two-way orderd @code{size_t} linked list into an ordinary
address@hidden linked list (no longer sorted). This can be useful when all
+the elements have been added and you just need to pop-out elements.
address@hidden deftypefun
+
address@hidden void gal_linkedlist_tosll_free (struct gal_linkedlist_tosll 
@code{*largest})
+Free the space for all the nodes in @code{largest}. Note that any values
+within the nodes will also be discarded.
address@hidden deftypefun
+
+
+
address@hidden List of gal_data_t,  , Two way list of ordered size_t, Linked 
lists
address@hidden List of @code{gal_data_t}
+
+Linked lists are a programming construct that allow several containers to
+be connected without a-priori knowledge of the number of elements, see
address@hidden://en.wikipedia.org/wiki/Linked_list, Wikipedia}, or @ref{Linked
+lists} for a more thorough discussion. The @code{next} element of
+Gnuastro's generic data container enables each dataset to be treated as a
+node in a simply linked list (see @ref{Generic data container}). This
+higher-level construct offers great versatility in combining multiple
+datasets and treating them as a larger whole.
+
+Tables are one example of the usage of linked lists: each column in a table
+in an independent dataset: with its own name, units, numeric data type (see
address@hidden data types}). The only constraint is on a table column dataset
+is its size: it is one-dimensional and must have the same number of
+elements as the other columns in the table. Another application is in
+Tessellating an input dataset into separate tiles or only studying
+particular regions, or tiles, of a larger dataset (see @ref{Tessellation
+library}). Each independent tile over the dataset can be connected to the
+others as a linked list and thus any number of tiles can be represented
+with one variable.
+
+The space keeping each @code{gal_data_t} node (column/tile in the examples
+above) in the linked list can be allocated once for many nodes as an array,
+when the total number is known a-priori (see @ref{Arrays of datasets}), or
+each dataset can be allocated separately: when the total number isn't
+finalized. In any case, through the @code{next} element, it is possible to
+connect them to define a linked list. The functions here are mainly useful
+in the latter case. There are two important things to keep in mind when
+defining and using simple linked lists:
+
address@hidden
+
address@hidden
+Before adding any nodes to a list, initialize it with a @code{NULL}
+pointer. The @code{NULL} pointer will mark the end/bottom of the list as
+more elements are added ontop of it.
+
address@hidden
+Simple linked lists are a last-in-first-out structure: so the last element
+you add to the top of the list is the first one that is popped out of, or
+read from, the list later. Hence when order matters, you can add the nodes
+to a list, then reverse the list with @code{gal_data_reverse_ll},
+otherwise, you should add them in reverse order from the beginning (which
+is only possible when the total number is known a-priori).
address@hidden itemize
+
+Here is one example of using these functions:
+
address@hidden
+gal_data_t *node, *newnode, *list=NULL;
+size_t minmapsize=-1; /* Largest unsigned number: data in RAM. */
+
+newnode=gal_fits_img_read("img1.fits", "1", minmapsize);
+gal_data_add_existing_to_ll(&list, newnode);
+
+newnode=gal_fits_img_read("img2.fits", "1", minmapsize);
+gal_data_add_existing_to_ll(&list, newnode);
+
+...                                   /* Read any more images. */
+
+gal_data_reverse_ll(&list);              /* Correct the order. */
+
+for(node=list; node!=NULL; node=node->next) /* Parse the list. */
+  @{
+    ...                          /* Do any further processing. */
+  @}
+
+gal_data_free_ll(list);                           /* Clean up. */
+list=NULL;          /* To be safe (if the function continues). */
address@hidden example
+
+These functions are declared in @file{gnuastro/data.h} which is also
+visible from the function names (see @ref{Gnuastro library}).
+
address@hidden void gal_data_add_existing_to_ll (gal_data_t @code{**list}, 
gal_data_t @code{*newnode})
+This function will add @code{newnode} to the top of the linked list pointed
+to by @code{*list}. Note that you need to give the pointer to the list,
+since this function will put @code{newnode} at the list's start/top (and
+thus change @code{*list}). Here is one example to read-in a series of
+images:
address@hidden deftypefun
+
+
+
+
+
address@hidden Table input output, Arithmetic on datasets, Linked lists, 
Gnuastro library
 @subsection Table input output (@file{table.h})
 
 Functions to read columns from/to tables.
@@ -17590,7 +18182,7 @@ error notice.
 @subsection Text files (@file{txt.h})
 
 
address@hidden Git wrappers, Linked lists, Text files, Gnuastro library
address@hidden Git wrappers, Polygons, Text files, Gnuastro library
 @subsection Git wrappers (@file{git.h})
 
 @cindex Git
@@ -17626,402 +18218,11 @@ not installed or the program calling this function 
is not within a version
 controlled directory, then the output will be the @code{NULL} pointer.
 @end deftypefun
 
address@hidden Linked lists, Polygons, Git wrappers, Gnuastro library
address@hidden Linked lists (@file{linkedlist.h})
-
address@hidden Array
address@hidden Linked list
-An array is a contiguous region of memory that is very efficient and easy
-to use for recording and later accessing the data. One major problem with
-an array is that the number of elements that go into it must be known in
-advance. This is where linked lists can be very useful: like a metal chain,
-each @emph{node} in a linked list is an independent C structure, keeping
-its own data along with pointer(s) to its immediate neighbor(s). Below we
-have one simple linked list node structure along with an ASCII art
-schematic of how we can use the @code{next} pointer to add any number of
-elements to the list that we want. The linked list is terminated when
address@hidden is a @code{NULL} pointer.
-
address@hidden The second and last lines lines are pushed line space forward, 
because
address@hidden the address@hidden' at the start of the line is only seen as `{' 
in the book.
address@hidden
-struct float_ll          /*     ---------    ---------              */
address@hidden                        /*     | Value |    | Value |             
 */
-  float          value;  /*     |  ---  |    |  ---  |              */
-  struct ll_node *next;  /*     |  next-|--> |  next-|--> NULL      */
address@hidden                        /*     ---------    ---------             
 */
address@hidden example
-
-The schematic shows another great advantage of linked lists: it is very
-easy to add or remove a node anywhere in the list (you just have to change
-one pointer in the structure above). You initially define a variable of
-this type with a @code{NULL} pointer as shown below, then you use functions
-provided for that type of linked list to add elements to the list or pop
-elements from it.
-
address@hidden
-struct float_ll *mylist=NULL
address@hidden example
-
address@hidden last-in-first-out
address@hidden first-in-first-out
address@hidden
-When you add an element to the list, it is conventionally added to the
-``top'' of the list: the general list pointer will point to the newly
-created node, which will point to the previously created node and so on. So
-when you ``pop'' from the top of the list, you are actually retrieving the
-last value you put in and changing the list pointer to the next oldest
-node. This is thus known as a ``last-in-first-out'' list. This is the most
-convenient type of linked list (easier to implement and faster to
-process). Alternatively, you can add each newly created node at the end of
-the list. If you do that, you will get a ``first-in-first-out'' list. But
-that will force you to go through the whole list for each new element that
-is created (this can slow down the processing)@footnote{A better way to get
-a first-in-first-out is to first keep the data as last-in-first-out until
-they are all read. Afterwards, pop each node and immediately add it to the
-new list: practically reversing the last-in-first-out list to a
-first-in-first-out one.}.
-
-Each node in a linked list doesn't have to have a single pointer to the
-next node like the example above. We can define each node with two pointers
-to both the next and previous neighbors, this is called a ``Doubly linked
-list''. In general, lists are very powerful and simple constructs that can
-be very useful. But going into more detail would be out of the scope of
-this short introduction in this
-book. @url{https://en.wikipedia.org/wiki/Linked_list, Wikipedia} has a nice
-and more thorough discussion of the various types of lists, so for more,
-please have a look at that article.
-
-In this section we will review the functions and structures that are
-available in Gnuastro for working on linked lists. For each linked-list
-node structure, we will first introduce the structure, then the functions
-for working on the structure. All these structures and functions are
-defined and declared in @file{gnuastro/linkedlist.h}.
-
-
address@hidden Structure gal_linkedlist_fll
-Float linked list (@code{fll}). Each node in this singly-linked list can
-have a single float type value.
address@hidden deftp
address@hidden
-struct gal_linkedlist_fll
address@hidden
-    float                         v;
-    struct gal_linkedlist_fll *next;
address@hidden;
address@hidden example
-
address@hidden void gal_linkedlist_print_fll_array (struct gal_linkedlist_fll 
@code{**afll}, size_t @code{num})
-Print all the values within the linked list to the output terminal. This
-can be used for inspecting the status of the list during development.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_add_to_fll (struct gal_linkedlist_fll 
@code{**list}, float @code{value})
-Allocate space for a new node in @code{list}, and put @code{value} into
-it. The new node will be added to the top of the list. So after this
-function, the already existing nodes will be appended to the new node and
address@hidden will point to the newly created node.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_pop_from_fll (struct gal_linkedlist_fll 
@code{**list}, float @code{*value})
-Pop a node from the top of @code{list} and put its values in
address@hidden This function will also free the allocated space for the
-popped node and after this function, @code{list} will point to the next
-node.
address@hidden deftypefun
-
address@hidden size_t gal_linkedlist_num_in_fll (struct gal_linkedlist_fll 
@code{*list})
-Return the number of nodes in @code{list}, the contents of @code{list} will
-be untouched.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_fll_to_array (struct gal_linkedlist_fll 
@code{*list}, float @code{**f}, size_t @code{*num})
-Put the elements of @code{list} into an array @code{f} and store the number
-of nodes in the list in @code{num}. The array will be filled in the same
-order as popped elements from the list. This function will allocate space
-for the @code{num} element @code{f} array internally, so you have to free
-it afterwards.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_free_fll (struct gal_linkedlist_fll 
@code{*list})
-Free the space for all the nodes in @code{list}. Note that any values
-within the nodes will also be discarded. This can be used when the list is
-no longer relevant for you. For example, you might have already converted
-the list to an array for future usage with
address@hidden
address@hidden deftypefun
-
address@hidden void gal_linkedlist_free_fll_array (struct gal_linkedlist_fll 
@code{**afll}, size_t @code{num})
-Free an array of @code{gal_linkedlist_fll} linked lists (@code{num}
-elements). Each element of the array is a pointer to a linked list, so we
-first need to free the separate linked lists, then the array.
address@hidden deftypefun
-
-
address@hidden Structure gal_linkedlist_tdll
-Two doubles linked list (@code{tdll}. Each node in this singly-linked list
-can have two double type values. It can be used to store an unknown number
-of floating point coordinates (for example RA and Dec).
address@hidden deftp
address@hidden
-struct gal_linkedlist_tdll
address@hidden
-    double                         a;
-    double                         b;
-    struct gal_linkedlist_tdll *next;
address@hidden;
address@hidden example
-
address@hidden void gal_linkedlist_add_to_tdll (struct gal_linkedlist_tdll 
@code{**list}, double @code{a}, double @code{b})
-Allocate space for a new node in @code{list}, and put the values @code{a}
-and @code{b} into it. The new node will be added to the top of the list. So
-after this function, the already existing nodes will be appended to the new
-node and @code{list} will point to the newly created node.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_pop_from_tdll (struct gal_linkedlist_tdll 
@code{**list}, double @code{*a}, double @code{*b})
-Pop a node from the top of @code{list} and put its values in @code{a} and
address@hidden This function will also free the allocated space for the popped
-node and after this function, @code{list} will point to the next node.
address@hidden deftypefun
-
address@hidden size_t gal_linkedlist_num_int_dll (struct gal_linkedlist_tdll 
@code{*list})
-Return the number of nodes in @code{list}. The contents of @code{list} will
-be untouched.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_tdll_to_array_inv (struct 
gal_linkedlist_tdll @code{*list}, double @code{**d}, size_t @code{*num})
-Put the elements of @code{list} into an array @code{d} in inverse order and
-store the number of nodes in the list in @code{num}. This function will
-allocate space for the @address@hidden element array internally
-so you have to free it afterwards. The two values for each node will be
-stored adjacently, so the array can be seen as a 2D array with @code{num}
-rows and 2 columns.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_free_tdll (struct gal_linkedlist_tdll 
@code{*list})
-Free the space for all the nodes in @code{list}. Note that any values
-within the nodes will also be discarded. This can be used when the list is
-no longer relevant for you. For example, you might have already converted
-the list to an array for future usage with
address@hidden
address@hidden deftypefun
-
-
address@hidden Structure gal_linkedlist_stll
-String linked list (@code{stll}. Each node in this singly-linked list has a
-string variable.
address@hidden deftp
address@hidden
-struct gal_linkedlist_stll
address@hidden
-    char                          *v;
-    struct gal_linkedlist_stll *next;
address@hidden;
address@hidden example
-
address@hidden void gal_linkedlist_add_to_stll (struct gal_linkedlist_stll 
@code{**list}, char @code{*value})
-Allocate space for a new node in @code{list}, and store the @code{value}
-pointer into it. The new node will be added to the top of the list. So
-after this function, the already existing nodes will be appended to the new
-node and @code{list} will point to the newly created node.
-
-It is important to remember that this function will only copy the pointer
-in the node, it will not allocate space for the string. So the string
-either has to be a literal string (with a fixed address) or dynamically
-allocated when this linked list is to be filled and used within one
-function.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_pop_from_stll (struct gal_linkedlist_stll 
@code{**list}, char @code{**value})
-Pop a node from the top of @code{list} and put its pointer in
address@hidden This function will also free the allocated space for the
-popped node and after this function, @code{list} will point to the next
-node.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_reverse_stll (struct gal_linkedlist_stll 
@code{**list})
-Reverse the linked list. The @code{gal_linkedlist_add_to_stll} function
-will make a last-in-first-out list, but commonly you will need a
-first-in-first-out list. This function can thus be useful after adding to
-the list has finished.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_print_stll (struct gal_linkedlist_stll 
@code{*list})
-Print all the values within the linked list to the output terminal. This
-can be used for inspecting the status of the list during development.
address@hidden deftypefun
-
address@hidden size_t gal_linkedlist_num_in_stll (struct gal_linkedlist_stll 
@code{*list})
-Return the number of nodes in @code{list}. The contents of @code{list} will
-be untouched.
address@hidden deftypefun
-
address@hidden Structure gal_linkedlist_sll
address@hidden @code{size_t}
address@hidden linked list (@code{sll}. Each node in this singly-linked list
-contains a @code{size_t} value. The @code{size_t} type is commonly used for
-``size'' related values: it is an un-signed type (negative values are not
-defined for it), therefore it is ideal for dealing with things like pixel
-indexes in an image (which can not be negative and can be very large).
address@hidden deftp
address@hidden
-struct gal_linkedlist_sll
address@hidden
-    size_t                        v;
-    struct gal_linkedlist_sll *next;
address@hidden;
address@hidden example
-
address@hidden void gal_linkedlist_add_to_sll (struct gal_linkedlist_sll 
@code{**list}, size_t @code{value})
-Allocate space for a new node in @code{list}, and store @code{value} into
-it. The new node will be added to the top of the list. So after this
-function, the already existing nodes will be appended to the new node and
address@hidden will point to the newly created node.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_pop_from_sll (struct gal_linkedlist_sll 
@code{**list}, size_t @code{*value})
-Pop a node from the top of @code{list} and put its value in
address@hidden This function will also free the allocated space for the
-popped node and after this function, @code{list} will point to the next
-node.
address@hidden deftypefun
-
address@hidden size_t gal_linkedlist_num_in_sll (struct gal_linkedlist_sll 
@code{*list})
-Return the number of nodes in @code{list}. The contents of @code{list} will
-be untouched.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_print_sll (struct gal_linkedlist_sll 
@code{*list})
-Print all the values within the linked list to the output terminal. This
-can be used for inspecting the status of the list during development.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_sll_to_array (struct gal_linkedlist_sll 
@code{*list}, size_t @code{**s}, size_t @code{*num}, int @code{inverse})
-Put the elements of @code{list} into an array @code{s} and store the number
-of nodes in the list in @code{num}. This function will allocate space for
-the @code{num} element array internally so you have to free it
-afterwards. If the value in @code{inverse} is @code{1}, then the first
-popped value in the list will be the last element in the array, otherwise,
-the array will be filled in the same order that the elements were popped.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_free_sll (struct gal_linkedlist_sll 
@code{*list})
-Free the space for all the nodes in @code{list}. Note that any values
-within the nodes will also be discarded. This can be used when the list is
-no longer relevant for you. For example, you might have already converted
-the list to an array for future usage with
address@hidden
address@hidden deftypefun
-
address@hidden Structure gal_linkedlist_osll
address@hidden @code{size_t}
-Ordered @code{size_t} linked list (@code{osll}. Each node in this
-singly-linked list contains a @code{size_t} value and a floating point
-value. The floating point value is used as a reference to add new nodes in
-a sorted manner. At any moment, the first popped node in this list will
-have the smallest @code{tosort} value, and subsequent nodes will have
-larger to values.
address@hidden deftp
address@hidden
-struct gal_linkedlist_osll
address@hidden
-  size_t                         v;
-  float                          s;
-  struct gal_linkedlist_osll *next;
address@hidden;
address@hidden example
-
address@hidden void gal_linkedlist_add_to_osll (struct gal_linkedlist_osll 
@code{**list}, size_t @code{value}, float @code{tosort})
-Allocate space for a new node in @code{list}, and store @code{value} into
-it. The new node will be added to the list based on the @code{tosort}
-value.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_pop_from_osll (struct gal_linkedlist_osll 
@code{**list}, size_t @code{*value}, float @code{*sortvalue})
-Pop a node from the top of @code{list}, put its value in @code{value} and
-its sort value in @code{sortvalue}. This function will also free the
-allocated space for the popped node and after this function, @code{list}
-will point to the next node (which has a larger @code{tosort} element).
address@hidden deftypefun
-
address@hidden void gal_linkedlist_osll_into_sll (struct gal_linkedlist_osll 
@code{*in}, struct gal_linkedlist_sll @code{**out})
-Convert the orderd @code{size_t} linked list into an ordinary @code{size_t}
-linked list (no longer sorted). This can be useful when all the elements
-have been added and you just need to pop-out elements.
address@hidden deftypefun
-
address@hidden Structure gal_linkedlist_tosll
address@hidden @code{size_t}
-Two-way, ordered @code{size_t} linked list (@code{tosll}. Each node in this
-Doubly-linked list contains a @code{size_t} value and a floating point
-value. The floating point value is used as a reference to add new nodes in
-a sorted manner. In the functions here, this linked list can be pointed to
-by two pointers (largest and smallest) with the following format:
address@hidden
-            largest pointer
-            |
-   NULL <-- (v0,s0) <--> (v1,s1) <--> ... (vn,sn) --> NULL
-                                          |
-                           smallest pointer
address@hidden example
-At any moment, the two pointers will point the nodes containing the
-``largest'' and ``smallest'' values and the rest of the nodes will be
-sorted. This is useful when an unknown number of nodes are being added
-continuously and during the operations it is important to have the nodes in
-a sorted format.
address@hidden deftp
address@hidden
-struct gal_linkedlist_tosll
address@hidden
-  size_t                          v;
-  float                           s;
-  struct gal_linkedlist_tosll *prev;
-  struct gal_linkedlist_tosll *next;
address@hidden;
address@hidden example
-
address@hidden void gal_linkedlist_print_tosll (struct gal_linkedlist_tosll 
@code{*largest}, struct gal_linkedlist_tosll @code{*smallest})
-Print all the values within the linked list to the output terminal. This
-can be used for inspecting the status of the list during development.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_add_to_tosll_end (struct 
gal_linkedlist_tosll @code{**largest}, struct gal_linkedlist_tosll 
@code{**smallest}, size_t @code{value}, float @code{tosort})
-Allocate space for a new node in @code{list}, and store @code{value} into
-it. The new node will be added to the list based on the @code{s} value as
-described in the description of @code{gal_linkedlist_tosll}. If this is the
-first node to be added to the list, both the @code{largest} and
address@hidden pointers can be @code{NULL}.
address@hidden deftypefun
 
address@hidden void gal_linkedlist_pop_from_tosll_start (struct 
gal_linkedlist_tosll @code{**lartest}, struct gal_linkedlist_tosll 
@code{**smallest}, size_t @code{*value}, float @code{*tosort})
-Pop the node with the smallest @code{s} of @code{list}, then put its value
-in @code{value} and its sort value in @code{sortvalue}. This function will
-also free the allocated space for the popped node and after this function,
address@hidden and @code{smallest} will be modified respectively. Note that
-even though only the smallest pointer will be popped, when there was only
-one node in the list, the @code{largest} pointer also has to change, so we
-need both.
address@hidden deftypefun
 
address@hidden void gal_linkedlist_smallest_tosll (struct gal_linkedlist_tosll 
@code{*largest}, struct gal_linkedlist_tosll @code{**smallest})
-Given the @code{largest} pointer, set @code{smallest} as described in
address@hidden
address@hidden deftypefun
-
address@hidden void gal_linkedlist_tosll_into_sll (struct gal_linkedlist_tosll 
@code{*in}, struct gal_linkedlist_sll @code{**out})
-Convert the two-way orderd @code{size_t} linked list into an ordinary
address@hidden linked list (no longer sorted). This can be useful when all
-the elements have been added and you just need to pop-out elements.
address@hidden deftypefun
-
address@hidden void gal_linkedlist_tosll_free (struct gal_linkedlist_tosll 
@code{*largest})
-Free the space for all the nodes in @code{largest}. Note that any values
-within the nodes will also be discarded.
address@hidden deftypefun
 
 
address@hidden Polygons, Qsort functions, Linked lists, Gnuastro library
address@hidden Polygons, Qsort functions, Git wrappers, Gnuastro library
 @subsection Polygons (@file{polygon.h})
 
 Polygons are commonly necessary in image processing. In Gnuastro, they are
@@ -18589,10 +18790,10 @@ Given the WCS structure @code{wcs} calculate the 
pixel area in
 arcsec-squared.
 @end deftypefun
 
address@hidden Library demo programs,  , Gnuastro library, Libraries
address@hidden Library demo programs,  , Gnuastro library, Library
 @section Library demo programs
 
-In this final section of @ref{Libraries}, we give some example Gnuastro
+In this final section of @ref{Library}, we give some example Gnuastro
 programs to demonstrate various features in the library. All these programs
 have been tested and once Gnuastro is installed you can compile and run
 them with with the program-like shell function that is described in
@@ -18682,7 +18883,7 @@ main(void)
 
 
 
address@hidden Developing, Gnuastro programs list, Libraries, Top
address@hidden Developing, Gnuastro programs list, Library, Top
 @chapter Developing
 
 The basic idea of GNU Astronomy Utilities is for an interested astronomer
@@ -19326,7 +19527,7 @@ which contains nice animated images of using Emacs.
 @cindex Convention for program source
 @cindex Gnuastro program structure convention
 Besides the fact that all the programs share some functions that were
-explained in @ref{Libraries}, everything else about each program is
+explained in @ref{Library}, everything else about each program is
 completely independent. In this section the conventions used in all the
 program sources are explained in @ref{Mandatory source code files}. To
 easily understand the explanations in this section you can use @ref{The
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 9d8070a..1f87c7d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -52,9 +52,9 @@ libgnuastro_la_LIBADD = 
$(top_builddir)/bootstrapped/lib/libgnu.la
 # Specify the library .c files
 libgnuastro_la_SOURCES = arithmetic.c arithmetic-binary.c                  \
   arithmetic-onlyint.c binary.c blank.c box.c checkset.c convolve.c data.c \
-  fits.c git.c interpolate.c linkedlist.c options.c permutation.c          \
-  polygon.c qsort.c dimension.c statistics.c table.c threads.c tile.c      \
-  timing.c txt.c type.c wcs.c
+  fits.c git.c interpolate.c list.c options.c permutation.c polygon.c      \
+  qsort.c dimension.c statistics.c table.c threads.c tile.c timing.c txt.c \
+  type.c wcs.c
 
 
 
@@ -66,14 +66,14 @@ libgnuastro_la_SOURCES = arithmetic.c arithmetic-binary.c   
               \
 # in the $(headersdir) directory. Some of the header files don't need to be
 # installed.
 headersdir=$(top_srcdir)/lib/gnuastro
-pkginclude_HEADERS = gnuastro/config.h $(headersdir)/arithmetic.h         \
-  $(headersdir)/binary.h $(headersdir)/blank.h $(headersdir)/box.h        \
+pkginclude_HEADERS = gnuastro/config.h $(headersdir)/arithmetic.h          \
+  $(headersdir)/binary.h $(headersdir)/blank.h $(headersdir)/box.h         \
   $(headersdir)/convolve.h $(headersdir)/data.h $(headersdir)/dimension.h  \
-  $(headersdir)/fits.h $(headersdir)/git.h $(headersdir)/interpolate.h    \
-  $(headersdir)/linkedlist.h $(headersdir)/permutation.h                  \
-  $(headersdir)/polygon.h $(headersdir)/qsort.h $(headersdir)/statistics.h \
-  $(headersdir)/table.h $(headersdir)/threads.h $(headersdir)/tile.h      \
-  $(headersdir)/txt.h $(headersdir)/type.h $(headersdir)/wcs.h
+  $(headersdir)/fits.h $(headersdir)/git.h $(headersdir)/interpolate.h     \
+  $(headersdir)/list.h $(headersdir)/permutation.h $(headersdir)/polygon.h \
+  $(headersdir)/qsort.h $(headersdir)/statistics.h $(headersdir)/table.h   \
+  $(headersdir)/threads.h $(headersdir)/tile.h $(headersdir)/txt.h         \
+  $(headersdir)/type.h $(headersdir)/wcs.h
 
 
 
diff --git a/lib/arithmetic.c b/lib/arithmetic.c
index 54c5464..252e0a6 100644
--- a/lib/arithmetic.c
+++ b/lib/arithmetic.c
@@ -139,17 +139,15 @@ arithmetic_not(gal_data_t *data, unsigned char flags)
 
 
 
-#define ARITHMETIC_ABS_SGN(CTYPE, U0_S1) {                        \
-    CTYPE *o=out->array, *a=in->array, *af=a+in->size;            \
-    if(U0_S1)          do *o++ = abs(*a); while(++a<af);          \
-    else if(out!=in) { do *o++ = *a; while(++a<af); }             \
-  }
-
 
 /* We don't want to use the standard function for unary functions in the
    case of the absolute operator. This is because there are multiple
    versions of this function in the C library for different types, which
    can greatly improve speed. */
+#define ARITHMETIC_ABS_SGN(CTYPE, FUNC) {                          \
+    CTYPE *o=out->array, *a=in->array, *af=a+in->size;             \
+    do *o++ = FUNC(*a); while(++a<af);                             \
+  }
 static gal_data_t *
 arithmetic_abs(unsigned char flags, gal_data_t *in)
 {
@@ -163,21 +161,28 @@ arithmetic_abs(unsigned char flags, gal_data_t *in)
                          in->wcs, 0, in->minmapsize, in->name, in->unit,
                          in->comment);
 
-  /* Put the absolute value depending on the type. Note that the unsigned
-     types are already positive, so if the input is not to be freed (the
-     output must be a separate array), just copy the values.*/
+  /* Put the absolute value depending on the type. */
   switch(in->type)
     {
-    case GAL_TYPE_UINT8:   ARITHMETIC_ABS_SGN(uint8_t, 0);   break;
-    case GAL_TYPE_INT8:    ARITHMETIC_ABS_SGN(int8_t, 1);    break;
-    case GAL_TYPE_UINT16:  ARITHMETIC_ABS_SGN(uint16_t, 0);  break;
-    case GAL_TYPE_INT16:   ARITHMETIC_ABS_SGN(int16_t, 1);   break;
-    case GAL_TYPE_UINT32:  ARITHMETIC_ABS_SGN(uint32_t, 0);  break;
-    case GAL_TYPE_INT32:   ARITHMETIC_ABS_SGN(int32_t, 1);   break;
-    case GAL_TYPE_UINT64:  ARITHMETIC_ABS_SGN(uint64_t, 0);  break;
-    case GAL_TYPE_INT64:   ARITHMETIC_ABS_SGN(int64_t, 1);   break;
-    case GAL_TYPE_FLOAT32: ARITHMETIC_ABS_SGN(float, 1);     break;
-    case GAL_TYPE_FLOAT64: ARITHMETIC_ABS_SGN(double, 1);    break;
+    /* Unsigned types are already positive, so if the input is not to be
+       freed (the output must be a separate array), just copy the whole
+       array. */
+    case GAL_TYPE_UINT8:
+    case GAL_TYPE_UINT16:
+    case GAL_TYPE_UINT32:
+    case GAL_TYPE_UINT64:
+      if(out!=in) gal_data_copy_to_allocated(in, out);
+      break;
+
+    /* For the signed types, we actually have to go over the data and
+       calculate the absolute value. There are unique functions for
+       different types, so we will be using them.*/
+    case GAL_TYPE_INT8:    ARITHMETIC_ABS_SGN( int8_t,  abs   );  break;
+    case GAL_TYPE_INT16:   ARITHMETIC_ABS_SGN( int16_t, abs   );  break;
+    case GAL_TYPE_INT32:   ARITHMETIC_ABS_SGN( int32_t, labs  );  break;
+    case GAL_TYPE_INT64:   ARITHMETIC_ABS_SGN( int64_t, llabs );  break;
+    case GAL_TYPE_FLOAT32: ARITHMETIC_ABS_SGN( float,   fabsf );  break;
+    case GAL_TYPE_FLOAT64: ARITHMETIC_ABS_SGN( double,  fabs  );  break;
     default:
       error(EXIT_FAILURE, 0, "type code %d not recognized in "
             "`arithmetic_abs'", in->type);
@@ -1356,7 +1361,7 @@ static gal_data_t *
 arithmetic_from_statistics(int operator, unsigned char flags,
                            gal_data_t *input)
 {
-  gal_data_t *out;
+  gal_data_t *out=NULL;
   int ip=(flags & GAL_ARITHMETIC_INPLACE) || (flags & GAL_ARITHMETIC_FREE);
 
   switch(operator)
diff --git a/lib/binary.c b/lib/binary.c
index 51c0b21..571c411 100644
--- a/lib/binary.c
+++ b/lib/binary.c
@@ -357,7 +357,7 @@ gal_binary_connected_components(gal_data_t *binary, 
gal_data_t **out,
   uint8_t *b, *bf;
   gal_data_t *lab;
   size_t p, i, curlab=1;
-  struct gal_linkedlist_sll *Q=NULL;
+  gal_list_sizet_t *Q=NULL;
   size_t *dinc=gal_dimension_increment(binary->ndim, binary->dsize);
 
   /* Two small sanity checks. */
@@ -419,14 +419,14 @@ gal_binary_connected_components(gal_data_t *binary, 
gal_data_t **out,
         l[i]=curlab;
 
         /* Add this pixel to the queue of pixels to work with. */
-        gal_linkedlist_add_to_sll(&Q, i);
+        gal_list_sizet_add(&Q, i);
 
         /* While a pixel remains in the queue, continue labelling and
            searching for neighbors. */
         while(Q!=NULL)
           {
             /* Pop an element from the queue. */
-            gal_linkedlist_pop_from_sll(&Q, &p);
+            p=gal_list_sizet_pop(&Q);
 
             /* Go over all its neighbors and add them to the list if they
                haven't already been labeled. */
@@ -436,7 +436,7 @@ gal_binary_connected_components(gal_data_t *binary, 
gal_data_t **out,
                 if( b[ nind ] && l[ nind ]==0 )
                   {
                     l[ nind ] = curlab;
-                    gal_linkedlist_add_to_sll(&Q, nind);
+                    gal_list_sizet_add(&Q, nind);
                   }
               } );
           }
@@ -480,9 +480,9 @@ gal_binary_connected_adjacency_matrix(gal_data_t *adjacency,
                                       size_t *numconnected)
 {
   gal_data_t *newlabs_d;
+  gal_list_sizet_t *Q=NULL;
   int32_t *newlabs, curlab=1;
   uint8_t *adj=adjacency->array;
-  struct gal_linkedlist_sll *Q=NULL;
   size_t i, j, p, num=adjacency->dsize[0];
 
   /* Some small sanity checks. */
@@ -515,13 +515,13 @@ gal_binary_connected_adjacency_matrix(gal_data_t 
*adjacency,
     if(newlabs[i]==0)
       {
         /* Add this old label to the list that must be corrected. */
-        gal_linkedlist_add_to_sll(&Q, i);
+        gal_list_sizet_add(&Q, i);
 
         /* Continue while the list has elements. */
         while(Q!=NULL)
           {
             /* Pop the top old-label from the list. */
-            gal_linkedlist_pop_from_sll(&Q, &p);
+            p=gal_list_sizet_pop(&Q);
 
             /* If it has already been labeled then ignore it. */
             if( newlabs[p]!=curlab )
@@ -534,7 +534,7 @@ gal_binary_connected_adjacency_matrix(gal_data_t *adjacency,
                    that are touching it. */
                 for(j=1;j<num;++j)
                   if( adj[ p*num+j ] && newlabs[j]==0 )
-                    gal_linkedlist_add_to_sll(&Q, j);
+                    gal_list_sizet_add(&Q, j);
               }
           }
 
@@ -692,7 +692,13 @@ gal_binary_fill_holes(gal_data_t *input)
   in=input->array;
   tile->array=gal_tile_block_relative_to_other(tile, holelabs);
   tile->block=holelabs; /* has to be after correcting `tile->array'. */
-  GAL_TILE_PARSE_OPERATE({
+
+
+  /* The type of the tile is already known (it is `int32_t') and we have no
+     output, so we'll just put `int' as a place-holder. In this way we can
+     avoid the switch statement of GAL_TILE_PARSE_OPERATE, and directly
+     use the workhorse macro `GAL_TILE_PO_OISET'. */
+  GAL_TILE_PO_OISET(int32_t, int, {
       *in = *i>1 && *i!=GAL_BLANK_INT32 ? 1 : *in;
       ++in;
     }, tile, NULL, 0, 0);
diff --git a/lib/blank.c b/lib/blank.c
index 617ae8f..4e01f9d 100644
--- a/lib/blank.c
+++ b/lib/blank.c
@@ -27,6 +27,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <inttypes.h>
 
 #include <gnuastro/data.h>
 #include <gnuastro/tile.h>
@@ -367,11 +368,15 @@ gal_blank_remove(gal_data_t *input)
 
 
 
-/* Print the blank value as a string. */
+/* Print the blank value as a string. For the integer types, we'll use the
+   PRIxNN keywords of `inttypes.h' (which is imported into Gnuastro from
+   Gnulib, so we don't necessarily rely on the host system having it). */
 char *
 gal_blank_as_string(uint8_t type, int width)
 {
-  char *blank;
+  char *blank=NULL, *fmt;
+
+  /* Print the given value. */
   switch(type)
     {
     case GAL_TYPE_BIT:
@@ -385,43 +390,51 @@ gal_blank_as_string(uint8_t type, int width)
       break;
 
     case GAL_TYPE_UINT8:
-      if(width) asprintf(&blank, "%*u", width,  (uint8_t)GAL_BLANK_UINT8);
-      else      asprintf(&blank, "%u",          (uint8_t)GAL_BLANK_UINT8);
+      fmt = width ? "%*"PRIu8 : "%*"PRIu8;
+      if(width) asprintf(&blank, fmt, width, (uint8_t)GAL_BLANK_UINT8);
+      else      asprintf(&blank, fmt,        (uint8_t)GAL_BLANK_UINT8);
       break;
 
     case GAL_TYPE_INT8:
-      if(width) asprintf(&blank, "%*d", width,  (int8_t)GAL_BLANK_INT8);
-      else      asprintf(&blank, "%d",          (int8_t)GAL_BLANK_INT8);
+      fmt = width ? "%*"PRId8 : "%*"PRId8;
+      if(width) asprintf(&blank, fmt, width, (int8_t)GAL_BLANK_INT8);
+      else      asprintf(&blank, fmt,        (int8_t)GAL_BLANK_INT8);
       break;
 
     case GAL_TYPE_UINT16:
-      if(width) asprintf(&blank, "%*u", width,  (uint16_t)GAL_BLANK_UINT16);
-      else      asprintf(&blank, "%u",          (uint16_t)GAL_BLANK_UINT16);
+      fmt = width ? "%*"PRIu16 : "%*"PRIu16;
+      if(width) asprintf(&blank, fmt, width, (uint16_t)GAL_BLANK_UINT16);
+      else      asprintf(&blank, fmt,        (uint16_t)GAL_BLANK_UINT16);
       break;
 
     case GAL_TYPE_INT16:
-      if(width) asprintf(&blank, "%*d", width,  (int16_t)GAL_BLANK_INT16);
-      else      asprintf(&blank, "%d",          (int16_t)GAL_BLANK_INT16);
+      fmt = width ? "%*"PRId16 : "%*"PRId16;
+      if(width) asprintf(&blank, fmt, width, (int16_t)GAL_BLANK_INT16);
+      else      asprintf(&blank, fmt,        (int16_t)GAL_BLANK_INT16);
       break;
 
     case GAL_TYPE_UINT32:
-      if(width) asprintf(&blank, "%*u", width,  (uint32_t)GAL_BLANK_UINT32);
-      else      asprintf(&blank, "%u",          (uint32_t)GAL_BLANK_UINT32);
+      fmt = width ? "%*"PRIu32 : "%*"PRIu32;
+      if(width) asprintf(&blank, fmt, width, (uint32_t)GAL_BLANK_UINT32);
+      else      asprintf(&blank, fmt,        (uint32_t)GAL_BLANK_UINT32);
       break;
 
     case GAL_TYPE_INT32:
-      if(width) asprintf(&blank, "%*d", width,  (int32_t)GAL_BLANK_INT32);
-      else      asprintf(&blank, "%d",          (int32_t)GAL_BLANK_INT32);
+      fmt = width ? "%*"PRId32 : "%*"PRId32;
+      if(width) asprintf(&blank, fmt, width, (int32_t)GAL_BLANK_INT32);
+      else      asprintf(&blank, fmt,        (int32_t)GAL_BLANK_INT32);
       break;
 
     case GAL_TYPE_UINT64:
-      if(width) asprintf(&blank, "%*lu", width, (uint64_t)GAL_BLANK_UINT64);
-      else      asprintf(&blank, "%lu",         (uint64_t)GAL_BLANK_UINT64);
+      fmt = width ? "%*"PRIu64 : "%*"PRIu64;
+      if(width) asprintf(&blank, fmt, width, (uint64_t)GAL_BLANK_UINT64);
+      else      asprintf(&blank, fmt,        (uint64_t)GAL_BLANK_UINT64);
       break;
 
     case GAL_TYPE_INT64:
-      if(width) asprintf(&blank, "%*ld", width, (int64_t)GAL_BLANK_INT64);
-      else      asprintf(&blank, "%ld",         (int64_t)GAL_BLANK_INT64);
+      fmt = width ? "%*"PRId64 : "%*"PRId64;
+      if(width) asprintf(&blank, fmt, width, (int64_t)GAL_BLANK_INT64);
+      else      asprintf(&blank, fmt,        (int64_t)GAL_BLANK_INT64);
       break;
 
     case GAL_TYPE_FLOAT32:
diff --git a/lib/convolve.c b/lib/convolve.c
index 92e9cfe..786ba1d 100644
--- a/lib/convolve.c
+++ b/lib/convolve.c
@@ -28,6 +28,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <string.h>
 #include <stdlib.h>
 
+#include <gnuastro/list.h>
 #include <gnuastro/tile.h>
 #include <gnuastro/threads.h>
 #include <gnuastro/convolve.h>
@@ -566,7 +567,7 @@ gal_convolve_spatial_general(gal_data_t *tiles, gal_data_t 
*kernel,
 
   /* Do the spatial convolution on threads. */
   gal_threads_spin_off(convolve_spatial_on_thread, &params,
-                       gal_data_num_in_ll(tiles), numthreads);
+                       gal_list_data_number(tiles), numthreads);
 
 
   /* Clean up and return the output array. */
diff --git a/lib/data.c b/lib/data.c
index 7795152..d279a68 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -31,6 +31,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <stdlib.h>
 #include <string.h>
 #include <dirent.h>
+#include <inttypes.h>
 #include <sys/mman.h>
 
 #include <gnuastro/wcs.h>
@@ -534,176 +535,6 @@ gal_data_array_free(gal_data_t *dataarr, size_t size, int 
free_array)
 
 
 
-/*********************************************************************/
-/*************    Data structure as a linked list   ******************/
-/*********************************************************************/
-/* Add a new data structure to the top of an existing linked list of data
-   structures. Note that if the new node is its self a list, all its nodes
-   will be added to the list. */
-void
-gal_data_add_existing_to_ll(gal_data_t **list, gal_data_t *newnode)
-{
-  gal_data_t *tmp=newnode, *toadd;
-
-  /* Check if newnode is itself a list or not. */
-  if(newnode->next)
-    {
-      /* Go onto the last node in newnode's existing list. */
-      while(tmp->next) tmp=tmp->next;
-
-      /* Set the last node as the node to add to the list. */
-      toadd=tmp;
-    }
-  else
-    /* Its not a list, so just set it to `toadd'. */
-    toadd=newnode;
-
-
-  /* Set the next element of toadd and update what list points to.*/
-  toadd->next=*list;
-  *list=toadd;
-}
-
-
-
-
-
-void
-gal_data_add_to_ll(gal_data_t **list, void *array, uint8_t type, size_t ndim,
-                   size_t *dsize, struct wcsprm *wcs, int clear,
-                   size_t minmapsize, char *name, char *unit, char *comment)
-{
-  gal_data_t *newnode;
-
-  /* Put all the input information into a new data structure node. */
-  newnode=gal_data_alloc(array, type, ndim, dsize, wcs, clear,
-                         minmapsize, name, unit, comment);
-
-  /* Add the new node to the list. */
-  gal_data_add_existing_to_ll(list, newnode);
-}
-
-
-
-
-
-gal_data_t *
-gal_data_pop_from_ll(gal_data_t **list)
-{
-  struct gal_data_t *out;
-
-  /* Keep the top pointer. */
-  out=*list;
-
-  /* Move the list pointer to the next node. */
-  *list=out->next;
-
-  /* Set the next poitner of the out pointer to NULL so it isn't
-     interpretted as a list any more. */
-  out->next=NULL;
-  return out;
-}
-
-
-
-
-
-void
-gal_data_reverse_ll(gal_data_t **list)
-{
-  gal_data_t *popped, *in=*list, *reversed=NULL;
-
-  /* Only do the job if the list is not NULL and has more than one node. */
-  if( in && in->next )
-    {
-      while(in!=NULL)
-        {
-          popped=gal_data_pop_from_ll(&in);
-          gal_data_add_existing_to_ll(&reversed, popped);
-        }
-      *list=reversed;
-    }
-}
-
-
-
-
-
-size_t
-gal_data_num_in_ll(gal_data_t *list)
-{
-  size_t num=0;
-  while(list!=NULL)
-    {
-      ++num;
-      list=list->next;
-    }
-  return num;
-}
-
-
-
-
-
-gal_data_t **
-gal_data_ll_to_array_of_ptrs(gal_data_t *list, size_t *num)
-{
-  size_t i=0;
-  gal_data_t **out;
-
-  /* Find the number of nodes in the list. */
-  *num=gal_data_num_in_ll(list);
-
-  /* Allocate space for the array. */
-  errno=0;
-  out=malloc(*num * sizeof *out);
-  if(out==NULL)
-    error(EXIT_FAILURE, 0, "%zu bytes for the output pointer in "
-          "`gal_data_ll_to_array_of_ptrs'", *num * sizeof *out);
-
-  /* Fill in the array with pointers to each data-structure. Note that we
-     don't need the list pointer any more, so we can just increment it.*/
-  while(list!=NULL) { out[i++]=list; list=list->next; }
-
-  /* Return the allocated array. */
-  return out;
-}
-
-
-
-
-
-void
-gal_data_free_ll(gal_data_t *list)
-{
-  struct gal_data_t *tmp;
-  while(list!=NULL)
-    {
-      tmp=list->next;
-      gal_data_free(list);
-      list=tmp;
-    }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 /*************************************************************
  **************            Copying             ***************
  *************************************************************/
@@ -854,34 +685,34 @@ data_copy_to_string(gal_data_t *from, gal_data_t *to)
   switch(from->type)
     {
     case GAL_TYPE_UINT8:
-      COPY_TO_STR_INT(uint8_t,  GAL_BLANK_UINT8, "%u");    break;
+      COPY_TO_STR_INT(uint8_t,  GAL_BLANK_UINT8,  "%"PRIu8);  break;
 
     case GAL_TYPE_INT8:
-      COPY_TO_STR_INT(int8_t,   GAL_BLANK_INT8, "%d");     break;
+      COPY_TO_STR_INT(int8_t,   GAL_BLANK_INT8,   "%"PRId8);  break;
 
     case GAL_TYPE_UINT16:
-      COPY_TO_STR_INT(uint16_t, GAL_BLANK_UINT16, "%u");   break;
+      COPY_TO_STR_INT(uint16_t, GAL_BLANK_UINT16, "%"PRIu16); break;
 
     case GAL_TYPE_INT16:
-      COPY_TO_STR_INT(int16_t,  GAL_BLANK_INT16, "%d");    break;
+      COPY_TO_STR_INT(int16_t,  GAL_BLANK_INT16,  "%"PRId16); break;
 
     case GAL_TYPE_UINT32:
-      COPY_TO_STR_INT(uint32_t, GAL_BLANK_UINT32, "%u");   break;
+      COPY_TO_STR_INT(uint32_t, GAL_BLANK_UINT32, "%"PRIu32); break;
 
     case GAL_TYPE_INT32:
-      COPY_TO_STR_INT(int32_t,  GAL_BLANK_INT32, "%d");    break;
+      COPY_TO_STR_INT(int32_t,  GAL_BLANK_INT32,  "%"PRId32); break;
 
     case GAL_TYPE_UINT64:
-      COPY_TO_STR_INT(uint64_t, GAL_BLANK_UINT64, "%lu");  break;
+      COPY_TO_STR_INT(uint64_t, GAL_BLANK_UINT64, "%"PRIu64); break;
 
     case GAL_TYPE_INT64:
-      COPY_TO_STR_INT(int64_t,  GAL_BLANK_INT64, "%ld");   break;
+      COPY_TO_STR_INT(int64_t,  GAL_BLANK_INT64,  "%"PRId64); break;
 
     case GAL_TYPE_FLOAT32:
-      COPY_TO_STR_FLT(float, GAL_BLANK_FLOAT32);           break;
+      COPY_TO_STR_FLT(float, GAL_BLANK_FLOAT32);              break;
 
     case GAL_TYPE_FLOAT64:
-      COPY_TO_STR_FLT(double, GAL_BLANK_FLOAT32);          break;
+      COPY_TO_STR_FLT(double, GAL_BLANK_FLOAT32);             break;
 
     case GAL_TYPE_STRING:
       for(i=0;i<from->size;++i)
@@ -1191,7 +1022,7 @@ gal_data_copy_element_same_type(gal_data_t *input, size_t 
index, void *ptr)
 char *
 gal_data_write_to_string(void *ptr, uint8_t type, int quote_if_str_has_space)
 {
-  char *c, *str;
+  char *c, *str=NULL;
   switch(type)
     {
     /* For a string we might need to make sure it has no white space
@@ -1208,16 +1039,16 @@ gal_data_write_to_string(void *ptr, uint8_t type, int 
quote_if_str_has_space)
         asprintf(&str, "%s", *(char **)ptr);
       break;
 
-    case GAL_TYPE_UINT8:   WRITE_TO_STRING( uint8_t,   "%u");  break;
-    case GAL_TYPE_INT8:    WRITE_TO_STRING( int8_t,    "%d");  break;
-    case GAL_TYPE_UINT16:  WRITE_TO_STRING( uint16_t,  "%u");  break;
-    case GAL_TYPE_INT16:   WRITE_TO_STRING( int16_t,   "%d");  break;
-    case GAL_TYPE_UINT32:  WRITE_TO_STRING( uint32_t,  "%u");  break;
-    case GAL_TYPE_INT32:   WRITE_TO_STRING( int32_t,   "%d");  break;
-    case GAL_TYPE_UINT64:  WRITE_TO_STRING( uint64_t, "%lu");  break;
-    case GAL_TYPE_INT64:   WRITE_TO_STRING( int64_t,  "%ld");  break;
-    case GAL_TYPE_FLOAT32: WRITE_TO_STRING( float,   "%.6g");  break;
-    case GAL_TYPE_FLOAT64: WRITE_TO_STRING( double, "%.10g");  break;
+    case GAL_TYPE_UINT8:   WRITE_TO_STRING( uint8_t,  "%"PRIu8  );  break;
+    case GAL_TYPE_INT8:    WRITE_TO_STRING( int8_t,   "%"PRId8  );  break;
+    case GAL_TYPE_UINT16:  WRITE_TO_STRING( uint16_t, "%"PRIu16 );  break;
+    case GAL_TYPE_INT16:   WRITE_TO_STRING( int16_t,  "%"PRId16 );  break;
+    case GAL_TYPE_UINT32:  WRITE_TO_STRING( uint32_t, "%"PRIu32 );  break;
+    case GAL_TYPE_INT32:   WRITE_TO_STRING( int32_t,  "%"PRId32 );  break;
+    case GAL_TYPE_UINT64:  WRITE_TO_STRING( uint64_t, "%"PRIu64 );  break;
+    case GAL_TYPE_INT64:   WRITE_TO_STRING( int64_t,  "%"PRId64 );  break;
+    case GAL_TYPE_FLOAT32: WRITE_TO_STRING( float,    "%.6g"    );  break;
+    case GAL_TYPE_FLOAT64: WRITE_TO_STRING( double,   "%.10g"   );  break;
 
     default:
       error(EXIT_FAILURE, 0, "type code %d not recognized in "
@@ -1379,8 +1210,7 @@ gal_data_string_to_type(void **out, char *string, uint8_t 
type)
 
     /* Linked lists, currently only string linked lists. */
     case GAL_TYPE_STRLL:
-      gal_linkedlist_add_to_stll( (struct gal_linkedlist_stll **)out,
-                                  string, 1);
+      gal_list_str_add( (struct gal_list_str_t **)out, string, 1);
       break;
 
     /* String, just allocate and copy the string and keep its pointer in
diff --git a/lib/dimension.c b/lib/dimension.c
index 03684ea..0536440 100644
--- a/lib/dimension.c
+++ b/lib/dimension.c
@@ -240,6 +240,6 @@ size_t
 gal_dimension_dist_manhattan(size_t *a, size_t *b, size_t ndim)
 {
   size_t i, out=0;
-  for(i=0;i<ndim;++i) out += labs(a[i]-b[i]);
+  for(i=0;i<ndim;++i) out += (a[i] > b[i]) ? (a[i]-b[i]) : (b[i]-a[i]);
   return out;
 }
diff --git a/lib/fits.c b/lib/fits.c
index 31834a2..2f3bb3c 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -35,6 +35,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/git.h>
 #include <gnuastro/wcs.h>
+#include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/tile.h>
 #include <gnuastro/blank.h>
@@ -1293,10 +1294,10 @@ gal_fits_img_read(char *filename, char *hdu, size_t 
minmapsize)
      the linked list of keys to keep the `name' and `unit' pointers. We can
      free the linked list after `gal_data_alloc' has read/copied the
      values.*/
-  gal_data_add_to_ll(&keysll, NULL, GAL_TYPE_STRING, 1, &dsize_key,
-                     NULL, 0, -1, "EXTNAME", NULL, NULL);
-  gal_data_add_to_ll(&keysll, NULL, GAL_TYPE_STRING, 1, &dsize_key,
-                     NULL, 0, -1, "BUNIT", NULL, NULL);
+  gal_list_data_add_alloc(&keysll, NULL, GAL_TYPE_STRING, 1, &dsize_key,
+                          NULL, 0, -1, "EXTNAME", NULL, NULL);
+  gal_list_data_add_alloc(&keysll, NULL, GAL_TYPE_STRING, 1, &dsize_key,
+                          NULL, 0, -1, "BUNIT", NULL, NULL);
   gal_fits_key_read_from_ptr(fptr, keysll, 0, 0);
   if(keysll->status==0)       {str=keysll->array;       unit=*str; }
   if(keysll->next->status==0) {str=keysll->next->array; name=*str; }
@@ -1306,7 +1307,7 @@ gal_fits_img_read(char *filename, char *hdu, size_t 
minmapsize)
   img=gal_data_alloc(NULL, type, ndim, dsize, NULL, 0, minmapsize,
                      name, unit, NULL);
   blank=gal_blank_alloc_write(type);
-  gal_data_free_ll(keysll);
+  gal_list_data_free(keysll);
   free(dsize);
 
 
@@ -2039,7 +2040,7 @@ gal_fits_tab_info(char *filename, char *hdu, size_t 
*numcols,
    input indexs linked list. You can use */
 gal_data_t *
 gal_fits_tab_read(char *filename, char *hdu, size_t numrows,
-                  gal_data_t *allcols, struct gal_linkedlist_sll *indexll,
+                  gal_data_t *allcols, gal_list_sizet_t *indexll,
                   int minmapsize)
 {
   size_t i=0;
@@ -2049,7 +2050,7 @@ gal_fits_tab_read(char *filename, char *hdu, size_t 
numrows,
   fitsfile *fptr;
   gal_data_t *out=NULL;
   int status=0, anynul=0;
-  struct gal_linkedlist_sll *ind;
+  gal_list_sizet_t *ind;
 
   /* Open the FITS file */
   fptr=gal_fits_hdu_open_type(filename, hdu, 1);
@@ -2060,9 +2061,9 @@ gal_fits_tab_read(char *filename, char *hdu, size_t 
numrows,
       /* Allocate the necessary data structure (including the array) for
          this column. */
       dsize=numrows;
-      gal_data_add_to_ll(&out, NULL, allcols[ind->v].type, 1, &dsize,
-                         NULL, 0, minmapsize, allcols[ind->v].name,
-                         allcols[ind->v].unit, allcols[ind->v].comment);
+      gal_list_data_add_alloc(&out, NULL, allcols[ind->v].type, 1, &dsize,
+                              NULL, 0, minmapsize, allcols[ind->v].name,
+                              allcols[ind->v].unit, allcols[ind->v].comment);
 
       /* For a string column, we need an allocated array for each element,
          even in binary values. This value should be stored in the
@@ -2351,16 +2352,16 @@ fits_write_tnull_tcomm(fitsfile *fptr, gal_data_t *col, 
int tabletype,
 /* Write the given columns (a linked list of `gal_data_t') into a FITS
    table.*/
 void
-gal_fits_tab_write(gal_data_t *cols, struct gal_linkedlist_stll *comments,
+gal_fits_tab_write(gal_data_t *cols, gal_list_str_t *comments,
                    int tabletype, char *filename, int dontdelete)
 {
   void *blank;
   fitsfile *fptr;
   gal_data_t *col;
   size_t i, numrows=-1;
+  gal_list_str_t *strt;
   char **ttype, **tform, **tunit;
   int tbltype, numcols=0, status=0;
-  struct gal_linkedlist_stll *strt;
 
 
   /* Make sure all the input columns have the same number of elements */
diff --git a/lib/gnuastro-internal/options.h b/lib/gnuastro-internal/options.h
index b915c4f..fde3aa1 100644
--- a/lib/gnuastro-internal/options.h
+++ b/lib/gnuastro-internal/options.h
@@ -24,9 +24,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <argp.h>
 
-#include <gnuastro/data.h>
 #include <gnuastro/tile.h>
-
+#include <gnuastro/list.h>
 
 
 
@@ -200,9 +199,9 @@ struct gal_options_common_params
   char        *program_authors; /* List of the program authors.           */
   struct argp_option *coptions; /* Common options to all programs.        */
   struct argp_option *poptions; /* Program specific options.              */
-  struct gal_linkedlist_ill   *mand_common; /* Common mandatory options.  */
-  struct gal_linkedlist_stll  *novalue_doc; /* Mandatory opts, no value   */
-  struct gal_linkedlist_stll *novalue_name; /* Mandatory opts, no value   */
+  gal_list_i32_t  *mand_common; /* Common mandatory options.  */
+  gal_list_str_t  *novalue_doc; /* Mandatory opts, no value   */
+  gal_list_str_t *novalue_name; /* Mandatory opts, no value   */
 };
 
 
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index 205032a..dfe6c14 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -281,36 +281,6 @@ gal_data_array_free(gal_data_t *dataarr, size_t num, int 
free_array);
 
 
 
-/*********************************************************************/
-/*************    Data structure as a linked list   ******************/
-/*********************************************************************/
-void
-gal_data_add_existing_to_ll(gal_data_t **list, gal_data_t *newnode);
-
-void
-gal_data_add_to_ll(gal_data_t **list, void *array, uint8_t type, size_t ndim,
-                   size_t *dsize, struct wcsprm *wcs, int clear,
-                   size_t minmapsize, char *name, char *unit, char *comment);
-
-gal_data_t *
-gal_data_pop_from_ll(struct gal_data_t **list);
-
-void
-gal_data_reverse_ll(gal_data_t **list);
-
-size_t
-gal_data_num_in_ll(struct gal_data_t *list);
-
-gal_data_t **
-gal_data_ll_to_array_of_ptrs(gal_data_t *list, size_t *num);
-
-void
-gal_data_free_ll(gal_data_t *list);
-
-
-
-
-
 /*************************************************************
  **************            Copying             ***************
  *************************************************************/
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index 96a39e2..b044c47 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -257,11 +257,11 @@ gal_fits_tab_info(char *filename, char *hdu, size_t 
*numcols,
 
 gal_data_t *
 gal_fits_tab_read(char *filename, char *hdu, size_t numrows,
-                    gal_data_t *colinfo, struct gal_linkedlist_sll *indexll,
-                    int minmapsize);
+                  gal_data_t *colinfo, gal_list_sizet_t *indexll,
+                  int minmapsize);
 
 void
-gal_fits_tab_write(gal_data_t *cols, struct gal_linkedlist_stll *comments,
+gal_fits_tab_write(gal_data_t *cols, gal_list_str_t *comments,
                    int tabletype, char *filename, int dontdelete);
 
 
diff --git a/lib/gnuastro/linkedlist.h b/lib/gnuastro/linkedlist.h
deleted file mode 100644
index 6ffb636..0000000
--- a/lib/gnuastro/linkedlist.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/*********************************************************************
-Functions for linked lists.
-This is part of GNU Astronomy Utilities (Gnuastro) package.
-
-Original author:
-     Mohammad Akhlaghi <address@hidden>
-Contributing author(s):
-Copyright (C) 2015, Free Software Foundation, Inc.
-
-Gnuastro is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation, either version 3 of the License, or (at your
-option) any later version.
-
-Gnuastro is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
-**********************************************************************/
-#ifndef __GAL_SLL_H__
-#define __GAL_SLL_H__
-
-/* Include other headers if necessary here. Note that other header files
-   must be included before the C++ preparations below */
-
-
-
-/* C++ Preparations */
-#undef __BEGIN_C_DECLS
-#undef __END_C_DECLS
-#ifdef __cplusplus
-# define __BEGIN_C_DECLS extern "C" {
-# define __END_C_DECLS }
-#else
-# define __BEGIN_C_DECLS                /* empty */
-# define __END_C_DECLS                  /* empty */
-#endif
-/* End of C++ preparations */
-
-
-
-/* Actual header contants (the above were for the Pre-processor). */
-__BEGIN_C_DECLS  /* From C++ preparations */
-
-
-
-/******************* float: */
-struct gal_linkedlist_fll
-{
-    float v;
-    struct gal_linkedlist_fll *next;
-};
-
-void
-gal_linkedlist_print_fll_array(struct gal_linkedlist_fll **afll,
-                               size_t num);
-
-void
-gal_linkedlist_add_to_fll(struct gal_linkedlist_fll **list,
-                          float value);
-
-void
-gal_linkedlist_pop_from_fll(struct gal_linkedlist_fll **list,
-                            float *value);
-
-size_t
-gal_linkedlist_num_in_fll(struct gal_linkedlist_fll *list);
-
-void
-gal_linkedlist_fll_to_array(struct gal_linkedlist_fll *list,
-                            float **f, size_t *num);
-
-void
-gal_linkedlist_free_fll(struct gal_linkedlist_fll *list);
-
-void
-gal_linkedlist_free_fll_array(struct gal_linkedlist_fll **afll,
-                              size_t num);
-
-
-
-
-
-/******************* double: */
-struct gal_linkedlist_dll
-{
-    double v;
-    struct gal_linkedlist_dll *next;
-};
-void
-gal_linkedlist_add_to_dll(struct gal_linkedlist_dll **list, double value);
-
-void
-gal_linkedlist_pop_from_dll(struct gal_linkedlist_dll **list, double *value);
-
-size_t
-gal_linkedlist_num_in_dll(struct gal_linkedlist_dll *list);
-
-void
-gal_linkedlist_dll_to_array(struct gal_linkedlist_dll *list,
-                            double **d, size_t *num);
-
-void
-gal_linkedlist_reverse_dll(struct gal_linkedlist_dll **list);
-
-void
-gal_linkedlist_free_dll(struct gal_linkedlist_dll *list);
-
-
-
-
-
-/******************* Two doubles (for coordinates) */
-struct gal_linkedlist_tdll
-{
-    double a;
-    double b;
-    struct gal_linkedlist_tdll *next;
-};
-
-void
-gal_linkedlist_add_to_tdll(struct gal_linkedlist_tdll **list,
-                           double a, double b);
-
-void
-gal_linkedlist_pop_from_tdll(struct gal_linkedlist_tdll **list,
-                             double *a, double *b);
-
-size_t
-gal_linkedlist_num_int_dll(struct gal_linkedlist_tdll *list);
-
-void
-gal_linkedlist_tdll_to_array_inv(struct gal_linkedlist_tdll *list,
-                                 double **d, size_t *num);
-
-void
-gal_linkedlist_free_tdll(struct gal_linkedlist_tdll *list);
-
-
-
-
-
-/******************* String: */
-struct gal_linkedlist_stll
-{
-    char *v;
-    struct gal_linkedlist_stll *next;
-};
-
-void
-gal_linkedlist_add_to_stll(struct gal_linkedlist_stll **list,
-                           char *value, int allocate);
-
-void
-gal_linked_list_copy_stll(struct gal_linkedlist_stll *from,
-                          struct gal_linkedlist_stll **to);
-
-void
-gal_linkedlist_pop_from_stll(struct gal_linkedlist_stll **list,
-                             char **value);
-
-void
-gal_linkedlist_reverse_stll(struct gal_linkedlist_stll **list);
-
-void
-gal_linkedlist_print_stll(struct gal_linkedlist_stll *list);
-
-size_t
-gal_linkedlist_num_in_stll(struct gal_linkedlist_stll *list);
-
-void
-gal_linkedlist_free_stll(struct gal_linkedlist_stll *list, int freevalue);
-
-
-
-/******************* size_t: */
-struct gal_linkedlist_sll
-{
-    size_t v;
-    struct gal_linkedlist_sll *next;
-};
-
-void
-gal_linkedlist_add_to_sll(struct gal_linkedlist_sll **list,
-                          size_t value);
-
-void
-gal_linkedlist_pop_from_sll(struct gal_linkedlist_sll **list,
-                            size_t *value);
-
-void
-gal_linkedlist_reverse_sll(struct gal_linkedlist_sll **list);
-
-size_t
-gal_linkedlist_num_in_sll(struct gal_linkedlist_sll *list);
-
-void
-gal_linkedlist_print_sll(struct gal_linkedlist_sll *list);
-
-void
-gal_linkedlist_sll_to_array(struct gal_linkedlist_sll *list,
-                            size_t **s, size_t *num, int inverse);
-
-void
-gal_linkedlist_free_sll(struct gal_linkedlist_sll *list);
-
-
-
-
-/******************* int: */
-struct gal_linkedlist_ill
-{
-    int v;
-    struct gal_linkedlist_ill *next;
-};
-
-void
-gal_linkedlist_add_to_ill(struct gal_linkedlist_ill **list, int value);
-
-void
-gal_linkedlist_pop_from_ill(struct gal_linkedlist_ill **list, int *value);
-
-void
-gal_linkedlist_reverse_ill(struct gal_linkedlist_ill **list);
-
-size_t
-gal_linkedlist_num_in_ill(struct gal_linkedlist_ill *list);
-
-void
-gal_linkedlist_print_ill(struct gal_linkedlist_ill *list);
-
-void
-gal_linkedlist_free_ill(struct gal_linkedlist_ill *list);
-
-
-
-
-/******************* void * */
-struct gal_linkedlist_vll
-{
-    void* v;
-    struct gal_linkedlist_vll *next;
-};
-
-void
-gal_linkedlist_add_to_vll(struct gal_linkedlist_vll **list, void *value);
-
-void
-gal_linkedlist_pop_from_vll(struct gal_linkedlist_vll **list, void **value);
-
-void
-gal_linkedlist_reverse_vll(struct gal_linkedlist_vll **list);
-
-void
-gal_linkedlist_free_vll(struct gal_linkedlist_vll *list, int freevalue);
-
-
-
-
-
-/******************* Ordered size_t: */
-struct gal_linkedlist_osll
-{
-  size_t v;                       /* The actual value. */
-  float s;                        /* The parameter to sort by. */
-  struct gal_linkedlist_osll *next;
-};
-
-void
-gal_linkedlist_add_to_osll(struct gal_linkedlist_osll **list,
-                           size_t value, float tosort);
-
-void
-gal_linkedlist_pop_from_osll(struct gal_linkedlist_osll **list,
-                             size_t *value, float *sortvalue);
-
-void
-gal_linkedlist_osll_into_sll(struct gal_linkedlist_osll *in,
-                             struct gal_linkedlist_sll **out);
-
-
-
-
-/******************* Two way ordered size_t: */
-struct gal_linkedlist_tosll
-{
-  size_t v;
-  float s;
-  struct gal_linkedlist_tosll *prev;
-  struct gal_linkedlist_tosll *next;
-};
-
-void
-gal_linkedlist_print_tosll(struct gal_linkedlist_tosll *largest,
-                           struct gal_linkedlist_tosll *smallest);
-
-void
-gal_linkedlist_add_to_tosll_end(struct gal_linkedlist_tosll **largest,
-                                struct gal_linkedlist_tosll **smallest,
-                                size_t value, float tosort);
-
-void
-gal_linkedlist_pop_from_tosll_start(struct gal_linkedlist_tosll **lartest,
-                                    struct gal_linkedlist_tosll **smallest,
-                                    size_t *value, float *tosort);
-
-void
-gal_linkedlist_smallest_tosll(struct gal_linkedlist_tosll *largest,
-                              struct gal_linkedlist_tosll **smallest);
-
-void
-gal_linkedlist_tosll_into_sll(struct gal_linkedlist_tosll *in,
-                              struct gal_linkedlist_sll **out);
-
-void
-gal_linkedlist_tosll_free(struct gal_linkedlist_tosll *largest);
-
-
-
-__END_C_DECLS    /* From C++ preparations */
-
-#endif           /* __GAL_LINKEDLIST_H__ */
diff --git a/lib/gnuastro/list.h b/lib/gnuastro/list.h
new file mode 100644
index 0000000..1c47cb2
--- /dev/null
+++ b/lib/gnuastro/list.h
@@ -0,0 +1,338 @@
+/*********************************************************************
+Functions for linked lists.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Mohammad Akhlaghi <address@hidden>
+Contributing author(s):
+Copyright (C) 2015, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#ifndef __GAL_LIST_H__
+#define __GAL_LIST_H__
+
+/* Include other headers if necessary here. Note that other header files
+   must be included before the C++ preparations below */
+#include <gnuastro/data.h>
+
+
+/* C++ Preparations */
+#undef __BEGIN_C_DECLS
+#undef __END_C_DECLS
+#ifdef __cplusplus
+# define __BEGIN_C_DECLS extern "C" {
+# define __END_C_DECLS }
+#else
+# define __BEGIN_C_DECLS                /* empty */
+# define __END_C_DECLS                  /* empty */
+#endif
+/* End of C++ preparations */
+
+
+
+/* Actual header contants (the above were for the Pre-processor). */
+__BEGIN_C_DECLS  /* From C++ preparations */
+
+
+
+
+
+/****************************************************************
+ *****************          String           ********************
+ ****************************************************************/
+typedef struct gal_list_str_t
+{
+  char *v;
+  struct gal_list_str_t *next;
+} gal_list_str_t;
+
+void
+gal_list_str_add(gal_list_str_t **list, char *value,
+                 int allocate);
+
+char *
+gal_list_str_pop(gal_list_str_t **list);
+
+size_t
+gal_list_str_number(gal_list_str_t *list);
+
+void
+gal_list_str_print(gal_list_str_t *list);
+
+void
+gal_list_str_reverse(gal_list_str_t **list);
+
+void
+gal_list_str_free(gal_list_str_t *list, int freevalue);
+
+
+
+
+
+/****************************************************************
+ *****************          int32            ********************
+ ****************************************************************/
+typedef struct gal_list_i32_t
+{
+  int32_t v;
+  struct gal_list_i32_t *next;
+} gal_list_i32_t;
+
+void
+gal_list_i32_add(gal_list_i32_t **list, int32_t value);
+
+int32_t
+gal_list_i32_pop(gal_list_i32_t **list);
+
+size_t
+gal_list_i32_number(gal_list_i32_t *list);
+
+void
+gal_list_i32_print(gal_list_i32_t *list);
+
+void
+gal_list_i32_reverse(gal_list_i32_t **list);
+
+int32_t *
+gal_list_i32_to_array(gal_list_i32_t *list, int inverse, size_t *num);
+
+void
+gal_list_i32_free(gal_list_i32_t *list);
+
+
+
+
+
+/****************************************************************
+ *****************           size_t          ********************
+ ****************************************************************/
+typedef struct gal_list_sizet_t
+{
+  size_t v;
+  struct gal_list_sizet_t *next;
+} gal_list_sizet_t;
+
+void
+gal_list_sizet_add(gal_list_sizet_t **list, size_t value);
+
+size_t
+gal_list_sizet_pop(gal_list_sizet_t **list);
+
+size_t
+gal_list_sizet_number(gal_list_sizet_t *list);
+
+void
+gal_list_sizet_print(gal_list_sizet_t *list);
+
+void
+gal_list_sizet_reverse(gal_list_sizet_t **list);
+
+size_t *
+gal_list_sizet_to_array(gal_list_sizet_t *list, int inverse, size_t *num);
+
+void
+gal_list_sizet_free(gal_list_sizet_t *list);
+
+
+
+
+
+/****************************************************************
+ *****************           float           ********************
+ ****************************************************************/
+typedef struct gal_list_f32_t
+{
+    float v;
+    struct gal_list_f32_t *next;
+} gal_list_f32_t;
+
+void
+gal_list_f32_add(gal_list_f32_t **list, float value);
+
+float
+gal_list_f32_pop(gal_list_f32_t **list);
+
+size_t
+gal_list_f32_number(gal_list_f32_t *list);
+
+void
+gal_list_f32_reverse(gal_list_f32_t **list);
+
+void
+gal_list_f32_print(gal_list_f32_t *list);
+
+float *
+gal_list_f32_to_array(gal_list_f32_t *list, int inverse, size_t *num);
+
+void
+gal_list_f32_free(gal_list_f32_t *list);
+
+
+
+
+
+/****************************************************************
+ *****************          double           ********************
+ ****************************************************************/
+typedef struct gal_list_f64_t
+{
+    double v;
+    struct gal_list_f64_t *next;
+} gal_list_f64_t;
+
+void
+gal_list_f64_add(gal_list_f64_t **list, double value);
+
+double
+gal_list_f64_pop(gal_list_f64_t **list);
+
+size_t
+gal_list_f64_number(gal_list_f64_t *list);
+
+void
+gal_list_f64_print(gal_list_f64_t *list);
+
+void
+gal_list_f64_reverse(gal_list_f64_t **list);
+
+double *
+gal_list_f64_to_array(gal_list_f64_t *list, int inverse, size_t *num);
+
+void
+gal_list_f64_free(gal_list_f64_t *list);
+
+
+
+
+
+/****************************************************************
+ *****************          void *           ********************
+ ****************************************************************/
+typedef struct gal_list_void_t
+{
+  void *v;
+  struct gal_list_void_t *next;
+} gal_list_void_t;
+
+void
+gal_list_void_add(gal_list_void_t **list, void *value);
+
+void *
+gal_list_void_pop(gal_list_void_t **list);
+
+size_t
+gal_list_void_number(gal_list_void_t *list);
+
+void
+gal_list_void_reverse(gal_list_void_t **list);
+
+void
+gal_list_void_free(gal_list_void_t *list, int freevalue);
+
+
+
+
+
+/****************************************************************
+ *****************       Ordered size_t      ********************
+ ****************************************************************/
+typedef struct gal_list_osizet_t
+{
+  size_t v;                       /* The actual value. */
+  float s;                        /* The parameter to sort by. */
+  struct gal_list_osizet_t *next;
+} gal_list_osizet_t;
+
+void
+gal_list_osizet_add(gal_list_osizet_t **list,
+                    size_t value, float tosort);
+
+void
+gal_list_osizet_pop(gal_list_osizet_t **list,
+                    size_t *value, float *sortvalue);
+
+void
+gal_list_osizet_to_sizet_free(gal_list_osizet_t *in,
+                              gal_list_sizet_t **out);
+
+
+
+
+
+/****************************************************************
+ ***********        Two way ordered size_t         **************
+ ****************************************************************/
+typedef struct gal_list_tosizet_t
+{
+  size_t v;                       /* The actual value. */
+  float s;                        /* The parameter to sort by. */
+  struct gal_list_tosizet_t *prev;
+  struct gal_list_tosizet_t *next;
+} gal_list_tosizet_t;
+
+void
+gal_list_tosizet_add(gal_list_tosizet_t **largest,
+                     gal_list_tosizet_t **smallest,
+                     size_t value, float tosort);
+
+void
+gal_list_tosizet_print(gal_list_tosizet_t *largest,
+                       gal_list_tosizet_t *smallest);
+
+void
+gal_list_tosizet_pop_smallest(gal_list_tosizet_t **lartest,
+                              gal_list_tosizet_t **smallest,
+                              size_t *value, float *tosort);
+
+void
+gal_list_tosizet_to_sizet(gal_list_tosizet_t *in,
+                          gal_list_sizet_t **out);
+
+void
+gal_list_tosizet_free(gal_list_tosizet_t *largest);
+
+
+
+
+
+/****************************************************************
+ *****************        gal_data_t         ********************
+ ****************************************************************/
+void
+gal_list_data_add(gal_data_t **list, gal_data_t *newnode);
+
+void
+gal_list_data_add_alloc(gal_data_t **list, void *array, uint8_t type,
+                        size_t ndim, size_t *dsize, struct wcsprm *wcs,
+                        int clear, size_t minmapsize, char *name,
+                        char *unit, char *comment);
+
+gal_data_t *
+gal_list_data_pop(gal_data_t **list);
+
+void
+gal_list_data_reverse(gal_data_t **list);
+
+size_t
+gal_list_data_number(gal_data_t *list);
+
+void
+gal_list_data_free(gal_data_t *list);
+
+
+
+__END_C_DECLS    /* From C++ preparations */
+
+#endif           /* __GAL_LIST_H__ */
diff --git a/lib/gnuastro/table.h b/lib/gnuastro/table.h
index 60041b5..3d3d6c9 100644
--- a/lib/gnuastro/table.h
+++ b/lib/gnuastro/table.h
@@ -27,7 +27,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
    must be included before the C++ preparations below */
 
 #include <gnuastro/fits.h> /* Includes `gnuastro/data.h' and `fitsio.h' */
-#include <gnuastro/linkedlist.h>
+#include <gnuastro/list.h>
 
 
 
@@ -179,7 +179,7 @@ gal_table_info(char *filename, char *hdu, size_t *numcols,
 /***************               Read a table               ***************/
 /************************************************************************/
 gal_data_t *
-gal_table_read(char *filename, char *hdu, struct gal_linkedlist_stll *cols,
+gal_table_read(char *filename, char *hdu, gal_list_str_t *cols,
                int searchin, int ignorecase, int minmapsize);
 
 
@@ -188,16 +188,16 @@ gal_table_read(char *filename, char *hdu, struct 
gal_linkedlist_stll *cols,
 /***************              Write a table               ***************/
 /************************************************************************/
 void
-gal_table_comments_add_intro(struct gal_linkedlist_stll **comments,
+gal_table_comments_add_intro(gal_list_str_t **comments,
                              char *program_string, time_t *rawtime);
 
 void
-gal_table_write(gal_data_t *cols, struct gal_linkedlist_stll *comments,
+gal_table_write(gal_data_t *cols, gal_list_str_t *comments,
                 int tableformat, char *filename, int dontdelete);
 
 void
 gal_table_write_log(gal_data_t *logll, char *program_string,
-                    time_t *rawtime, struct gal_linkedlist_stll *comments,
+                    time_t *rawtime, gal_list_str_t *comments,
                     char *filename, int dontdelete, int quiet);
 
 
diff --git a/lib/gnuastro/tile.h b/lib/gnuastro/tile.h
index 5cdf0e7..6f3ef80 100644
--- a/lib/gnuastro/tile.h
+++ b/lib/gnuastro/tile.h
@@ -173,10 +173,21 @@ gal_tile_full_free_contents(struct 
gal_tile_two_layer_params *tl);
 /***********************************************************************/
 /**************           Function-like macros        ******************/
 /***********************************************************************/
+
+/* Useful when the input and output types are already known. We want this
+   to be self-sufficient (and be possible to call it independent of
+   `GAL_TILE_PARSE_OPERATE'), so some variables (basic definitions) are
+   re-defined here are in `GAL_TILE_PARSE_OPERATE'.*/
 #define GAL_TILE_PO_OISET(IT, OT, OP, IN, OUT, PARSE_OUT, CHECK_BLANK) { \
-    gal_data_t *out_w=OUT; /* Since `OUT' may be NULL. */               \
-    OT *ost, *o = out_w ? out_w->array : NULL;                          \
+    int parse_out=(OUT && PARSE_OUT);                                   \
+    size_t increment=0, num_increment=1;                                \
+    gal_data_t *out_w=OUT; /* `OUT' may be NULL. */                     \
+    gal_data_t *iblock = gal_tile_block(IN);                            \
     IT b=0, *st=NULL, *i=IN->array, *f=i+IN->size;                      \
+    OT *ost=NULL, *o = out_w ? out_w->array : NULL;                     \
+    gal_data_t *oblock = OUT ? gal_tile_block(OUT) : NULL;              \
+    int hasblank = CHECK_BLANK ? gal_blank_present(IN, 0) : 0;          \
+    size_t s_e_ind[2]={0,iblock->size-1}; /* -1: this is INCLUSIVE */   \
                                                                         \
     /* Write the blank value for the input type into `b'). Note that */ \
     /* a tile doesn't necessarily have to have a type. */               \
@@ -375,11 +386,8 @@ gal_tile_full_free_contents(struct 
gal_tile_two_layer_params *tl);
 */
 #define GAL_TILE_PARSE_OPERATE(OP, IN, OUT, PARSE_OUT, CHECK_BLANK) {   \
     int parse_out=(OUT && PARSE_OUT);                                   \
-    size_t increment=0, num_increment=1;                                \
     gal_data_t *iblock = gal_tile_block(IN);                            \
     gal_data_t *oblock = OUT ? gal_tile_block(OUT) : NULL;              \
-    int hasblank = CHECK_BLANK ? gal_blank_present(IN, 0) : 0;          \
-    size_t s_e_ind[2]={0,iblock->size-1}; /* -1: this is INCLUSIVE */   \
                                                                         \
     /* A small sanity check. */                                         \
     if( parse_out && gal_data_dsize_is_different(iblock, oblock) )      \
diff --git a/lib/gnuastro/txt.h b/lib/gnuastro/txt.h
index 447e1b5..89b797d 100644
--- a/lib/gnuastro/txt.h
+++ b/lib/gnuastro/txt.h
@@ -26,8 +26,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 /* Include other headers if necessary here. Note that other header files
    must be included before the C++ preparations below */
 
-#include <gnuastro/data.h>
-#include <gnuastro/linkedlist.h>
+#include <gnuastro/list.h>
 
 
 
@@ -90,14 +89,14 @@ gal_txt_table_info(char *filename, size_t *numcols, size_t 
*numrows);
 
 gal_data_t *
 gal_txt_table_read(char *filename, size_t numrows, gal_data_t *colinfo,
-                   struct gal_linkedlist_sll *indexll, size_t minmapsize);
+                   gal_list_sizet_t *indexll, size_t minmapsize);
 
 gal_data_t *
 gal_txt_image_read(char *filename, size_t minmapsize);
 
 void
-gal_txt_write(gal_data_t *cols, struct gal_linkedlist_stll *comment,
-              char *filename, int dontdelete);
+gal_txt_write(gal_data_t *cols, gal_list_str_t *comment, char *filename,
+              int dontdelete);
 
 
 
diff --git a/lib/interpolate.c b/lib/interpolate.c
index 8043ea9..1565021 100644
--- a/lib/interpolate.c
+++ b/lib/interpolate.c
@@ -28,7 +28,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <stdlib.h>
 #include <string.h>
 
-#include <gnuastro/data.h>
+#include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/blank.h>
 #include <gnuastro/threads.h>
@@ -64,7 +64,7 @@ struct interpolate_params
   size_t                  numneighbors;
   uint8_t                *thread_flags;
   int                        onlyblank;
-  struct gal_linkedlist_vll  *ngb_vals;
+  gal_list_void_t            *ngb_vals;
   struct gal_tile_two_layer_params *tl;
 };
 
@@ -87,8 +87,8 @@ interpolate_close_neighbors_on_thread(void *in_prm)
   void *nv;
   float pdist;
   uint8_t *b, *bf, *bb;
-  struct gal_linkedlist_vll *tvll;
-  struct gal_linkedlist_tosll *lQ, *sQ;
+  gal_list_void_t *tvll;
+  gal_list_tosizet_t *lQ, *sQ;
   size_t ngb_counter, dist, pind, *dinc;
   size_t i, index, fullind, chstart=0, ndim=input->ndim;
   gal_data_t *median, *tin, *tout, *tnear, *nearest=NULL;
@@ -113,11 +113,11 @@ interpolate_close_neighbors_on_thread(void *in_prm)
     {
       nv=gal_data_ptr_increment(tvll->v, tprm->id*prm->numneighbors,
                                 input->type);
-      gal_data_add_to_ll(&nearest, nv, tin->type, 1, &prm->numneighbors,
-                         NULL, 0, -1, NULL, NULL, NULL);
+      gal_list_data_add_alloc(&nearest, nv, tin->type, 1, &prm->numneighbors,
+                              NULL, 0, -1, NULL, NULL, NULL);
       tin=tin->next;
     }
-  gal_data_reverse_ll(&nearest);
+  gal_list_data_reverse(&nearest);
 
 
   /* Go over all the points given to this thread. */
@@ -184,11 +184,11 @@ interpolate_close_neighbors_on_thread(void *in_prm)
          list structure. To start from the nearest and go out to the
          farthest. */
       lQ=sQ=NULL;
-      gal_linkedlist_add_to_tosll_end(&lQ, &sQ, index, 0.0f);
+      gal_list_tosizet_add(&lQ, &sQ, index, 0.0f);
       while(sQ)
         {
           /* Pop-out (p) an index from the queue: */
-          gal_linkedlist_pop_from_tosll_start(&lQ, &sQ, &pind, &pdist);
+          gal_list_tosizet_pop_smallest(&lQ, &sQ, &pind, &pdist);
 
           /* If this isn't a blank value then add its values to the list of
              neighbor values. Note that we didn't check whether the values
@@ -210,7 +210,7 @@ interpolate_close_neighbors_on_thread(void *in_prm)
                  list and break out. */
               if(++ngb_counter>=prm->numneighbors)
                 {
-                  if(lQ) gal_linkedlist_tosll_free(lQ);
+                  if(lQ) gal_list_tosizet_free(lQ);
                   break;
                 }
             }
@@ -232,7 +232,7 @@ interpolate_close_neighbors_on_thread(void *in_prm)
                  dist=gal_dimension_dist_manhattan(icoord, ncoord, ndim);
 
                  /* Add this neighbor to the list. */
-                 gal_linkedlist_add_to_tosll_end(&lQ, &sQ, nind, dist);
+                 gal_list_tosizet_add(&lQ, &sQ, nind, dist);
 
                  /* Flag this neighbor as checked. */
                  flag[nind] |= INTERPOLATE_FLAGS_CHECKED;
@@ -267,7 +267,7 @@ interpolate_close_neighbors_on_thread(void *in_prm)
 
   /* Clean up. */
   for(tnear=nearest; tnear!=NULL; tnear=tnear->next) tnear->array=NULL;
-  gal_data_free_ll(nearest);
+  gal_list_data_free(nearest);
   free(icoord);
   free(ncoord);
   free(dinc);
@@ -305,7 +305,7 @@ interpolate_copy_input(gal_data_t *input, int aslinkedlist)
         }
 
       /* Output is the reverse of the input, so reverse it. */
-      gal_data_reverse_ll(&tout);
+      gal_list_data_reverse(&tout);
     }
 
   /* Return the copied list. */
@@ -345,7 +345,7 @@ gal_interpolate_close_neighbors(gal_data_t *input,
   prm.input        = input;
   prm.onlyblank    = onlyblank;
   prm.numneighbors = numneighbors;
-  prm.num          = aslinkedlist ? gal_data_num_in_ll(input) : 1;
+  prm.num          = aslinkedlist ? gal_list_data_number(input) : 1;
 
 
   /* Flag the blank values. */
@@ -374,8 +374,8 @@ gal_interpolate_close_neighbors(gal_data_t *input,
   prm.out=gal_data_alloc(NULL, input->type, input->ndim, input->dsize,
                          input->wcs, 0, input->minmapsize, NULL,
                          input->unit, NULL);
-  gal_linkedlist_add_to_vll(&prm.ngb_vals,
-                            gal_data_malloc_array(input->type, ngbvnum));
+  gal_list_void_add(&prm.ngb_vals,
+                    gal_data_malloc_array(input->type, ngbvnum));
 
 
   /* If we are given a list of datasets, make the necessary
@@ -393,16 +393,16 @@ gal_interpolate_close_neighbors(gal_data_t *input,
                 "`gal_interpolate_close_neighbors'");
 
         /* Allocate the output array for this node. */
-        gal_data_add_to_ll(&prm.out, NULL, tin->type, tin->ndim, tin->dsize,
-                           tin->wcs, 0, tin->minmapsize, NULL, tin->unit,
-                           NULL);
+        gal_list_data_add_alloc(&prm.out, NULL, tin->type, tin->ndim,
+                                tin->dsize, tin->wcs, 0, tin->minmapsize,
+                                NULL, tin->unit, NULL);
 
         /* Allocate the space for the neighbor values of this input. */
-        gal_linkedlist_add_to_vll(&prm.ngb_vals,
-                                  gal_data_malloc_array(tin->type, ngbvnum));
+        gal_list_void_add(&prm.ngb_vals,
+                          gal_data_malloc_array(tin->type, ngbvnum));
       }
-  gal_data_reverse_ll(&prm.out);
-  gal_linkedlist_reverse_vll(&prm.ngb_vals);
+  gal_list_data_reverse(&prm.out);
+  gal_list_void_reverse(&prm.ngb_vals);
 
 
   /* Allocate space for all the flag values of all the threads here (memory
@@ -439,6 +439,6 @@ gal_interpolate_close_neighbors(gal_data_t *input,
   /* Clean up and return. */
   free(prm.thread_flags);
   gal_data_free(prm.blanks);
-  gal_linkedlist_free_vll(prm.ngb_vals, 1);
+  gal_list_void_free(prm.ngb_vals, 1);
   return prm.out;
 }
diff --git a/lib/linkedlist.c b/lib/linkedlist.c
deleted file mode 100644
index e67183b..0000000
--- a/lib/linkedlist.c
+++ /dev/null
@@ -1,1197 +0,0 @@
-/*********************************************************************
-Functions for linked lists.
-This is part of GNU Astronomy Utilities (Gnuastro) package.
-
-Original author:
-     Mohammad Akhlaghi <address@hidden>
-Contributing author(s):
-Copyright (C) 2015, Free Software Foundation, Inc.
-
-Gnuastro is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation, either version 3 of the License, or (at your
-option) any later version.
-
-Gnuastro is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
-**********************************************************************/
-#include <config.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <error.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include <gnuastro/linkedlist.h>
-
-#include <gnuastro-internal/checkset.h>
-
-
-
-
-
-
-
-/****************************************************************
- *****************            Float          ********************
- ****************************************************************/
-void
-gal_linkedlist_print_fll_array(struct gal_linkedlist_fll **afll, size_t num)
-{
-  size_t i;
-  struct gal_linkedlist_fll *tmp;
-  for(i=0;i<num;++i)
-    {
-      printf(" %zu:\n", i);
-      for(tmp=afll[i];tmp!=NULL;tmp=tmp->next)
-        printf("%f, ", tmp->v);
-      printf("\n");
-    }
-}
-
-
-
-
-
-void
-gal_linkedlist_add_to_fll(struct gal_linkedlist_fll **list, float value)
-{
-  struct gal_linkedlist_fll *newnode;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: New element in "
-          "gal_linkedlist_fll");
-
-  newnode->v=value;
-  newnode->next=*list;
-  *list=newnode;
-}
-
-
-
-
-
-void
-gal_linkedlist_pop_from_fll(struct gal_linkedlist_fll **list, float *value)
-{
-  struct gal_linkedlist_fll *tmp;
-  tmp=*list;
-  *value=tmp->v;
-  *list=tmp->next;
-  free(tmp);
-}
-
-
-
-
-
-size_t
-gal_linkedlist_num_in_fll(struct gal_linkedlist_fll *list)
-{
-  size_t num=0;
-  struct gal_linkedlist_fll *tmp;
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    ++num;
-  return num;
-}
-
-
-
-
-
-void
-gal_linkedlist_fll_to_array(struct gal_linkedlist_fll *list,
-                            float **f, size_t *num)
-{
-  float *tf;
-  size_t i=0;
-  struct gal_linkedlist_fll *tmp;
-
-  /* Find the number of elements: */
-  if(*num==0)
-    *num=gal_linkedlist_num_in_fll(list);
-
-  /* Allocate the space: */
-  errno=0;
-  *f=malloc(*num*sizeof(float));
-  if(*f==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: array of gal_linkedlist_fll "
-          "with %zu elements", *num);
-  tf=*f;
-
-  /* Fill in the array: */
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    tf[i++]=tmp->v;
-}
-
-
-
-
-
-void
-gal_linkedlist_free_fll(struct gal_linkedlist_fll *list)
-{
-  struct gal_linkedlist_fll *tmp, *ttmp;
-  tmp=list;
-  while(tmp!=NULL)
-    {
-      ttmp=tmp->next;
-      free(tmp);
-      tmp=ttmp;
-    }
-}
-
-
-
-
-
-void
-gal_linkedlist_free_fll_array(struct gal_linkedlist_fll **afll, size_t num)
-{
-  size_t i;
-  for(i=0;i<num;++i)
-    gal_linkedlist_free_fll(afll[i]);
-  free(afll);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- *****************          Double           ********************
- ****************************************************************/
-void
-gal_linkedlist_add_to_dll(struct gal_linkedlist_dll **list, double value)
-{
-  struct gal_linkedlist_dll *newnode;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: New element in "
-          "gal_linkedlist_dll");
-
-  newnode->v=value;
-  newnode->next=*list;
-  *list=newnode;
-}
-
-
-
-
-
-void
-gal_linkedlist_pop_from_dll(struct gal_linkedlist_dll **list, double *value)
-{
-  struct gal_linkedlist_dll *tmp;
-  tmp=*list;
-  *value=tmp->v;
-  *list=tmp->next;
-  free(tmp);
-}
-
-
-
-
-
-size_t
-gal_linkedlist_num_in_dll(struct gal_linkedlist_dll *list)
-{
-  size_t num=0;
-  struct gal_linkedlist_dll *tmp;
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    ++num;
-  return num;
-}
-
-
-
-
-
-void
-gal_linkedlist_dll_to_array(struct gal_linkedlist_dll *list,
-                            double **d, size_t *num)
-{
-  double *td;
-  size_t i=0;
-  struct gal_linkedlist_dll *tmp;
-
-  /* Find the number of elements: */
-  *num=gal_linkedlist_num_in_dll(list);
-
-  /* Allocate the space: */
-  errno=0;
-  td=*d=malloc(*num*sizeof(double));
-  if(*d==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: array of gal_linkedlist_dll "
-          "with %zu elements", *num);
-
-  /* Fill in the array: */
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    td[i++]=tmp->v;
-}
-
-
-
-
-
-void
-gal_linkedlist_reverse_dll(struct gal_linkedlist_dll **list)
-{
-  double thisvalue;
-  struct gal_linkedlist_dll *correctorder=NULL;
-
-  /* Only do the reversal if there is more than one element. */
-  if( *list && (*list)->next )
-    {
-      while(*list!=NULL)
-        {
-          gal_linkedlist_pop_from_dll(list, &thisvalue);
-          gal_linkedlist_add_to_dll(&correctorder, thisvalue);
-        }
-      *list=correctorder;
-    }
-}
-
-
-
-
-
-void
-gal_linkedlist_free_dll(struct gal_linkedlist_dll *list)
-{
-  struct gal_linkedlist_dll *tmp, *ttmp;
-  tmp=list;
-  while(tmp!=NULL)
-    {
-      ttmp=tmp->next;
-      free(tmp);
-      tmp=ttmp;
-    }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- *****************        Two doubles        ********************
- ****************************************************************/
-void
-gal_linkedlist_add_to_tdll(struct gal_linkedlist_tdll **list,
-                           double a, double b)
-{
-  struct gal_linkedlist_tdll *newnode;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: New element in "
-          "gal_linkedlist_tdll");
-
-  newnode->a=a;
-  newnode->b=b;
-  newnode->next=*list;
-  *list=newnode;
-}
-
-
-
-
-
-void
-gal_linkedlist_pop_from_tdll(struct gal_linkedlist_tdll **list,
-                             double *a, double *b)
-{
-  struct gal_linkedlist_tdll *tmp=*list;
-
-  *a=tmp->a;
-  *b=tmp->b;
-  *list=tmp->next;
-  free(tmp);
-}
-
-
-
-
-
-size_t
-gal_linkedlist_num_int_dll(struct gal_linkedlist_tdll *list)
-{
-  size_t num=0;
-  struct gal_linkedlist_tdll *tmp;
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    ++num;
-  return num;
-}
-
-
-
-
-
-void
-gal_linkedlist_tdll_to_array_inv(struct gal_linkedlist_tdll *list,
-                                 double **d, size_t *num)
-{
-  size_t i;
-  double *td;
-  struct gal_linkedlist_tdll *tmp;
-
-  /* Find the number of elements: */
-  if(*num==0)
-    *num=gal_linkedlist_num_int_dll(list);
-
-  /* Allocate the space (every element of the list has two
-     elements.) */
-  errno=0;
-  td=*d=malloc(2 * *num * sizeof(double));
-  if(*d==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: array of gal_linkedlist_tdll "
-          "with %zu elements", *num);
-
-  /* Fill in the array in reverse order */
-  i = 2 * *num - 2;
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    {
-      td[i]=tmp->a;
-      td[i+1]=tmp->b;
-      i-=2;
-    }
-}
-
-
-
-
-
-void
-gal_linkedlist_free_tdll(struct gal_linkedlist_tdll *list)
-{
-  struct gal_linkedlist_tdll *tmp, *ttmp;
-  tmp=list;
-  while(tmp!=NULL)
-    {
-      ttmp=tmp->next;
-      free(tmp);
-      tmp=ttmp;
-    }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- *****************           string          ********************
- ****************************************************************/
-void
-gal_linkedlist_add_to_stll(struct gal_linkedlist_stll **list,
-                           char *value, int allocate)
-{
-  struct gal_linkedlist_stll *newnode;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno,
-          "linkedlist: New element in gal_linkedlist_stll");
-
-  if(allocate)
-    gal_checkset_allocate_copy(value, &newnode->v);
-  else
-    newnode->v=value;
-
-  newnode->next=*list;
-  *list=newnode;
-}
-
-
-
-
-
-void
-gal_linked_list_copy_stll(struct gal_linkedlist_stll *from,
-                          struct gal_linkedlist_stll **to)
-{
-  struct gal_linkedlist_stll *tmp, *out=NULL;
-
-  for(tmp=from; tmp!=NULL; tmp=tmp->next)
-    gal_linkedlist_add_to_stll(&out, tmp->v, 1);
-
-  gal_linkedlist_reverse_stll(&out);
-  *to=out;
-}
-
-
-
-
-
-void
-gal_linkedlist_pop_from_stll(struct gal_linkedlist_stll **list, char **value)
-{
-  struct gal_linkedlist_stll *tmp;
-  tmp=*list;
-  *value=tmp->v;
-  *list=tmp->next;
-  free(tmp);
-}
-
-
-
-
-
-void
-gal_linkedlist_reverse_stll(struct gal_linkedlist_stll **list)
-{
-  char *thisstring;
-  struct gal_linkedlist_stll *correctorder=NULL;
-
-  /* Only do the reversal if there is more than one element. */
-  if( *list && (*list)->next )
-    {
-      while(*list!=NULL)
-        {
-          gal_linkedlist_pop_from_stll(list, &thisstring);
-          gal_linkedlist_add_to_stll(&correctorder, thisstring, 0);
-        }
-      *list=correctorder;
-    }
-}
-
-
-
-
-void
-gal_linkedlist_print_stll(struct gal_linkedlist_stll *list)
-{
-  struct gal_linkedlist_stll *tmp;
-  for(tmp=list; tmp!=NULL; tmp=tmp->next)
-    printf("%s\n", tmp->v);
-}
-
-
-
-
-
-size_t
-gal_linkedlist_num_in_stll(struct gal_linkedlist_stll *list)
-{
-  size_t num=0;
-  struct gal_linkedlist_stll *tmp;
-  for(tmp=list;tmp!=NULL;tmp=tmp->next) ++num;
-  return num;
-}
-
-
-
-
-
-void
-gal_linkedlist_free_stll(struct gal_linkedlist_stll *list, int freevalue)
-{
-  struct gal_linkedlist_stll *tmp;
-  while(list!=NULL)
-    {
-      tmp=list->next;
-      if(freevalue)
-        free(list->v);
-      free(list);
-      list=tmp;
-    }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- *****************           size_t          ********************
- ****************************************************************/
-void
-gal_linkedlist_add_to_sll(struct gal_linkedlist_sll **list, size_t value)
-{
-  struct gal_linkedlist_sll *newnode;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno,
-          "linkedlist: New element in gal_linkedlist_sll");
-
-  newnode->v=value;
-  newnode->next=*list;
-  *list=newnode;
-}
-
-
-
-
-
-void
-gal_linkedlist_pop_from_sll(struct gal_linkedlist_sll **list, size_t *value)
-{
-  struct gal_linkedlist_sll *tmp;
-  tmp=*list;
-  *value=tmp->v;
-  *list=tmp->next;
-  free(tmp);
-}
-
-
-
-
-
-void
-gal_linkedlist_reverse_sll(struct gal_linkedlist_sll **list)
-{
-  size_t thisnum;
-  struct gal_linkedlist_sll *correctorder=NULL;
-
-  if( *list && (*list)->next )
-    {
-      while(*list!=NULL)
-        {
-          gal_linkedlist_pop_from_sll(list, &thisnum);
-          gal_linkedlist_add_to_sll(&correctorder, thisnum);
-        }
-      *list=correctorder;
-    }
-}
-
-
-
-
-
-size_t
-gal_linkedlist_num_in_sll(struct gal_linkedlist_sll *list)
-{
-  size_t num=0;
-  struct gal_linkedlist_sll *tmp;
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    ++num;
-  return num;
-}
-
-
-
-
-
-void
-gal_linkedlist_sll_to_array(struct gal_linkedlist_sll *list,
-                            size_t **s, size_t *num, int inverse)
-{
-  size_t i, *ts;
-  struct gal_linkedlist_sll *tmp;
-
-  *num=gal_linkedlist_num_in_sll(list);
-
-  errno=0;
-  *s=malloc(*num*sizeof(size_t));
-  if(*s==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: array of gal_linkedlist_sll "
-          "with %zu elements", *num);
-  ts=*s;
-
-  i = inverse ? *num-1: 0;
-  if(inverse)
-    for(tmp=list;tmp!=NULL;tmp=tmp->next)
-      ts[i--]=tmp->v;
-  else
-    for(tmp=list;tmp!=NULL;tmp=tmp->next)
-      ts[i++]=tmp->v;
-}
-
-
-
-
-
-void
-gal_linkedlist_print_sll(struct gal_linkedlist_sll *list)
-{
-  struct gal_linkedlist_sll *tmp;
-  printf("\n\n");
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    printf("%zu, ", tmp->v);
-  printf("\b\b.\n\n");
-  return;
-}
-
-
-
-
-
-void
-gal_linkedlist_free_sll(struct gal_linkedlist_sll *list)
-{
-  struct gal_linkedlist_sll *tmp, *ttmp;
-  tmp=list;
-  while(tmp!=NULL)
-    {
-      ttmp=tmp->next;
-      free(tmp);
-      tmp=ttmp;
-    }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- *****************            int            ********************
- ****************************************************************/
-void
-gal_linkedlist_add_to_ill(struct gal_linkedlist_ill **list, int value)
-{
-  struct gal_linkedlist_ill *newnode;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno,
-          "linkedlist: New element in gal_linkedlist_ill");
-
-  newnode->v=value;
-  newnode->next=*list;
-  *list=newnode;
-}
-
-
-
-
-
-void
-gal_linkedlist_pop_from_ill(struct gal_linkedlist_ill **list, int *value)
-{
-  struct gal_linkedlist_ill *tmp;
-  tmp=*list;
-  *value=tmp->v;
-  *list=tmp->next;
-  free(tmp);
-}
-
-
-
-
-
-void
-gal_linkedlist_reverse_ill(struct gal_linkedlist_ill **list)
-{
-  int thisnum;
-  struct gal_linkedlist_ill *correctorder=NULL;
-
-  if( *list && (*list)->next )
-    {
-      while(*list!=NULL)
-        {
-          gal_linkedlist_pop_from_ill(list, &thisnum);
-          gal_linkedlist_add_to_ill(&correctorder, thisnum);
-        }
-      *list=correctorder;
-    }
-}
-
-
-
-
-
-size_t
-gal_linkedlist_num_in_ill(struct gal_linkedlist_ill *list)
-{
-  size_t num=0;
-  struct gal_linkedlist_ill *tmp;
-  for(tmp=list;tmp!=NULL;tmp=tmp->next)
-    ++num;
-  return num;
-}
-
-
-
-
-
-void
-gal_linkedlist_print_ill(struct gal_linkedlist_ill *list)
-{
-  struct gal_linkedlist_ill *tmp;
-  for(tmp=list; tmp!=NULL; tmp=tmp->next)
-    printf("%d\n", tmp->v);
-}
-
-
-
-
-
-void
-gal_linkedlist_free_ill(struct gal_linkedlist_ill *list)
-{
-  struct gal_linkedlist_ill *tmp, *ttmp;
-  tmp=list;
-  while(tmp!=NULL)
-    {
-      ttmp=tmp->next;
-      free(tmp);
-      tmp=ttmp;
-    }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- *****************          void *           ********************
- ****************************************************************/
-void
-gal_linkedlist_add_to_vll(struct gal_linkedlist_vll **list, void *value)
-{
-  struct gal_linkedlist_vll *newnode;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno,
-          "linkedlist: New element in gal_linkedlist_ill");
-
-  newnode->v=value;
-  newnode->next=*list;
-  *list=newnode;
-}
-
-
-
-
-
-void
-gal_linkedlist_pop_from_vll(struct gal_linkedlist_vll **list, void **value)
-{
-  struct gal_linkedlist_vll *tmp;
-  tmp=*list;
-  *value=tmp->v;
-  *list=tmp->next;
-  free(tmp);
-}
-
-
-
-
-
-void
-gal_linkedlist_reverse_vll(struct gal_linkedlist_vll **list)
-{
-  void *thisptr;
-  struct gal_linkedlist_vll *correctorder=NULL;
-
-  if( *list && (*list)->next )
-    {
-      while(*list!=NULL)
-        {
-          gal_linkedlist_pop_from_vll(list, &thisptr);
-          gal_linkedlist_add_to_vll(&correctorder, thisptr);
-        }
-      *list=correctorder;
-    }
-}
-
-
-
-
-
-void
-gal_linkedlist_free_vll(struct gal_linkedlist_vll *list, int freevalue)
-{
-  struct gal_linkedlist_vll *tmp=list, *ttmp;
-  while(tmp!=NULL)
-    {
-      if(freevalue) free(tmp->v);
-      ttmp=tmp->next;
-      free(tmp);
-      tmp=ttmp;
-    }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- ******************        Ordered SLL       ********************
- *****************           size_t          ********************
- ****************************************************************/
-/* We want to put the nodes in order based on the 'tosort' value of
-each node. The top element should always have the smallest radius. */
-void
-gal_linkedlist_add_to_osll(struct gal_linkedlist_osll **list,
-                           size_t value, float tosort)
-{
-  struct gal_linkedlist_osll *newnode, *tmp=*list, *prev=NULL;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: New element "
-          "in gal_linkedlist_osll");
-
-  newnode->v=value;
-  newnode->s=tosort;
-
-  /* *list points to the smallest value in the queue!*/
-  while(tmp!=NULL)
-    {
-      if(tosort<tmp->s) break;
-      /* No need for else, it will only come here if the condition
-         above is not satisfied. */
-      prev=tmp;
-      tmp=tmp->next;
-    }
-
-  if(tmp==NULL)      /* This is the largest value so far. */
-    {                /* '*list' only changes if it is NULL. */
-      newnode->next=NULL;
-      if(prev) prev->next=newnode;   /* 'prev' is not NULL! */
-      else     *list=newnode;        /* Only for initial node. */
-    }
-  else
-    {
-      if(prev) prev->next=newnode;
-      else     *list=newnode;        /* 'tosort' is smaller than all. */
-      newnode->next=tmp;
-    }
-}
-
-
-
-
-
-/* Note that the popped element is the smallest! */
-void
-gal_linkedlist_pop_from_osll(struct gal_linkedlist_osll **list,
-                             size_t *value, float *sortvalue)
-{
-  struct gal_linkedlist_osll *tmp;
-  tmp=*list;
-  *value=tmp->v;
-  *sortvalue=tmp->s;
-  *list=tmp->next;
-  free(tmp);
-}
-
-
-
-
-
-/* Add the elements of an gal_linkedlist_osll to a gal_linkedlist_sll. */
-void
-gal_linkedlist_osll_into_sll(struct gal_linkedlist_osll *in,
-                             struct gal_linkedlist_sll **out)
-{
-  struct gal_linkedlist_osll *tmp;
-  while(in!=NULL)
-    {
-      tmp=in->next;
-      gal_linkedlist_add_to_sll(out, in->v);
-      free(in);
-      in=tmp;
-    }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- ******************   Two way, Ordered SLL   ********************
- *****************           size_t          ********************
- ****************************************************************/
-
-/* The two way ordered SLL looks something like this:
-
-            largest pointer
-            |
-   NULL <-- (v0,s0) <--> (v1,s1) <--> ... (vn,sn) --> NULL
-                                          |
-                           smallest pointer
-
-   Where s(n)>s(n+1) for all n.
-*/
-
-void
-gal_linkedlist_print_tosll(struct gal_linkedlist_tosll *largest,
-                           struct gal_linkedlist_tosll *smallest)
-{
-  size_t counter=1;   /* We are not counting array elements :-D ! */
-  while(largest!=NULL)
-    {
-      printf("\t%-5zu (%zu, %.4f) \n", counter++,
-             largest->v, largest->s);
-      largest=largest->next;
-      printf("\t\t\t\t(%zu, %.4f)\n", smallest->v, smallest->s);
-      smallest=smallest->prev;
-    }
-  printf("\n");
-}
-
-
-
-
-
-/* Very similar to Ordered SLL, but now it is two way. */
-void
-gal_linkedlist_add_to_tosll_end(struct gal_linkedlist_tosll **largest,
-                                struct gal_linkedlist_tosll **smallest,
-                                size_t value, float tosort)
-{
-  struct gal_linkedlist_tosll *newnode, *tmp=*largest;
-
-  errno=0;
-  newnode=malloc(sizeof *newnode);
-  if(newnode==NULL)
-    error(EXIT_FAILURE, errno, "linkedlist: New element "
-          "in gal_linkedlist_tosll");
-
-  newnode->v=value;
-  newnode->s=tosort;
-  newnode->prev=NULL;
-
-  while(tmp!=NULL)
-    {
-      if(tosort >= tmp->s) break;
-      /* No need for else, it will only come here if the condition
-         above is not satisfied. */
-      newnode->prev=tmp;
-      tmp=tmp->next;
-    }
-
-  if(tmp==NULL)      /* This is the smallest value so far.     */
-    {                /* '*largest' only changes if it is NULL. */
-      newnode->next=NULL;
-      *smallest=newnode;
-      if(newnode->prev)         /* 'prev' is not NULL! */
-        newnode->prev->next=newnode;
-      else                      /* 'prev is NULL, Only first. */
-        *largest=newnode;
-    }
-  else
-    {
-      if(newnode->prev)
-        {
-          newnode->prev->next->prev=newnode;
-          newnode->prev->next=newnode;
-        }
-      else
-        {
-          (*largest)->prev=newnode;
-          *largest=newnode;       /* 'tosort' is larger than all. */
-        }
-      newnode->next=tmp;
-    }
-}
-
-
-
-
-
-/* Note that start has to be initialized. */
-void
-gal_linkedlist_pop_from_tosll_start(struct gal_linkedlist_tosll **largest,
-                                    struct gal_linkedlist_tosll **smallest,
-                                    size_t *value, float *tosort)
-{
-  struct gal_linkedlist_tosll *tmp=*smallest;
-
-  *value=tmp->v;
-  *tosort=tmp->s;
-
-  *smallest=tmp->prev;
-  free(tmp);
-  if(*smallest)
-    (*smallest)->next=NULL;
-  else
-    *largest=NULL;
-
-  /*printf("Popped v: %zu, s: %f\n", *value, *tosort);*/
-}
-
-
-
-
-
-void
-gal_linkedlist_smallest_tosll(struct gal_linkedlist_tosll *largest,
-                              struct gal_linkedlist_tosll **smallest)
-{
-  struct gal_linkedlist_tosll *tmp=largest;
-
-  while(tmp!=NULL)
-    {
-      if(tmp->next==NULL)
-        {
-          *smallest=tmp;
-          break;
-        }
-      tmp=tmp->next;
-    }
-
-  /* If *largest wasn't NULL initially, tmp should not be NULL because
-     the loop terminated before it becomes null. But if it was
-     initiall NULL, it will never enter the loop, and so smallest
-     should also be NULL. */
-  if(tmp==NULL) *smallest=NULL;
-}
-
-
-
-
-void
-gal_linkedlist_tosll_into_sll(struct gal_linkedlist_tosll *in,
-                              struct gal_linkedlist_sll **out)
-{
-  struct gal_linkedlist_tosll *tmp;
-  while(in!=NULL)
-    {
-      tmp=in->next;
-      gal_linkedlist_add_to_sll(out, in->v);
-      free(in);
-      in=tmp;
-    }
-}
-
-
-
-
-
-void
-gal_linkedlist_tosll_free(struct gal_linkedlist_tosll *largest)
-{
-  struct gal_linkedlist_tosll *tmp;
-  while(largest!=NULL)
-    {
-      tmp=largest->next;
-      free(largest);
-      largest=tmp;
-    }
-}
diff --git a/lib/list.c b/lib/list.c
new file mode 100644
index 0000000..9858500
--- /dev/null
+++ b/lib/list.c
@@ -0,0 +1,1307 @@
+/*********************************************************************
+Functions for linked lists.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Mohammad Akhlaghi <address@hidden>
+Contributing author(s):
+Copyright (C) 2015, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#include <gnuastro/list.h>
+#include <gnuastro/blank.h>
+
+#include <gnuastro-internal/checkset.h>
+
+
+
+
+
+
+
+
+
+/****************************************************************
+ *****************           String          ********************
+ ****************************************************************/
+void
+gal_list_str_add(gal_list_str_t **list, char *value,
+                 int allocate)
+{
+  gal_list_str_t *newnode;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno,
+          "list: New element in gal_list_stll");
+
+  if(allocate)
+    gal_checkset_allocate_copy(value, &newnode->v);
+  else
+    newnode->v=value;
+
+  newnode->next=*list;
+  *list=newnode;
+}
+
+
+
+
+
+char *
+gal_list_str_pop(gal_list_str_t **list)
+{
+  char *out=NULL;
+  gal_list_str_t *tmp;
+  if(*list)
+    {
+      tmp=*list;
+      out=tmp->v;
+      *list=tmp->next;
+      free(tmp);
+    }
+  return out;
+}
+
+
+
+
+
+size_t
+gal_list_str_number(gal_list_str_t *list)
+{
+  size_t num=0;
+  gal_list_str_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next) ++num;
+  return num;
+}
+
+
+
+
+
+void
+gal_list_str_print(gal_list_str_t *list)
+{
+  gal_list_str_t *tmp;
+  for(tmp=list; tmp!=NULL; tmp=tmp->next)
+    printf("%s\n", tmp->v);
+}
+
+
+
+
+
+void
+gal_list_str_reverse(gal_list_str_t **list)
+{
+  char *thisstring;
+  gal_list_str_t *correctorder=NULL;
+
+  /* Only do the reversal if there is more than one element. */
+  if( *list && (*list)->next )
+    {
+      while(*list!=NULL)
+        {
+          thisstring=gal_list_str_pop(list);
+          gal_list_str_add(&correctorder, thisstring, 0);
+        }
+      *list=correctorder;
+    }
+}
+
+
+
+
+
+void
+gal_list_str_free(gal_list_str_t *list, int freevalue)
+{
+  gal_list_str_t *tmp;
+  while(list!=NULL)
+    {
+      tmp=list->next;
+      if(freevalue)
+        free(list->v);
+      free(list);
+      list=tmp;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/****************************************************************
+ *****************            int            ********************
+ ****************************************************************/
+void
+gal_list_i32_add(gal_list_i32_t **list, int32_t value)
+{
+  gal_list_i32_t *newnode;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno,
+          "list: New element in gal_list_ill");
+
+  newnode->v=value;
+  newnode->next=*list;
+  *list=newnode;
+}
+
+
+
+
+
+int32_t
+gal_list_i32_pop(gal_list_i32_t **list)
+{
+  gal_list_i32_t *tmp;
+  int out=GAL_BLANK_INT32;
+
+  if(*list)
+    {
+      tmp=*list;
+      out=tmp->v;
+      *list=tmp->next;
+      free(tmp);
+    }
+  return out;
+}
+
+
+
+
+
+size_t
+gal_list_i32_number(gal_list_i32_t *list)
+{
+  size_t num=0;
+  gal_list_i32_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next)
+    ++num;
+  return num;
+}
+
+
+
+
+
+void
+gal_list_i32_print(gal_list_i32_t *list)
+{
+  gal_list_i32_t *tmp;
+  for(tmp=list; tmp!=NULL; tmp=tmp->next)
+    printf("%"PRId32"\n", tmp->v);
+}
+
+
+
+
+
+void
+gal_list_i32_reverse(gal_list_i32_t **list)
+{
+  int thisnum;
+  gal_list_i32_t *correctorder=NULL;
+
+  if( *list && (*list)->next )
+    {
+      while(*list!=NULL)
+        {
+          thisnum=gal_list_i32_pop(list);
+          gal_list_i32_add(&correctorder, thisnum);
+        }
+      *list=correctorder;
+    }
+}
+
+
+
+
+
+int32_t *
+gal_list_i32_to_array(gal_list_i32_t *list, int inverse, size_t *num)
+{
+  size_t i;
+  int32_t *out=NULL;
+  gal_list_i32_t *tmp;
+
+  *num=gal_list_i32_number(list);
+
+  if(*num)
+    {
+      out=gal_data_malloc_array(GAL_TYPE_SIZE_T, *num);
+
+      i = inverse ? *num-1: 0;
+      if(inverse)
+        for(tmp=list;tmp!=NULL;tmp=tmp->next)
+          out[i--]=tmp->v;
+      else
+        for(tmp=list;tmp!=NULL;tmp=tmp->next)
+          out[i++]=tmp->v;
+    }
+
+  return out;
+}
+
+
+
+
+
+void
+gal_list_i32_free(gal_list_i32_t *list)
+{
+  gal_list_i32_t *tmp, *ttmp;
+  tmp=list;
+  while(tmp!=NULL)
+    {
+      ttmp=tmp->next;
+      free(tmp);
+      tmp=ttmp;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/****************************************************************
+ *****************           size_t          ********************
+ ****************************************************************/
+void
+gal_list_sizet_add(gal_list_sizet_t **list, size_t value)
+{
+  gal_list_sizet_t *newnode;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno,
+          "list: New element in gal_list_sll");
+
+  newnode->v=value;
+  newnode->next=*list;
+  *list=newnode;
+}
+
+
+
+
+
+size_t
+gal_list_sizet_pop(gal_list_sizet_t **list)
+{
+  gal_list_sizet_t *tmp;
+  size_t out=GAL_BLANK_SIZE_T;
+
+  if(list)
+    {
+      tmp=*list;
+      out=tmp->v;
+      *list=tmp->next;
+      free(tmp);
+    }
+  return out;
+}
+
+
+
+
+
+size_t
+gal_list_sizet_number(gal_list_sizet_t *list)
+{
+  size_t num=0;
+  gal_list_sizet_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next)
+    ++num;
+  return num;
+}
+
+
+
+
+void
+gal_list_sizet_print(gal_list_sizet_t *list)
+{
+  gal_list_sizet_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next)
+    printf("%zu\n", tmp->v);
+  return;
+}
+
+
+
+
+
+void
+gal_list_sizet_reverse(gal_list_sizet_t **list)
+{
+  size_t thisnum;
+  gal_list_sizet_t *correctorder=NULL;
+
+  if( *list && (*list)->next )
+    {
+      while(*list!=NULL)
+        {
+          thisnum=gal_list_sizet_pop(list);
+          gal_list_sizet_add(&correctorder, thisnum);
+        }
+      *list=correctorder;
+    }
+}
+
+
+
+
+
+size_t *
+gal_list_sizet_to_array(gal_list_sizet_t *list, int inverse, size_t *num)
+{
+  size_t i, *out=NULL;
+  gal_list_sizet_t *tmp;
+
+  *num=gal_list_sizet_number(list);
+
+  if(*num)
+    {
+      out=gal_data_malloc_array(GAL_TYPE_SIZE_T, *num);
+
+      i = inverse ? *num-1: 0;
+      if(inverse)
+        for(tmp=list;tmp!=NULL;tmp=tmp->next)
+          out[i--]=tmp->v;
+      else
+        for(tmp=list;tmp!=NULL;tmp=tmp->next)
+          out[i++]=tmp->v;
+    }
+
+  return out;
+}
+
+
+
+
+
+void
+gal_list_sizet_free(gal_list_sizet_t *list)
+{
+  gal_list_sizet_t *tmp, *ttmp;
+  tmp=list;
+  while(tmp!=NULL)
+    {
+      ttmp=tmp->next;
+      free(tmp);
+      tmp=ttmp;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/****************************************************************
+ *****************            Float          ********************
+ ****************************************************************/
+void
+gal_list_f32_add(gal_list_f32_t **list, float value)
+{
+  struct gal_list_f32_t *newnode;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "list: New element in "
+          "gal_list_f32_t");
+
+  newnode->v=value;
+  newnode->next=*list;
+  *list=newnode;
+}
+
+
+
+
+
+float
+gal_list_f32_pop(gal_list_f32_t **list)
+{
+  float out=NAN;
+  gal_list_f32_t *tmp;
+
+  if(*list)
+    {
+      tmp=*list;
+      out=tmp->v;
+      *list=tmp->next;
+      free(tmp);
+    }
+  return out;
+}
+
+
+
+
+
+size_t
+gal_list_f32_number(gal_list_f32_t *list)
+{
+  size_t num=0;
+  gal_list_f32_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next)
+    ++num;
+  return num;
+}
+
+
+
+
+
+void
+gal_list_f32_reverse(gal_list_f32_t **list)
+{
+  float thisnum;
+  gal_list_f32_t *correctorder=NULL;
+
+  if( *list && (*list)->next )
+    {
+      while(*list!=NULL)
+        {
+          thisnum=gal_list_f32_pop(list);
+          gal_list_f32_add(&correctorder, thisnum);
+        }
+      *list=correctorder;
+    }
+}
+
+
+
+
+
+void
+gal_list_f32_print(gal_list_f32_t *list)
+{
+  gal_list_f32_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next)
+    printf("%f\n", tmp->v);
+  return;
+}
+
+
+
+
+
+float *
+gal_list_f32_to_array(gal_list_f32_t *list, int inverse, size_t *num)
+{
+  size_t i;
+  float *out=NULL;
+  gal_list_f32_t *tmp;
+
+  /* Find the number of elements: */
+  *num=gal_list_f32_number(list);
+
+  /* If there is actually anything in the list, then allocate the array and
+     fill it in. */
+  if(*num)
+    {
+      /* Allocate the space: */
+      out=gal_data_malloc_array(GAL_TYPE_FLOAT32, *num);
+
+      /* Fill in the array. */
+      i = inverse ? *num-1: 0;
+      if(inverse)
+        for(tmp=list;tmp!=NULL;tmp=tmp->next)
+          out[i--]=tmp->v;
+      else
+        for(tmp=list;tmp!=NULL;tmp=tmp->next)
+          out[i++]=tmp->v;
+    }
+
+  /* Return the created array. */
+  return out;
+}
+
+
+
+
+
+void
+gal_list_f32_free(gal_list_f32_t *list)
+{
+  gal_list_f32_t *tmp, *ttmp;
+  tmp=list;
+  while(tmp!=NULL)
+    {
+      ttmp=tmp->next;
+      free(tmp);
+      tmp=ttmp;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/****************************************************************
+ *****************          Double           ********************
+ ****************************************************************/
+void
+gal_list_f64_add(gal_list_f64_t **list, double value)
+{
+  gal_list_f64_t *newnode;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "list: New element in "
+          "gal_list_dll");
+
+  newnode->v=value;
+  newnode->next=*list;
+  *list=newnode;
+}
+
+
+
+
+
+double
+gal_list_f64_pop(gal_list_f64_t **list)
+{
+  double out=NAN;
+  gal_list_f64_t *tmp;
+
+  if(*list)
+    {
+      tmp=*list;
+      out=tmp->v;
+      *list=tmp->next;
+      free(tmp);
+    }
+  return out;
+}
+
+
+
+
+
+size_t
+gal_list_f64_number(gal_list_f64_t *list)
+{
+  size_t num=0;
+  gal_list_f64_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next)
+    ++num;
+  return num;
+}
+
+
+
+
+
+void
+gal_list_f64_print(gal_list_f64_t *list)
+{
+  gal_list_f64_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next)
+    printf("%f\n", tmp->v);
+  return;
+}
+
+
+
+
+
+void
+gal_list_f64_reverse(gal_list_f64_t **list)
+{
+  double thisvalue;
+  gal_list_f64_t *correctorder=NULL;
+
+  /* Only do the reversal if there is more than one element. */
+  if( *list && (*list)->next )
+    {
+      while(*list!=NULL)
+        {
+          thisvalue=gal_list_f64_pop(list);
+          gal_list_f64_add(&correctorder, thisvalue);
+        }
+      *list=correctorder;
+    }
+}
+
+
+
+
+double *
+gal_list_f64_to_array(gal_list_f64_t *list, int inverse, size_t *num)
+{
+  size_t i;
+  double *out=NULL;
+  gal_list_f64_t *tmp;
+
+  /* Find the number of elements: */
+  *num=gal_list_f64_number(list);
+
+  /* If there is actually anything in the list, then allocate the array and
+     fill it in. */
+  if(*num)
+    {
+      /* Allocate the space: */
+      out=gal_data_malloc_array(GAL_TYPE_FLOAT64, *num);
+
+      /* Fill in the array. */
+      i = inverse ? *num-1: 0;
+      if(inverse)
+        for(tmp=list;tmp!=NULL;tmp=tmp->next)
+          out[i--]=tmp->v;
+      else
+        for(tmp=list;tmp!=NULL;tmp=tmp->next)
+          out[i++]=tmp->v;
+    }
+
+  /* Return the created array. */
+  return out;
+}
+
+
+
+
+
+void
+gal_list_f64_free(gal_list_f64_t *list)
+{
+  gal_list_f64_t *tmp, *ttmp;
+  tmp=list;
+  while(tmp!=NULL)
+    {
+      ttmp=tmp->next;
+      free(tmp);
+      tmp=ttmp;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/****************************************************************
+ *****************          void *           ********************
+ ****************************************************************/
+void
+gal_list_void_add(gal_list_void_t **list, void *value)
+{
+  gal_list_void_t *newnode;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno,
+          "list: New element in gal_list_ill");
+
+  newnode->v=value;
+  newnode->next=*list;
+  *list=newnode;
+}
+
+
+
+
+
+void *
+gal_list_void_pop(gal_list_void_t **list)
+{
+  void *out=NULL;
+  gal_list_void_t *tmp;
+
+  if(*list)
+    {
+      tmp=*list;
+      out=tmp->v;
+      *list=tmp->next;
+      free(tmp);
+    }
+  return out;
+}
+
+
+
+
+
+size_t
+gal_list_void_number(gal_list_void_t *list)
+{
+  size_t num=0;
+  gal_list_void_t *tmp;
+  for(tmp=list;tmp!=NULL;tmp=tmp->next)
+    ++num;
+  return num;
+}
+
+
+
+
+void
+gal_list_void_reverse(gal_list_void_t **list)
+{
+  void *thisptr;
+  gal_list_void_t *correctorder=NULL;
+
+  if( *list && (*list)->next )
+    {
+      while(*list!=NULL)
+        {
+          thisptr=gal_list_void_pop(list);
+          gal_list_void_add(&correctorder, thisptr);
+        }
+      *list=correctorder;
+    }
+}
+
+
+
+
+
+void
+gal_list_void_free(gal_list_void_t *list, int freevalue)
+{
+  gal_list_void_t *tmp=list, *ttmp;
+  while(tmp!=NULL)
+    {
+      if(freevalue) free(tmp->v);
+      ttmp=tmp->next;
+      free(tmp);
+      tmp=ttmp;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/****************************************************************
+ ****************       Ordered size_t       ********************
+ ****************************************************************/
+/* We want to put the nodes in order based on the 'tosort' value of
+each node. The top element should always have the smallest radius. */
+void
+gal_list_osizet_add(gal_list_osizet_t **list,
+                    size_t value, float tosort)
+{
+  gal_list_osizet_t *newnode, *tmp=*list, *prev=NULL;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "list: New element "
+          "in gal_list_osll");
+
+  newnode->v=value;
+  newnode->s=tosort;
+
+  /* *list points to the smallest value in the queue!*/
+  while(tmp!=NULL)
+    {
+      if(tosort<tmp->s) break;
+      /* No need for else, it will only come here if the condition
+         above is not satisfied. */
+      prev=tmp;
+      tmp=tmp->next;
+    }
+
+  if(tmp==NULL)      /* This is the largest value so far. */
+    {                /* '*list' only changes if it is NULL. */
+      newnode->next=NULL;
+      if(prev) prev->next=newnode;   /* 'prev' is not NULL! */
+      else     *list=newnode;        /* Only for initial node. */
+    }
+  else
+    {
+      if(prev) prev->next=newnode;
+      else     *list=newnode;        /* 'tosort' is smaller than all. */
+      newnode->next=tmp;
+    }
+}
+
+
+
+
+
+/* Note that the popped element is the smallest! */
+void
+gal_list_osizet_pop(gal_list_osizet_t **list,
+                    size_t *value, float *sortvalue)
+{
+  gal_list_osizet_t *tmp=*list;
+
+  if(*list)
+    {
+      *value=tmp->v;
+      *sortvalue=tmp->s;
+      *list=tmp->next;
+      free(tmp);
+    }
+  else
+    {
+      *value=GAL_BLANK_SIZE_T;
+      *sortvalue=NAN;
+    }
+}
+
+
+
+
+
+/* Add the elements of an gal_list_osll to a gal_list_sll. */
+void
+gal_list_osizet_to_sizet_free(gal_list_osizet_t *in,
+                              gal_list_sizet_t **out)
+{
+  gal_list_osizet_t *tmp;
+  while(in!=NULL)
+    {
+      tmp=in->next;
+      gal_list_sizet_add(out, in->v);
+      free(in);
+      in=tmp;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/****************************************************************
+ ******************   Two way, Ordered SLL   ********************
+ *****************           size_t          ********************
+ ****************************************************************/
+
+/* The two way ordered SLL looks something like this:
+
+            largest pointer
+            |
+   NULL <-- (v0,s0) <--> (v1,s1) <--> ... (vn,sn) --> NULL
+                                          |
+                           smallest pointer
+
+   Where s(n)>s(n+1) for all n.
+*/
+/* Very similar to Ordered SLL, but now it is two way. */
+void
+gal_list_tosizet_add(gal_list_tosizet_t **largest,
+                     gal_list_tosizet_t **smallest,
+                     size_t value, float tosort)
+{
+  gal_list_tosizet_t *newnode, *tmp=*largest;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "list: New element "
+          "in gal_list_tosll");
+
+  newnode->v=value;
+  newnode->s=tosort;
+  newnode->prev=NULL;
+
+  while(tmp!=NULL)
+    {
+      if(tosort >= tmp->s) break;
+      /* No need for else, it will only come here if the condition
+         above is not satisfied. */
+      newnode->prev=tmp;
+      tmp=tmp->next;
+    }
+
+  if(tmp==NULL)      /* This is the smallest value so far.     */
+    {                /* '*largest' only changes if it is NULL. */
+      newnode->next=NULL;
+      *smallest=newnode;
+      if(newnode->prev)         /* 'prev' is not NULL! */
+        newnode->prev->next=newnode;
+      else                      /* 'prev is NULL, Only first. */
+        *largest=newnode;
+    }
+  else
+    {
+      if(newnode->prev)
+        {
+          newnode->prev->next->prev=newnode;
+          newnode->prev->next=newnode;
+        }
+      else
+        {
+          (*largest)->prev=newnode;
+          *largest=newnode;       /* 'tosort' is larger than all. */
+        }
+      newnode->next=tmp;
+    }
+}
+
+
+
+
+
+void
+gal_list_tosizet_print(gal_list_tosizet_t *largest,
+                       gal_list_tosizet_t *smallest)
+{
+  size_t counter=1;   /* We are not counting array elements :-D ! */
+  while(largest!=NULL)
+    {
+      printf("\t%-5zu (%zu, %.4f) \n", counter++,
+             largest->v, largest->s);
+      largest=largest->next;
+      printf("\t\t\t\t(%zu, %.4f)\n", smallest->v, smallest->s);
+      smallest=smallest->prev;
+    }
+  printf("\n");
+}
+
+
+
+
+
+/* Note that start has to be initialized. */
+void
+gal_list_tosizet_pop_smallest(gal_list_tosizet_t **largest,
+                              gal_list_tosizet_t **smallest,
+                              size_t *value, float *tosort)
+{
+  gal_list_tosizet_t *tmp=*smallest;
+
+  if(*smallest)
+    {
+      *value=tmp->v;
+      *tosort=tmp->s;
+
+      *smallest=tmp->prev;
+      free(tmp);
+      if(*smallest)
+        (*smallest)->next=NULL;
+      else
+        *largest=NULL;
+    }
+  else
+    {
+      /* If `smallest' is NULL, `largest' should also be NULL. */
+      if(*largest)
+        error(EXIT_FAILURE, 0, "`largest' and `smallest' pointers to "
+              "`gal_list_tosizet_pop_smallest' must both be non-NULL or "
+              "both be NULL. However, in this call, `smallest' was NULL "
+              "while `largest' isn't NULL");
+      *value=GAL_BLANK_SIZE_T;
+      *tosort=NAN;
+    }
+
+  /*printf("Popped v: %zu, s: %f\n", *value, *tosort);*/
+}
+
+
+
+
+
+void
+gal_list_tosizet_to_sizet(gal_list_tosizet_t *in, gal_list_sizet_t **out)
+{
+  gal_list_tosizet_t *tmp;
+  while(in!=NULL)
+    {
+      tmp=in->next;
+      gal_list_sizet_add(out, in->v);
+      free(in);
+      in=tmp;
+    }
+}
+
+
+
+
+
+void
+gal_list_tosizet_free(gal_list_tosizet_t *largest)
+{
+  gal_list_tosizet_t *tmp;
+  while(largest!=NULL)
+    {
+      tmp=largest->next;
+      free(largest);
+      largest=tmp;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*********************************************************************/
+/*************    Data structure as a linked list   ******************/
+/*********************************************************************/
+/* Add a new data structure to the top of an existing linked list of data
+   structures. Note that if the new node is its self a list, all its nodes
+   will be added to the list. */
+void
+gal_list_data_add(gal_data_t **list, gal_data_t *newnode)
+{
+  gal_data_t *tmp=newnode, *toadd;
+
+  /* Check if newnode is itself a list or not. */
+  if(newnode->next)
+    {
+      /* Go onto the last node in newnode's existing list. */
+      while(tmp->next) tmp=tmp->next;
+
+      /* Set the last node as the node to add to the list. */
+      toadd=tmp;
+    }
+  else
+    /* Its not a list, so just set it to `toadd'. */
+    toadd=newnode;
+
+
+  /* Set the next element of toadd and update what list points to.*/
+  toadd->next=*list;
+  *list=toadd;
+}
+
+
+
+
+
+void
+gal_list_data_add_alloc(gal_data_t **list, void *array, uint8_t type,
+                        size_t ndim, size_t *dsize, struct wcsprm *wcs,
+                        int clear, size_t minmapsize, char *name,
+                        char *unit, char *comment)
+{
+  gal_data_t *newnode;
+
+  /* Put all the input information into a new data structure node. */
+  newnode=gal_data_alloc(array, type, ndim, dsize, wcs, clear,
+                         minmapsize, name, unit, comment);
+
+  /* Add the new node to the list. */
+  gal_list_data_add(list, newnode);
+}
+
+
+
+
+
+gal_data_t *
+gal_list_data_pop(gal_data_t **list)
+{
+  gal_data_t *out=NULL;
+
+  /* If list is not empty. */
+  if(*list)
+    {
+      /* Keep the top pointer. */
+      out=*list;
+
+      /* Move the list pointer to the next node. */
+      *list=out->next;
+
+      /* Set the next poitner of the out pointer to NULL so it isn't
+         interpretted as a list any more. */
+      out->next=NULL;
+    }
+  return out;
+}
+
+
+
+
+
+void
+gal_list_data_reverse(gal_data_t **list)
+{
+  gal_data_t *popped, *in=*list, *reversed=NULL;
+
+  /* Only do the job if the list is not NULL and has more than one node. */
+  if( in && in->next )
+    {
+      while(in!=NULL)
+        {
+          popped=gal_list_data_pop(&in);
+          gal_list_data_add(&reversed, popped);
+        }
+      *list=reversed;
+    }
+}
+
+
+
+
+
+size_t
+gal_list_data_number(gal_data_t *list)
+{
+  size_t num=0;
+  while(list!=NULL)
+    {
+      ++num;
+      list=list->next;
+    }
+  return num;
+}
+
+
+
+
+void
+gal_list_data_free(gal_data_t *list)
+{
+  struct gal_data_t *tmp;
+  while(list!=NULL)
+    {
+      tmp=list->next;
+      gal_data_free(list);
+      list=tmp;
+    }
+}
diff --git a/lib/options.c b/lib/options.c
index 84db9d8..d78f17a 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -30,6 +30,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/git.h>
 #include <gnuastro/txt.h>
+#include <gnuastro/list.h>
 #include <gnuastro/data.h>
 #include <gnuastro/table.h>
 #include <gnuastro/arithmetic.h>
@@ -85,8 +86,8 @@ void
 gal_options_add_to_not_given(struct gal_options_common_params *cp,
                              struct argp_option *option)
 {
-  gal_linkedlist_add_to_stll(&cp->novalue_doc, (char *)option->doc, 0);
-  gal_linkedlist_add_to_stll(&cp->novalue_name, (char *)option->name, 0);
+  gal_list_str_add(&cp->novalue_doc, (char *)option->doc, 0);
+  gal_list_str_add(&cp->novalue_name, (char *)option->name, 0);
 }
 
 
@@ -97,8 +98,8 @@ void
 gal_options_abort_if_mandatory_missing(struct gal_options_common_params *cp)
 {
   int namewidth=0;
+  gal_list_str_t *tmp;
   char info[5000], *name, *doc;
-  struct gal_linkedlist_stll *tmp;
 
   /* If there is no mandatory options, then just return. */
   if(cp->novalue_name==NULL)
@@ -116,8 +117,8 @@ gal_options_abort_if_mandatory_missing(struct 
gal_options_common_params *cp)
   /* Print the list of options along with their description. */
   while(cp->novalue_name!=NULL)
     {
-      gal_linkedlist_pop_from_stll(&cp->novalue_doc, &doc);
-      gal_linkedlist_pop_from_stll(&cp->novalue_name, &name);
+      doc  = gal_list_str_pop(&cp->novalue_doc);
+      name = gal_list_str_pop(&cp->novalue_name);
       sprintf(info+strlen(info), "  %-*s (%s\b)\n", namewidth+4, name, doc);
     }
   sprintf(info+strlen(info), "\n");
@@ -166,8 +167,8 @@ gal_options_parse_list_of_numbers(char *string, char 
*filename, size_t lineno)
   size_t i, num=0;
   gal_data_t *out;
   char *c=string, *tailptr;
+  gal_list_f64_t *list=NULL, *tdll;
   double numerator=NAN, denominator=NAN, tmp;
-  struct gal_linkedlist_dll *list=NULL, *tdll;
 
 
   /* The nature of the arrays/numbers read here is very small, so since
@@ -194,8 +195,8 @@ gal_options_parse_list_of_numbers(char *string, char 
*filename, size_t lineno)
             error_at_line(EXIT_FAILURE, 0, filename, lineno, "a number "
                           "must be given before `,'. You have given: `%s'",
                           string);
-          gal_linkedlist_add_to_dll(&list, isnan(denominator)
-                                    ? numerator : numerator/denominator);
+          gal_list_f64_add(&list, isnan(denominator)
+                           ? numerator : numerator/denominator);
           numerator=denominator=NAN;
           ++num;
           ++c;
@@ -241,8 +242,8 @@ gal_options_parse_list_of_numbers(char *string, char 
*filename, size_t lineno)
   if( !isnan(numerator) )
     {
       ++num;
-      gal_linkedlist_add_to_dll(&list, isnan(denominator)
-                                ? numerator : numerator/denominator);
+      gal_list_f64_add(&list, isnan(denominator)
+                       ? numerator : numerator/denominator);
     }
 
 
@@ -255,7 +256,7 @@ gal_options_parse_list_of_numbers(char *string, char 
*filename, size_t lineno)
 
 
   /* Clean up and return. */
-  gal_linkedlist_free_dll(list);
+  gal_list_f64_free(list);
   return out;
 }
 
@@ -909,7 +910,7 @@ gal_options_read_check(struct argp_option *option, char 
*arg, char *filename,
   if(arg)
     {
       if(option->type==GAL_TYPE_STRLL)
-        gal_linkedlist_add_to_stll(option->value, arg, 1);
+        gal_list_str_add(option->value, arg, 1);
       else
         {
           /* If the option is already set, ignore the given value. */
@@ -1406,8 +1407,7 @@ options_reverse_lists_check_mandatory(struct 
gal_options_common_params *cp,
         switch(options[i].type)
           {
           case GAL_TYPE_STRLL:
-            gal_linkedlist_reverse_stll(
-                  (struct gal_linkedlist_stll **)(options[i].value) );
+            gal_list_str_reverse( (gal_list_str_t **)(options[i].value) );
             break;
           }
       else if(options[i].mandatory==GAL_OPTIONS_MANDATORY)
@@ -1533,7 +1533,7 @@ options_correct_max_lengths(struct argp_option *option, 
int *max_nlen,
                             struct gal_options_common_params *cp)
 {
   int vlen;
-  struct gal_linkedlist_stll *tmp;
+  gal_list_str_t *tmp;
 
   /* Invalid types are set for functions that don't save the raw user
      input, but do higher-level analysis on them for storing. */
@@ -1549,7 +1549,7 @@ options_correct_max_lengths(struct argp_option *option, 
int *max_nlen,
               "are acceptable for printing");
 
       /* Check each node, one by one. */
-      for(tmp=*(struct gal_linkedlist_stll **)(option->value);
+      for(tmp=*(gal_list_str_t **)(option->value);
           tmp!=NULL; tmp=tmp->next)
         {
           /* Get the length of this node: */
@@ -1661,7 +1661,7 @@ options_print_all_in_group(struct argp_option *options, 
int groupint,
                            struct gal_options_common_params *cp)
 {
   size_t i;
-  struct gal_linkedlist_stll *tmp;
+  gal_list_str_t *tmp;
   int namewidth=namelen+1, valuewidth=valuelen+1;
 
   /* Go over all the options. */
@@ -1672,7 +1672,7 @@ options_print_all_in_group(struct argp_option *options, 
int groupint,
       {
         /* Linked lists */
         if(gal_type_is_linked_list(options[i].type))
-          for(tmp=*(struct gal_linkedlist_stll **)(options[i].value);
+          for(tmp=*(gal_list_str_t **)(options[i].value);
               tmp!=NULL; tmp=tmp->next)
             {
               fprintf(fp, " %-*s ", namewidth, options[i].name);
@@ -1705,9 +1705,9 @@ options_print_all(struct gal_options_common_params *cp, 
char *dirname,
   FILE *fp;
   time_t rawtime;
   char *topicstr, *filename;
+  gal_list_i32_t *group=NULL;
+  gal_list_str_t *topic=NULL;
   int groupint, namelen, valuelen;
-  struct gal_linkedlist_ill *group=NULL;
-  struct gal_linkedlist_stll *topic=NULL;
   struct argp_option *coptions=cp->coptions, *poptions=cp->poptions;
 
   /* If the configurations are to be written to a file, then do the
@@ -1761,19 +1761,19 @@ options_print_all(struct gal_options_common_params *cp, 
char *dirname,
       {
         /* The `(char *)' is because `.doc' is a constant and this helps
            remove the compiler warning. */
-        gal_linkedlist_add_to_ill(&group, coptions[i].group);
-        gal_linkedlist_add_to_stll(&topic, (char *)coptions[i].doc, 0);
+        gal_list_i32_add(&group, coptions[i].group);
+        gal_list_str_add(&topic, (char *)coptions[i].doc, 0);
       }
   for(i=0; !gal_options_is_last(&poptions[i]); ++i)
     if(poptions[i].name==NULL && poptions[i].key==0 && poptions[i].doc)
       {
-        gal_linkedlist_add_to_ill(&group, poptions[i].group);
-        gal_linkedlist_add_to_stll(&topic, (char *)poptions[i].doc, 0);
+        gal_list_i32_add(&group, poptions[i].group);
+        gal_list_str_add(&topic, (char *)poptions[i].doc, 0);
       }
 
   /* Reverse the linked lists to get the same input order. */
-  gal_linkedlist_reverse_stll(&topic);
-  gal_linkedlist_reverse_ill(&group);
+  gal_list_str_reverse(&topic);
+  gal_list_i32_reverse(&group);
 
   /* Get the maximum width of names and values. */
   options_set_lengths(poptions, coptions, &namelen, &valuelen, cp);
@@ -1782,8 +1782,8 @@ options_print_all(struct gal_options_common_params *cp, 
char *dirname,
   while(topic)
     {
       /* Pop the nodes from the linked list. */
-      gal_linkedlist_pop_from_ill(&group, &groupint);
-      gal_linkedlist_pop_from_stll(&topic, &topicstr);
+      groupint = gal_list_i32_pop(&group);
+      topicstr = gal_list_str_pop(&topic);
 
       /* First print the topic, */
       fprintf(fp, "\n# %s\n", topicstr);
diff --git a/lib/table.c b/lib/table.c
index a862a1a..428d725 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -600,17 +600,17 @@ table_set_strcheck(gal_data_t *col, int searchin)
 
 
 
-static struct gal_linkedlist_sll *
-make_list_of_indexs(struct gal_linkedlist_stll *cols, gal_data_t *allcols,
+static gal_list_sizet_t *
+make_list_of_indexs(gal_list_str_t *cols, gal_data_t *allcols,
                     size_t numcols, int searchin, int ignorecase,
                     char *filename, char *hdu)
 {
   long tlong;
   int regreturn;
   regex_t *regex;
+  gal_list_str_t *tmp;
   size_t i, nummatch, len;
-  struct gal_linkedlist_stll *tmp;
-  struct gal_linkedlist_sll *indexll=NULL;
+  gal_list_sizet_t *indexll=NULL;
   char *str, *strcheck, *tailptr, *errorstring;
 
   for(tmp=cols; tmp!=NULL; tmp=tmp->next)
@@ -665,7 +665,7 @@ make_list_of_indexs(struct gal_linkedlist_stll *cols, 
gal_data_t *allcols,
               if(strcheck && regexec(regex, strcheck, 0, 0, 0)==0)
                 {
                   ++nummatch;
-                  gal_linkedlist_add_to_sll(&indexll, i);
+                  gal_list_sizet_add(&indexll, i);
                 }
             }
 
@@ -711,7 +711,7 @@ make_list_of_indexs(struct gal_linkedlist_stll *cols, 
gal_data_t *allcols,
               /* Everything seems to be fine, put this column number in the
                  output column numbers linked list. Note that internally,
                  the column numbers start from 0, not 1.*/
-              gal_linkedlist_add_to_sll(&indexll, tlong-1);
+              gal_list_sizet_add(&indexll, tlong-1);
               ++nummatch;
             }
 
@@ -733,7 +733,7 @@ make_list_of_indexs(struct gal_linkedlist_stll *cols, 
gal_data_t *allcols,
                                    : !strcmp(tmp->v, strcheck) ) )
                     {
                       ++nummatch;
-                      gal_linkedlist_add_to_sll(&indexll, i);
+                      gal_list_sizet_add(&indexll, i);
                     }
                 }
             }
@@ -752,7 +752,7 @@ make_list_of_indexs(struct gal_linkedlist_stll *cols, 
gal_data_t *allcols,
     }
 
   /* Reverse the list. */
-  gal_linkedlist_reverse_sll(&indexll);
+  gal_list_sizet_reverse(&indexll);
   return indexll;
 }
 
@@ -777,13 +777,13 @@ make_list_of_indexs(struct gal_linkedlist_stll *cols, 
gal_data_t *allcols,
    So the first requested column is the first popped data structure and so
    on. */
 gal_data_t *
-gal_table_read(char *filename, char *hdu, struct gal_linkedlist_stll *cols,
+gal_table_read(char *filename, char *hdu, gal_list_str_t *cols,
                int searchin, int ignorecase, int minmapsize)
 {
   int tableformat;
+  gal_list_sizet_t *indexll;
   size_t i, numcols, numrows;
   gal_data_t *allcols, *out=NULL;
-  struct gal_linkedlist_sll *indexll;
 
   /* If the column string linked list is empty, no need to continue. */
   if(cols==NULL) return NULL;
@@ -807,7 +807,7 @@ gal_table_read(char *filename, char *hdu, struct 
gal_linkedlist_stll *cols,
      order as the input list of desired columns. Also note that after these
      functions, the `indexll' will be all freed (each popped element is
      actually freed).*/
-  gal_linkedlist_reverse_sll(&indexll);
+  gal_list_sizet_reverse(&indexll);
   switch(tableformat)
     {
     case GAL_TABLE_FORMAT_TXT:
@@ -830,7 +830,7 @@ gal_table_read(char *filename, char *hdu, struct 
gal_linkedlist_stll *cols,
   for(i=0;i<numcols;++i)
     gal_data_free_contents(&allcols[i]);
   free(allcols);
-  gal_linkedlist_free_sll(indexll);
+  gal_list_sizet_free(indexll);
 
   /* Return the final linked list. */
   return out;
@@ -862,8 +862,8 @@ gal_table_read(char *filename, char *hdu, struct 
gal_linkedlist_stll *cols,
    comments field. Note that the `comments' has to be already sorted in the
    proper order. */
 void
-gal_table_comments_add_intro(struct gal_linkedlist_stll **comments,
-                             char *program_string, time_t *rawtime)
+gal_table_comments_add_intro(gal_list_str_t **comments, char *program_string,
+                             time_t *rawtime)
 {
   char gitdescribe[100], *tmp;
 
@@ -877,16 +877,16 @@ gal_table_comments_add_intro(struct gal_linkedlist_stll 
**comments,
   /* Git version and time of program's starting, this will be the second
      line. Note that ctime puts a `\n' at the end of its string, so we'll
      have to remove that. Also, note that since we are allocating `msg', we
-     are setting the allocate flag of `gal_linkedlist_add_to_stll' to 0. */
+     are setting the allocate flag of `gal_list_str_add' to 0. */
   asprintf(&tmp, "Created%s on %s", gitdescribe, ctime(rawtime));
   tmp[ strlen(tmp)-1 ]='\0';
-  gal_linkedlist_add_to_stll(comments, tmp, 0);
+  gal_list_str_add(comments, tmp, 0);
 
 
   /* Program name: this will be the top of the list (first line). We will
      need to set the allocation flag for this one, because program_string
      is usually statically allocated.*/
-  gal_linkedlist_add_to_stll(comments, program_string, 1);
+  gal_list_str_add(comments, program_string, 1);
 }
 
 
@@ -898,7 +898,7 @@ gal_table_comments_add_intro(struct gal_linkedlist_stll 
**comments,
    specified by `tableformat'. If it already exists, and `dontdelete' has a
    value of 1, then it won't be deleted and an error will be printed. */
 void
-gal_table_write(gal_data_t *cols, struct gal_linkedlist_stll *comments,
+gal_table_write(gal_data_t *cols, gal_list_str_t *comments,
                 int tableformat, char *filename, int dontdelete)
 {
   /* If a filename was given, then the tableformat is relevant and must be
@@ -922,7 +922,7 @@ gal_table_write(gal_data_t *cols, struct 
gal_linkedlist_stll *comments,
 
 void
 gal_table_write_log(gal_data_t *logll, char *program_string,
-                    time_t *rawtime, struct gal_linkedlist_stll *comments,
+                    time_t *rawtime, gal_list_str_t *comments,
                     char *filename, int dontdelete, int quiet)
 {
   char *msg;
diff --git a/lib/tile.c b/lib/tile.c
index 3b999f9..3cb8e6b 100644
--- a/lib/tile.c
+++ b/lib/tile.c
@@ -486,7 +486,7 @@ gal_data_t *
 gal_tile_block_check_tiles(gal_data_t *tilesll)
 {
   int32_t *arr;
-  size_t i, dsize=gal_data_num_in_ll(tilesll);
+  size_t i, dsize=gal_list_data_number(tilesll);
   gal_data_t *ids, *out, *block=gal_tile_block(tilesll);
 
   /* Allocate the array to keep the IDs of each tile. */
@@ -1252,7 +1252,7 @@ gal_tile_full_blank_flag(gal_data_t *tile_ll, size_t 
numthreads)
 {
   /* Go over all the tiles and update their blank flag. */
   gal_threads_spin_off(tile_full_blank_flag, tile_ll,
-                       gal_data_num_in_ll(tile_ll), numthreads);
+                       gal_list_data_number(tile_ll), numthreads);
 }
 
 
diff --git a/lib/txt.c b/lib/txt.c
index 7025307..24a7085 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -31,6 +31,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <stdlib.h>
 
 #include <gnuastro/txt.h>
+#include <gnuastro/list.h>
 #include <gnuastro/blank.h>
 #include <gnuastro/table.h>
 
@@ -255,8 +256,8 @@ txt_info_from_comment(char *line, gal_data_t **datall, char 
*comm_start)
          into the array by `gal_table_read_blank'. To keep the name, unit,
          and comment strings, trim the white space before and after each
          before using them here.  */
-      gal_data_add_to_ll(datall, NULL, type, 0, NULL, NULL, 0, -1, name,
-                         txt_trim_space(unit), txt_trim_space(comment) );
+      gal_list_data_add_alloc(datall, NULL, type, 0, NULL, NULL, 0, -1, name,
+                              txt_trim_space(unit), txt_trim_space(comment) );
 
       /* Put the number of this column into the status variable of the data
          structure. If the type is string, then also copy the width into
@@ -363,8 +364,8 @@ txt_info_from_first_row(char *line, gal_data_t **datall, 
int format)
              information). */
           if( *datall==NULL || format==TXT_FORMAT_TABLE )
             {
-              gal_data_add_to_ll(datall, NULL, GAL_TYPE_FLOAT64, 0,
-                                 NULL, NULL, 0, -1, NULL, NULL, NULL);
+              gal_list_data_add_alloc(datall, NULL, GAL_TYPE_FLOAT64, 0,
+                                      NULL, NULL, 0, -1, NULL, NULL, NULL);
               (*datall)->status=n;
             }
         }
@@ -464,7 +465,7 @@ txt_infoll_to_array(gal_data_t *datall, size_t *numdata)
       while(datall!=NULL)
         {
           /* Pop the top element. */
-          data=gal_data_pop_from_ll(&datall);
+          data=gal_list_data_pop(&datall);
 
           /* The `status' value is the number of the column (counting from
              1, not 0). */
@@ -840,13 +841,13 @@ txt_fill(char *line, char **tokens, size_t maxcolnum, 
gal_data_t *info,
 
 static gal_data_t *
 gal_txt_read(char *filename, size_t *dsize, gal_data_t *info,
-             struct gal_linkedlist_sll *indexll, int minmapsize, int format)
+             gal_list_sizet_t *indexll, int minmapsize, int format)
 {
   FILE *fp;
   char *line;
   char **tokens;
   gal_data_t *out=NULL;
-  struct gal_linkedlist_sll *ind;
+  gal_list_sizet_t *ind;
   size_t maxcolnum=0, rowind=0, lineno=0, ndim;
   size_t linelen=10;        /* `linelen' will be increased by `getline'. */
 
@@ -878,9 +879,9 @@ gal_txt_read(char *filename, size_t *dsize, gal_data_t 
*info,
         {
           ndim=1;
           maxcolnum = maxcolnum>ind->v+1 ? maxcolnum : ind->v+1;
-          gal_data_add_to_ll(&out, NULL, info[ind->v].type, ndim, dsize,
-                             NULL, 0, minmapsize, info[ind->v].name,
-                             info[ind->v].unit, info[ind->v].comment);
+          gal_list_data_add_alloc(&out, NULL, info[ind->v].type, ndim, dsize,
+                                  NULL, 0, minmapsize, info[ind->v].name,
+                                  info[ind->v].unit, info[ind->v].comment);
           out->disp_width=info[ind->v].disp_width;
           out->status=ind->v+1;
         }
@@ -944,7 +945,7 @@ gal_txt_read(char *filename, size_t *dsize, gal_data_t 
*info,
 
 gal_data_t *
 gal_txt_table_read(char *filename, size_t numrows, gal_data_t *colinfo,
-                   struct gal_linkedlist_sll *indexll, size_t minmapsize)
+                   gal_list_sizet_t *indexll, size_t minmapsize)
 {
   return gal_txt_read(filename, &numrows, colinfo, indexll, minmapsize,
                       TXT_FORMAT_TABLE);
@@ -959,7 +960,7 @@ gal_txt_image_read(char *filename, size_t minmapsize)
 {
   size_t numimg, dsize[2];
   gal_data_t *img, *imginfo;
-  struct gal_linkedlist_sll *indexll=NULL;
+  gal_list_sizet_t *indexll=NULL;
 
   /* Get the image information. */
   imginfo=gal_txt_image_info(filename, &numimg, dsize);
@@ -1136,14 +1137,14 @@ txt_print_value(FILE *fp, void *array, int type, size_t 
ind, char *fmt)
 
 static FILE *
 txt_open_file_write_info(gal_data_t *datall, char **fmts,
-                         struct gal_linkedlist_stll *comment,
-                         char *filename, int dontdelete)
+                         gal_list_str_t *comment, char *filename,
+                         int dontdelete)
 {
   FILE *fp;
   gal_data_t *data;
   char *tmp, *nstr;
   size_t i, j, num=0;
-  struct gal_linkedlist_stll *strt;
+  gal_list_str_t *strt;
   int nlen, nw=0, uw=0, tw=0, bw=0;
 
 
@@ -1228,8 +1229,8 @@ txt_open_file_write_info(gal_data_t *datall, char **fmts,
 
 
 void
-gal_txt_write(gal_data_t *datall, struct gal_linkedlist_stll *comment,
-              char *filename, int dontdelete)
+gal_txt_write(gal_data_t *datall, gal_list_str_t *comment, char *filename,
+              int dontdelete)
 {
   FILE *fp;
   char **fmts;
diff --git a/lib/wcs.c b/lib/wcs.c
index acc4b45..a8f6153 100644
--- a/lib/wcs.c
+++ b/lib/wcs.c
@@ -287,13 +287,13 @@ gal_wcs_warp_matrix(struct wcsprm *wcs)
           "`gal_wcs_array_from_wcsprm'", size*sizeof *out);
 
   /* Fill in the array. */
-  if(wcs->altlin |= 1)          /* Has a PCi_j array. */
+  if(wcs->altlin & 0x1)        /* Has a PCi_j array. */
     {
       for(i=0;i<wcs->naxis;++i)
         for(j=0;j<wcs->naxis;++j)
           out[i*wcs->naxis+j] = wcs->cdelt[i] * wcs->pc[i*wcs->naxis+j];
     }
-  else if(wcs->altlin |= 2)     /* Has CDi_j array */
+  else if(wcs->altlin & 0x2)     /* Has CDi_j array */
     {
       for(i=0;i<size;++i)
         out[i]=wcs->cd[i];
@@ -330,7 +330,7 @@ gal_wcs_decompose_pc_cdelt(struct wcsprm *wcs)
 
   /* The correction is only needed when the matrix is internally stored
      as PCi_j. */
-  if(wcs->altlin |= 1)
+  if(wcs->altlin & 1)
     {
       /* Get the pixel scale. */
       ps=gal_wcs_pixel_scale_deg(wcs);
diff --git a/tests/crop/wcspolygon.sh b/tests/crop/wcspolygon.sh
index 9999505..0fb694c 100755
--- a/tests/crop/wcspolygon.sh
+++ b/tests/crop/wcspolygon.sh
@@ -39,8 +39,16 @@ execname=../bin/$prog/ast$prog
 #
 #   - The input data was not made (for example the test that created the
 #     data file failed).
-if [ ! -f $execname ]; then exit 77; fi
-for fn in $img; do if [ ! -f $fn ]; then exit 77; fi; done
+if [ ! -f $execname ]; then
+    echo "$execname doesn't exist.";
+    exit 77;
+fi
+for fn in $img; do
+    if [ ! -f $fn ]; then
+        echo "$fn doesn't exist";
+        exit 77;
+    fi;
+done
 
 
 
@@ -48,5 +56,5 @@ for fn in $img; do if [ ! -f $fn ]; then exit 77; fi; done
 
 # Actual test script
 # ==================
-$execname $img --mode=wcs --zeroisnotblank --output=wcspolygon.fits           \
-          --polygon=0.99980497,1.0001967:0.998378,1.0012267:0.9999766,1.0013217
+$execname $img --mode=wcs --zeroisnotblank --output=wcspolygon.fits         \
+        --polygon=0.99980497,1.0001967:0.998378,1.0012267:0.9999766,1.0013217
diff --git a/tests/mkcatalog/simple.sh b/tests/mkcatalog/simple.sh
index 0ff05bd..62138e2 100755
--- a/tests/mkcatalog/simple.sh
+++ b/tests/mkcatalog/simple.sh
@@ -48,4 +48,5 @@ if [ ! -f $execname ] || [ ! -f $img ]; then exit 77; fi
 
 # Actual test script
 # ==================
-$execname $img --sn --upperlimitmag --magnitude --dec --ra --y --x
+$execname $img --x --y --ra --dec --magnitude --upperlimitmag --sn  \
+          --tableformat=txt



reply via email to

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