[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master 9256566: Updating doc, lib. check as scripts,
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master 9256566: Updating doc, lib. check as scripts, and lib. cleanup |
Date: |
Tue, 25 Apr 2017 22:16:50 -0400 (EDT) |
branch: master
commit 92565665db09d542b19a7f1acb0edabaf000f683
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
Updating doc, lib. check as scripts, and lib. cleanup
This work started with updating the documentation and in particular
starting to describe `gal_data_t'. As it progressed, several corrections
were made in the code and checks that are listed below. The documentation
work is not complete, but these changes are large enough to warrant a
commit.
- The library chapter of the book now has a "Library demo programs"
section that will have some simple programs to help users get started
with the libraries.
- The two functions `gal_data_alloc_number' and
`gal_data_string_fixed_alloc_size' were not used anywhere in Gnuastro
and not very generic, so they were removed. The one usage of the first
(in `gal_data_string_to_number') was replaced with an `mmap' call and
the second was moved into `lib/fits.c' as a static function.
- To be more clear (mainly motivated by the book), the first argument to
`gal_data_array_free' was changed to `dataarr' (previously it was just
`data').
- The library `multithread' check, now reads one of the images created
during `make check' and prints its values by multiple threads thus both
testing the reading of data into memory and the multithreaded
features. This new re-write now also uses the new high-level
`gal_threads_spin_off' function instead of the direct low-level usage of
pthreads libraries.
- Until now the actual library executable was tested (`check_PROGRAMS' was
one of the values in `TESTS' in `Makefile.am'). This would cause
problems when we wanted the library tests to depend on other tests: the
tests creating the dependencies would be run multiple times. So after
reviewing the "Scripts based testsuites", I noticed that we should
actually also build scripts to run the `check_PROGRAMS'
executables. This will allow them to also have their dependencies. So
the two `lib/versioncpp.sh' and `lib/multithread.sh' scripts were
created and are now in charge of testing the executables that are built.
---
doc/gnuastro.texi | 547 ++++++++++++++++++++++++++++++++++++++++++-----
lib/data.c | 133 ++----------
lib/fits.c | 54 ++++-
lib/gnuastro/data.h | 23 +-
lib/threads.c | 2 +-
tests/Makefile.am | 26 ++-
tests/lib/multithread.c | 160 ++++++--------
tests/lib/multithread.sh | 48 +++++
tests/lib/versioncpp.sh | 45 ++++
tests/prepconf.sh | 36 ++--
10 files changed, 762 insertions(+), 312 deletions(-)
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index f0286df..5273526 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -516,6 +516,7 @@ Libraries
* Review of library fundamentals:: Guide on libraries and linking.
* Gnuastro library:: Description of all library functions.
+* Library demo programs::
Review of library fundamentals
@@ -529,7 +530,9 @@ Gnuastro library
* Configuration information:: General information about library config.
* Library data container::
* Library data types::
+* Table input output::
* Arithmetic on datasets::
+* Tessellation library::
* Bounding box:: Finding the bounding box.
* FITS files:: Working with FITS data.
* Text files::
@@ -543,7 +546,8 @@ Gnuastro library
Data container (@file{data.h})
-* Data container type::
+* Generic data container::
+* Basic dataset functions::
FITS files (@file{fits.h})
@@ -555,6 +559,10 @@ Multithreaded programming (@file{threads.h})
* Implementation of pthread_barrier:: Some systems don't have pthread_barrier
* Gnuastro's thread related functions:: Functions for managing threads.
+Library demo programs
+
+* Library demo - reading a image::
+
Developing
* Why C:: Why Gnuastro is designed in C.
@@ -15846,6 +15854,7 @@ program} to easily define your own programs(s).
@menu
* Review of library fundamentals:: Guide on libraries and linking.
* Gnuastro library:: Description of all library functions.
+* Library demo programs::
@end menu
@node Review of library fundamentals, Gnuastro library, Libraries, Libraries
@@ -16475,7 +16484,7 @@ $ gnuastro-gcc myprog && ./myprog
@end example
address@hidden Gnuastro library, , Review of library fundamentals, Libraries
address@hidden Gnuastro library, Library demo programs, Review of library
fundamentals, Libraries
@section Gnuastro library
Gnuastro library's programming constructs (function declarations, macros,
@@ -16530,7 +16539,9 @@ documentation will correspond to your installed version.
* Configuration information:: General information about library config.
* Library data container::
* Library data types::
+* Table input output::
* Arithmetic on datasets::
+* Tessellation library::
* Bounding box:: Finding the bounding box.
* FITS files:: Working with FITS data.
* Text files::
@@ -16640,22 +16651,23 @@ mask images are integers using bit-wise flags to
identify certain classes
of special pixels, see @ref{Numeric data types}). Certain other information
about a dataset are also commonly necessary, for example the units of the
dataset, the name of the dataset and some comments. To deal with any
-generic dataset, Gnuastro defines the @code{gal_data_t} type.
+generic dataset, Gnuastro defines the @code{gal_data_t} as input or output.
@menu
-* Data container type::
+* Generic data container::
+* Basic dataset functions::
@end menu
address@hidden Data container type, , Library data container, Library data
container
address@hidden Data container type (@code{gal_data_t})
address@hidden Generic data container, Basic dataset functions, Library data
container, Library data container
address@hidden Generic data container (@code{gal_data_t})
-For a generic operation on any dataset (with various dimensions, numeric
-data types, units and higher-level structures), Gnuastro defines the
address@hidden type which is the main input/output of many Gnuastro's
-library functions. It is defined in @file{gnuastro/data.h}. If you will be
-using (address@hidden include}'ing) those libraries, you don't need to include
-this header explicity, it is already included by any library header that
-uses @code{gal_data_t}.
+To be able to deal with any dataset (various dimensions, numeric data
+types, units and higher-level structures), Gnuastro defines the
address@hidden type which is the input/output container of choice for
+many of Gnuastro library's functions. It is defined in
address@hidden/data.h}. If you will be using (address@hidden include}'ing) those
+libraries, you don't need to include this header explicity, it is already
+included by any library header that uses @code{gal_data_t}.
@deftp {Type (C @code{struct})} gal_data_t
The main container for datasets in Gnuastro. It can host data of any
@@ -16697,71 +16709,426 @@ typedef struct gal_data_t
@noindent
The list below contains a description for each @code{gal_data_t} element.
address@hidden @code{void *}
@table @code
@item void *restrict array
This is the pointer to the main array of the dataset containing the raw
data (values). All the other elements in this data-structure are actually
meta-data enabling us to use/understand the series of values in this
-array. Since it is to use data of any type, the array is actually a
address@hidden *} pointer. A @code{void *} array is not directly usable, you
-can use a procedure like the example below to use the array in any
-type. You can compile and run this program with the script described in
address@hidden linking script}
+array. It must allow data of any type (see @ref{Numeric data types}), so it
+is defined as a @code{void *} pointer. A @code{void *} array is not
+directly usable in C, so you have to cast it to proper type before using
+it, please see @ref{Library demo - reading a image} for a demonstration.
+
address@hidden @code{restrict}
address@hidden C: @code{restrict}
+The @code{restrict} keyword was formally introduced in C99 and is used to
+tell the compiler that at any moment only this pointer will modify what it
+points to (the a pixel in an image for example)@footnote{Also see
address@hidden://en.wikipedia.org/wiki/Restrict}.}. This extra piece of
+information can greatly help in compiler optimizations and thus the running
+time of the program. But older compilers might not have this capability, so
+at @command{./configure} time, Gnuastro checks this feature and if the
+user's compiler doesn't support @code{restrict}, it will be removed from
+this definition.
+
address@hidden Data type
address@hidden uint8_t type
+A fixed code (integer) used to identify the type of data in @code{array}
+(see @ref{Numeric data types}). For the list of acceptable values to this
+variable, please see @ref{Library data types}.
+
address@hidden size_t ndim
+The dataset's number of dimensions.
+
+
address@hidden Fortran
address@hidden FITS standard
address@hidden Standard, FITS
address@hidden size_t *dsize
+The size of the dataset along each dimension. This is an array (with
address@hidden elements), of positive integers in row-major
address@hidden see
address@hidden://en.wikipedia.org/wiki/Row-_and_column-major_order}.} (based
+on C). When a data file is read into memory with Gnuastro's libraries, this
+array is dynamically allocated based on the number of dimensions that the
+dataset has.
+
+It is important to remember that C's row-major ordering is the opposite of
+the FITS standard which is in column-major order: in the FITS standard the
+fastest dimension's size is specified by @code{NAXIS1}, and slower
+dimensions follow. The FITS standard was defined mainly based on the
+Fortran language which is the opposite of C's approach to multi-dimensional
+arrays (and also starts counting from 1 not 0). Hence if a FITS image has
address@hidden and @code{NAXIS2==50}, the @code{dsize} array must be
+filled with @code{dsize[0]==50} and @code{dsize[1]==20}.
+
+The fastest dimension is the one that is contiguous in memory: to increment
+by one along that dimension, just go to the next element in the array. As
+we go to slower dimensions, the number of memory cells we have to skip for
+an increment along that dimension becomes larger.
+
address@hidden size_t size
+The total number of elements in the dataset. This is actually a
+multiplication of all the values in the @code{dsize} array, so it is not an
+indepenent parameter. However, low-level operations with the dataset
+(irrespective of its dimensionality) commonly need this number, so this
+element is designed to avoid calculating it everytime.
+
address@hidden char *mmapname
+Name of file hosting the @code{mmap}'d contents of @code{array}. If the
+value of this variable is @code{NULL}, then the contents of @code{array}
+are actually stored in RAM, not in a file on the HDD/SSD. See the
+description of @code{minmapsize} below for more.
+
+If a file is used, it will be kept in the hidden @file{.gnuastro} directory
+with a randomly selected name to allow multiple arrays to be kept there at
+the same time. When @code{gal_data_free} is called the randomly named file
+will be deleted.
+
address@hidden size_t minmapsize
+The minimum size of an array (in bytes) to store the contents of
address@hidden as a file (on the non-volatile HDD/SSD), not in RAM. This can
+be very useful for large datasets which can be very memory intensive and
+the user's hardware RAM might not be sufficent to keep/process it. A random
+filename is assigned to the array which is available in the @code{mmapname}
+element of @code{gal_data_t} (above), see there for more.
+
+When this variable has a value of @code{0} (zero), any allocated
address@hidden will actually be in a file (not in RAM). When the value is
address@hidden (largest possible number in the unsigned types including
address@hidden) the array will be definitely allocated in RAM.
+
+Please note that using a non-volatile file instead of RAM will
+significantly increase the programs running time, especially on HDDs. So it
+is best to give this option very large values (depending on how much memory
+you will need for a given input). For example your processing might involve
+a copy of the the input (possibly to a wider data type which takes more
+bytes for each element), so take all such issues into
+consideration. @code{minmapsize} is actually stored in each
address@hidden, so it can be passed on to derivate datasets.
+
address@hidden nwcs
+The number of WCS coordinate representations (for WCSLIB).
+
address@hidden struct wcsprm *wcs
+The main WCSLIB structure keeping all the relevant information necessary
+for WCSLIB to do its processing and convert data-set positions into
+real-world positions. When it is given a @code{NULL} value, all posssible
+WCS calculations/measurements will be ignored.
+
address@hidden uint8_t flag
+Bit-wise flags to describe general properties of the dataset. The number of
+bytes available in this flag is stored in the @code{GAL_DATA_FLAG_SIZE}
+macro. Note that you should use bit-wise address@hidden
address@hidden://en.wikipedia.org/wiki/Bitwise_operations_in_C}.} to check
+these flags. The currently recognized bits are stored in these macros:
+
address@hidden @code
+
address@hidden Blank data
address@hidden GAL_DATA_FLAG_BLANK_CH
+Marking that the dataset has been checked for blank values. Therefore, the
+value of the bit in @code{GAL_DATA_FLAG_HASBLANK} is relibable. Without
+this bit, when a dataset doesn't have any blank values (and this has been
+checked), the @code{GAL_DATA_FLAG_HASBLANK} bit will be zero so a checker
+has no way to know if this zero is real or if no check has been done yet.
+
address@hidden GAL_DATA_FLAG_HASBLANK
+This bit has a value of @code{1} when the given dataset has blank
+values. If this bit is @code{0} and @code{GAL_DATA_FLAG_BLANK_CH} is
address@hidden, then the dataset has been checked and it didn't have any blank
+values, so there is no more need for further checks.
+
address@hidden GAL_DATA_FLAG_SORT_CH
+Marking that the dataset is already checked for being sorted or not and
+thus that the possible @code{0} values in @code{GAL_DATA_FLAG_SORTED_I} and
address@hidden are meaningful.
+
address@hidden GAL_DATA_FLAG_SORTED_I
+This bit has a value of @code{1} when the given dataset is sorted in an
+increasing manner. If this bit is @code{0} and @code{GAL_DATA_FLAG_SORT_CH}
+is @code{1}, then the dataset has been checked and wasn't sorted
+(increasing), so there is no more need for further checks.
+
address@hidden GAL_DATA_FLAG_SORTED_D
+This bit has a value of @code{1} when the given dataset is sorted in a
+decreasing manner. If this bit is @code{0} and @code{GAL_DATA_FLAG_SORT_CH}
+is @code{1}, then the dataset has been checked and wasn't sorted
+(decreasing), so there is no more need for further checks.
address@hidden table
+
+The macro @code{GAL_DATA_FLAG_MAXFLAG} contains the largest internally used
+bit-position. Higher-level flags can be defined with the bit-wise shift
+operators using this macro to define internal flags for libraries/programs
+that depend on Gnuastro without causing any possible conflict with the
+internal flags discussed above or having to check the values manually on
+every release.
+
+
address@hidden int status
+A context-specific status values for this data-structure. This integer will
+not be set by Gnuastro's libraries. You can use it keep some additional
+information about the dataset (with integer constants) depending on your
+applications.
+
address@hidden char *name
+The name of the dataset. If the dataset is a multi-dimensional array and
+read/written as a FITS image, this will be the value in the @code{EXTNAME}
+FITS keyword. If the dataset is a one-dimensional table column, this will
+be the column name. If it is set to @code{NULL} (by default), it will be
+ignored.
+
address@hidden char *unit
+The units of the dataset (for example @code{BUNIT} in the standard FITS
+keywords) that will be read from or written to files/tables along with the
+dataset. If it is set to @code{NULL} (by default), it will be ignored.
+
address@hidden char *comment
+Any further explanation about the dataset which will be written to any
+output file if present.
+
address@hidden disp_fmt
+Format to use for printing each element of the dataset to a plain text
+file, the acceptable values to this element are defined in @ref{Table input
+output}. Based on C's @code{printf} standards.
+
address@hidden disp_width
+Width of printing each element of the dataset to a plain text file, the
+acceptable values to this element are defined in @ref{Table input
+output}. Based on C's @code{printf} standards.
+
address@hidden disp_precision
+Width of printing each element of the dataset to a plain text file, the
+acceptable values to this element are defined in @ref{Table input
+output}. Based on C's @code{printf} standards.
+
address@hidden gal_data_t *next
+Through this pointer, you can link a @code{gal_data_t} with other datasets
+related datasets, for example the different columns in a dataset each have
+one @code{gal_data_t} associate with them and they are linked to each other
+using this element. There are several functions described below to
+facilitate using @code{gal_data_t} as a linked list. See @ref{Linked lists}
+for more on these wonderful high-level constructs.
+
address@hidden gal_data_t *block
+Pointer to the start of the complete allocated block of memory. When this
+pointer is not @code{NULL}, the dataset is not treated as a contiguous
+patch of memory. Rather, it is seen as covering only a portion of the
+larger patch of memory that @code{block} points to.
+
+In many contexts, it is desirable to slice the dataset into subsets or
+tiles (not necessarily overlapping). In such a way that you can work on
+each tile independently. One method would be to copy that region to a
+separate allocated space, but in many contexts this isn't necessary and
+infact can be a big burden on CPU/Memory usage. The @code{block} pointer in
address@hidden is defined for such situations: where allocation is not
+necessary. You just want to read the data or write to it independently (or
+in coordination with) other regions of the dataset. Added with parallel
+processing, this can greatly improve the time/memory consumption.
+
+See the figure below for example: assume the @code{larger} dataset is a
+contiguous block of memory that you are interpretting as a 2D array. But
+you only want to work on the smaller @code{tile} region.
@example
-#include <stdio.h>
-#include <stdlib.h>
-#include <gnuastro/fits.h>
-#include <gnuastro/statistics.h>
+ larger
+ ---------------------------------
+ | |
+ | tile |
+ | ---------- |
+ | | | |
+ | |_ | |
+ | |*| | |
+ | ---------- |
+ | tile->block = larger |
+ |_ |
+ |*| |
+ ---------------------------------
address@hidden example
-int
-main(void)
address@hidden
- size_t i;
- float *farray;
- double sum=0.0f;
- gal_data_t *image;
- char *filename="img.fits", *hdu="1";
+To use @code{gal_data_t}'s @code{block} concept, you allocate a
address@hidden *tile} which is initialized with the pointer to the first
+element in the sub-array (as its @code{array} argument). Note that this is
+not necessarily the first element in the larger array. You can set the size
+of the tile along with the initialization as you please. Recall that, when
+given a address@hidden pointer as @code{array}, @code{gal_data_initialize}
+(and thus @code{gal_data_alloc}) do not allocate any space and just uses
+the given pointer for the new @code{array} element of the
address@hidden So your @code{tile} data structure will not be pointing
+to a separately allocated space.
+
+After the allocation is done, you just point @code{tile->block} to the
address@hidden dataset which hosts the full block of memory. Gnuastro's
+library will check the @code{block} pointer of their input dataset to see
+how to deal with dimensions and increments so they can always remain within
+the tile, see @ref{Tessellation library}.
+
+Since the block structure is defined as a pointer, arbitrary levels of
+tesselation/griding are possible (@code{tile->block} may itself be a tile
+in an even larger allocated space). Therefore, just like a linked-list (see
address@hidden lists}), it is important to have the @code{block} pointer of
+the largest dataset set to @code{NULL}. Normally, you won't have to worry
+about this, because @code{gal_data_initialize} (and thus
address@hidden) will set the @code{block} element to @code{NULL} by
+default (just remember not to change it). You can then only change the
address@hidden element for the tiles you define over the allocated space.
+
+The functions in @ref{Tessellation library} are defined to help you most
+effectively use/check/define a tessellation or tiles. This approach to
+dealing with parts of a larger block was inspired from the way the GNU
+Scientific Library (GSL) does it in its ``Vectors and Matrices'' chapter.
- /* Read `img.fits' (HDU: 1) as a float32 array. */
- image=gal_fits_img_read_to_type(filename, hdu,
- GAL_TYPE_FLOAT32, -1);
address@hidden table
- /* Use the allocated space as a single precision floating
- * point array (recall that `image->array' has `void *'
- * type, so it is not directly usable. */
- farray=image->array;
- /* Calculate the sum of all the values. */
- for(i=0; i<image->size; ++i)
- sum += farray[i];
address@hidden Basic dataset functions, , Generic data container, Library data
container
address@hidden Basic dataset functions
- /* Report the sum. */
- printf("Sum of values in %s (hdu %s) is: %f\n",
- filename, hdu, sum);
+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.
- /* Clean up and return. */
- gal_data_free(image);
- return EXIT_SUCCESS;
address@hidden
address@hidden example
address@hidden 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
+all dimensions. This function will also return @code{1} when the number of
+dimensions of the two datasets are different.
address@hidden deftypefun
address@hidden table
address@hidden {void *} gal_data_ptr_increment (void @code{*pointer}, size_t
@code{increment}, uint8_t @code{type})
+Return a pointer to an element that is @code{increment} elements ahead of
address@hidden, assuming each element has type of @code{type} (for the type
+codes, see @ref{Library data types}).
+
+When working with the @code{array} elements of @code{gal_data_t}, we are
+actually dealing with @code{void *} pointers. However, pointer arithmetic
+doesn't apply to @code{void *}, because the system doesn't know how many
+bytes there are in each element to increment the pointer respectively. This
+function will use the given @code{type} to calculate where the incremented
+element is located in memory.
address@hidden deftypefun
+
address@hidden size_t gal_data_ptr_dist (void @code{*earlier}, void
@code{*later}, uint8_t @code{type})
+Return the number of elements between @code{earlier} and @code{later}
+assuming each element has a type defined by @code{type} (for the type
+codes, see @ref{Library data types}).
address@hidden deftypefun
+
address@hidden {void *} gal_data_malloc_array (uint8_t @code{type}, size_t
@code{size})
+Allocate an array of type @code{type} with @code{size} elements in RAM (for
+the type codes, see @ref{Library data types}). This is effectively just a
+wrapper around C's @code{malloc} function but takes Gnuastro's integer type
+codes and will also abort with an error if there the allocation was not
+successful.
address@hidden deftypefun
+
address@hidden {void *} gal_data_calloc_array (uint8_t @code{type}, size_t
@code{size})
+Allocate and clear (initialize to zero) an array of type @code{type} with
address@hidden elements in RAM (for the type codes, see @ref{Library data
+types}). This is effectively just a wrapper around C's @code{calloc}
+function but takes Gnuastro's integer type codes and will also abort with
+an error if there the allocation was not successful.
address@hidden deftypefun
+
address@hidden void gal_data_initialize (gal_data_t @code{*data}, void
@code{*array}, uint8_t @code{type}, size_t @code{ndim}, size_t @code{*dsize},
struct wcsprm @code{*wcs}, int @code{clear}, size_t @code{minmapsize}, char
@code{*name}, char @code{*unit}, char @code{*comment})
+
+Initialize the given data structure (@code{data}) with all the given
+values. Note that the raw input @code{gal_data_t} must already have been
+allocated before calling this function. For a description of each variable
+see @ref{Generic data container}. It will set the values and do the
+necessary allocations. If they aren't @code{NULL}, all input arrays
+(@code{dsize}, @code{wcs}, @code{name}, @code{unit}, @code{comment}) are
+separately copied (allocated) by this function for usage in @code{data}, so
+you can safely use one value to initialize many datasets or use statically
+allocated variables in this function call. Once you are done with the
+dataset, you can clean all the allocated spaces with
address@hidden
+
+If @code{array} is not @code{NULL}, it will be directly copied into
address@hidden>array} and no new space will be allocated for the array of this
+dataset, this has many low-level advantages and can be used to work on
+regions of a dataset instead of the whole allocated array (see the
+description under @code{block} in @ref{Generic data container} for one
+example). If the given pointer is not the start of an allocated block of
+memory or it is used in multiple datasets, be sure to set it to @code{NULL}
+(with @code{data->array=NULL}) before cleaning up with
address@hidden
address@hidden deftypefun
+
address@hidden {void *} gal_data_alloc (void @code{*array}, uint8_t
@code{type}, size_t @code{ndim}, size_t @code{*dsize}, struct wcsprm
@code{*wcs}, int @code{clear}, size_t @code{minmapsize}, char @code{*name},
char @code{*unit}, char @code{*comment})
+
+Dynamically allocate a @code{gal_data_t} and initialize it will all the
+given values. See the description of @code{gal_data_initialize} and
address@hidden data container} for more information. This function will often
+be the most frequently used because it allocates the @code{gal_data_t}
+hosting all the values @emph{and} initializes it. Once you are done with
+the dataset, be sure to clean up all the allocated spaces with
address@hidden
address@hidden deftypefun
+
address@hidden void gal_data_free_contents (gal_data_t @code{*data})
+Free all the address@hidden pointers in @code{gal_data_t}, for a complete
+description of the @code{gal_data_t} contents, see @ref{Generic data
+container}.
address@hidden deftypefun
+
address@hidden void gal_data_free (gal_data_t @code{*data})
+Free all the address@hidden pointers in @code{gal_data_t}, then free the
+actual data structure.
address@hidden 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 {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}.
address@hidden
+size_t i;
+gal_data_t *dataarr;
+dataarr=gal_data_array_calloc(10);
+for(i=0;i<10;++i) gal_data_initialize(&dataarr[i], ...);
+...
+gal_data_array_free(dataarr, 10, 1);
address@hidden example
address@hidden deftypefun
address@hidden Library data types, Arithmetic on datasets, Library data
container, Gnuastro library
address@hidden void gal_data_array_free (gal_data_t @code{*dataarr}, size_t
@code{num}, int @code{free_array})
+Free all the @code{num} elements within @code{dataarr} and the actual
+allocated array. If @code{free_array} is not zero, then the @code{array}
+element of all the datasets will also be freed, see @ref{Generic data
+container}.
address@hidden deftypefun
+
address@hidden Library data types, Table input output, Library data container,
Gnuastro library
@subsection Library data types (@file{type.h})
This header defines basic type identifiers and functions relating to the
different types.
address@hidden Arithmetic on datasets, Bounding box, Library data types,
Gnuastro library
address@hidden Table input output, Arithmetic on datasets, Library data types,
Gnuastro library
address@hidden Table input output (@file{table.h})
+
+Functions to read columns from/to tables.
+
address@hidden Arithmetic on datasets, Tessellation library, Table input
output, Gnuastro library
@subsection Arithmetic on datasets (@file{arithmetic.h})
address@hidden Tessellation library, Bounding box, Arithmetic on datasets,
Gnuastro library
address@hidden Tessellation library (@file{tile.h})
address@hidden Bounding box, FITS files, Arithmetic on datasets, Gnuastro
library
+
address@hidden Bounding box, FITS files, Tessellation library, Gnuastro library
@subsection Bounding box (@file{box.h})
Functions related to reporting a the bounding box of certain inputs are
@@ -18222,6 +18589,82 @@ 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
+
+In this final section of @ref{Libraries}, 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
address@hidden linking script}. If you don't have any FITS file to
+experiment on, you can use those that are generated by Gnuastro after
address@hidden check} in the @file{tests/} directory, see @ref{Quick start}.
+
+
address@hidden
+* Library demo - reading a image::
address@hidden menu
+
address@hidden Library demo - reading a image, , Library demo programs,
Library demo programs
address@hidden Library demo - reading a FITS image
+
+The following simple program demonstrates how to read a FITS image into
+memory and use the @code{void *array} pointer in of @ref{Generic data
+container}. For easy linking/compilation of this program along with a first
+run see @ref{Automatic linking script}. Before running, also change the
address@hidden and @code{hdu} variable values to specify an existing FITS
+file and/or extension/HDU.
+
+This is just intended to demonstrate how to use the @code{array} pointer of
address@hidden Hence it doesn't do important sanity checks, for example
+in real datasets you may also have blank pixels. In such cases, this
+program will return a NaN value (see @ref{Blank pixels}). So for general
+statistical information of a dataset, it is much better to use Gnuastro's
address@hidden program which can deal with blank pixels any many other
+issues in a generic dataset.
+
address@hidden
+#include <stdio.h>
+#include <stdlib.h>
+#include <gnuastro/fits.h> /* includes gnuastro's data.h and type.h */
+#include <gnuastro/statistics.h>
+
+int
+main(void)
address@hidden
+ size_t i;
+ float *farray;
+ double sum=0.0f;
+ gal_data_t *image;
+ char *filename="img.fits", *hdu="1";
+
+
+ /* Read `img.fits' (HDU: 1) as a float32 array. */
+ image=gal_fits_img_read_to_type(filename, hdu, GAL_TYPE_FLOAT32, -1);
+
+
+ /* Use the allocated space as a single precision floating
+ * point array (recall that `image->array' has `void *'
+ * type, so it is not directly usable. */
+ farray=image->array;
+
+
+ /* Calculate the sum of all the values. */
+ for(i=0; i<image->size; ++i)
+ sum += farray[i];
+
+
+ /* Report the sum. */
+ printf("Sum of values in %s (hdu %s) is: %f\n",
+ filename, hdu, sum);
+
+
+ /* Clean up and return. */
+ gal_data_free(image);
+ return EXIT_SUCCESS;
address@hidden
address@hidden example
+
diff --git a/lib/data.c b/lib/data.c
index 1b7d766..7795152 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -162,62 +162,6 @@ gal_data_calloc_array(uint8_t type, size_t size)
-/* Allocate space for one blank value of the given type and put the value
- in it. */
-void *
-gal_data_alloc_number(uint8_t type, void *number)
-{
- void *allocd;
-
- /* Allocate the space for the blank value: */
- allocd=gal_data_malloc_array(type, 1);
-
- /* Put the blank value into it. */
- errno=0;
- switch(type)
- {
- case GAL_TYPE_BIT:
- error(EXIT_FAILURE, 0, "Currently Gnuastro doesn't support blank "
- "values for `GAL_TYPE_BIT', please get in touch with "
- "us to see how we can implement it.");
-
- case GAL_TYPE_UINT8: *(uint8_t *)allocd = *(uint8_t *) number; break;
- case GAL_TYPE_INT8: *(int8_t *)allocd = *(int8_t *) number; break;
- case GAL_TYPE_UINT16: *(uint16_t *)allocd = *(uint16_t *) number; break;
- case GAL_TYPE_INT16: *(int16_t *)allocd = *(int16_t *) number; break;
- case GAL_TYPE_UINT32: *(uint32_t *)allocd = *(uint32_t *) number; break;
- case GAL_TYPE_INT32: *(int32_t *)allocd = *(int32_t *) number; break;
- case GAL_TYPE_UINT64: *(uint64_t *)allocd = *(uint64_t *) number; break;
- case GAL_TYPE_INT64: *(int64_t *)allocd = *(int64_t *) number; break;
- case GAL_TYPE_FLOAT32: *(float *)allocd = *(float *) number; break;
- case GAL_TYPE_FLOAT64: *(double *)allocd = *(double *) number; break;
-
- case GAL_TYPE_COMPLEX32:
- GSL_COMPLEX_P_REAL(((gsl_complex_float *)allocd)) =
- GSL_COMPLEX_P_REAL(((gsl_complex_float *)number));
- GSL_COMPLEX_P_IMAG(((gsl_complex_float *)allocd)) =
- GSL_COMPLEX_P_IMAG(((gsl_complex_float *)number));
- break;
-
- case GAL_TYPE_COMPLEX64:
- GSL_COMPLEX_P_REAL(((gsl_complex *)allocd)) =
- GSL_COMPLEX_P_REAL(((gsl_complex *)number));
- GSL_COMPLEX_P_IMAG(((gsl_complex *)allocd)) =
- GSL_COMPLEX_P_IMAG(((gsl_complex *)number));
- break;
-
- default:
- error(EXIT_FAILURE, 0, "type value of %d not recognized in "
- "`gal_data_alloc_number'", type);
- }
-
- return allocd;
-}
-
-
-
-
-
static void
gal_data_mmap(gal_data_t *data, int clear)
{
@@ -413,60 +357,6 @@ gal_data_alloc(void *array, uint8_t type, size_t ndim,
size_t *dsize,
-/* In some contexts, it is necessary for all the strings to have the same
- allocated space (when the `strlen' is different). This function will
- allocate new copies for all elements to have the same length as the
- maximum length and set all trailing elements to `\0' for those that are
- shorter than the length. The return value is the allocated space. If the
- dataset is not a string, the returned value will be -1 (largest number
- of `size_t'). */
-size_t
-gal_data_string_fixed_alloc_size(gal_data_t *data)
-{
- size_t i, j, maxlen=0;
- char *tmp, **strarr=data->array;
-
- /* Return 0 if the dataset is not a string. */
- if(data->type!=GAL_TYPE_STRING)
- return -1;
-
- /* Get the maximum length. */
- for(i=0;i<data->size;++i)
- maxlen = strlen(strarr[i])>maxlen ? strlen(strarr[i]) : maxlen;
-
- /* For all elements, check the length and if they aren't equal to maxlen,
- then allocate a maxlen sized array and put the values in. */
- for(i=0;i<data->size;++i)
- {
- /* Allocate (and clear) the space for the new string. We want it to
- be cleared, so when the strings are smaller, the rest of the space
- is filled with '\0' (ASCII for 0) values.*/
- errno=0;
- tmp=calloc(maxlen+1, sizeof *strarr[i]);
- if(tmp==NULL)
- error(EXIT_FAILURE, 0, "%zu bytes for tmp in "
- "`gal_data_fixed_alloc_size_for_string'",
- maxlen+1*sizeof *strarr[i]);
-
- /* Put the old array into the newly allocated space. `tmp' was
- cleared (all values set to `\0', so we don't need to set the final
- one explicity after the copy.*/
- for(j=0;strarr[i][j]!='\0';++j)
- tmp[j]=strarr[i][j];
-
- /* Free the old array and put in the new one. */
- free(strarr[i]);
- strarr[i]=tmp;
- }
-
- /* Return the allocated space. */
- return maxlen+1;
-}
-
-
-
-
-
/* Free the allocated contents of a data structure, not the structure
itsself. The reason that this function is separate from `gal_data_free'
is that the data structure might be allocated as an array (statically
@@ -603,26 +493,26 @@ gal_data_array_calloc(size_t size)
/* When you have an array of data structures. */
void
-gal_data_array_free(gal_data_t *data, size_t size, int free_array)
+gal_data_array_free(gal_data_t *dataarr, size_t size, int free_array)
{
size_t i;
/* If its NULL, don't do anything. */
- if(data==NULL) return;
+ if(dataarr==NULL) return;
/* First free all the contents. */
for(i=0;i<size;++i)
{
/* See if the array should be freed or not. */
if(free_array==0)
- data[i].array=NULL;
+ dataarr[i].array=NULL;
/* Now clear the contents of the dataset. */
- gal_data_free_contents(&data[i]);
+ gal_data_free_contents(&dataarr[i]);
}
/* Now you can free the whole array. */
- free(data);
+ free(dataarr);
}
@@ -1363,10 +1253,11 @@ gal_data_write_to_string(void *ptr, uint8_t type, int
quote_if_str_has_space)
gal_data_t *
gal_data_string_to_number(char *string)
{
- size_t dsize[1]={1};
+ void *ptr;
+ gal_data_t *out;
int fnz=-1, lnz=0; /* `F'irst (or `L'ast) `N'on-`Z'ero. */
- void *ptr, *numarr;
char *tailptr, *cp;
+ size_t dsize[1]={1};
uint8_t type, forcedfloat=0;
/* Define initial spaces to keep the value. */
@@ -1436,10 +1327,10 @@ gal_data_string_to_number(char *string)
{ ptr=&d; type=GAL_TYPE_FLOAT64; }
}
- /* Return the pointer to the data structure. */
- numarr=gal_data_alloc_number(type, ptr);
- return gal_data_alloc(numarr, type, 1, dsize, NULL, 0, -1,
- NULL, NULL, NULL);
+ /* Allocate a one-element dataset, then copy the number into it. */
+ out=gal_data_alloc(NULL, type, 1, dsize, NULL, 0, -1, NULL, NULL, NULL);
+ memcpy(out->array, ptr, gal_type_sizeof(type));
+ return out;
}
diff --git a/lib/fits.c b/lib/fits.c
index e3a56f4..31834a2 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -2099,6 +2099,58 @@ gal_fits_tab_read(char *filename, char *hdu, size_t
numrows,
+/* This function will allocate new copies for all elements to have the same
+ length as the maximum length and set all trailing elements to `\0' for
+ those that are shorter than the length. The return value is the
+ allocated space. If the dataset is not a string, the returned value will
+ be -1 (largest number of `size_t'). */
+static size_t
+fits_string_fixed_alloc_size(gal_data_t *data)
+{
+ size_t i, j, maxlen=0;
+ char *tmp, **strarr=data->array;
+
+ /* Return 0 if the dataset is not a string. */
+ if(data->type!=GAL_TYPE_STRING)
+ return -1;
+
+ /* Get the maximum length. */
+ for(i=0;i<data->size;++i)
+ maxlen = strlen(strarr[i])>maxlen ? strlen(strarr[i]) : maxlen;
+
+ /* For all elements, check the length and if they aren't equal to maxlen,
+ then allocate a maxlen sized array and put the values in. */
+ for(i=0;i<data->size;++i)
+ {
+ /* Allocate (and clear) the space for the new string. We want it to
+ be cleared, so when the strings are smaller, the rest of the space
+ is filled with '\0' (ASCII for 0) values.*/
+ errno=0;
+ tmp=calloc(maxlen+1, sizeof *strarr[i]);
+ if(tmp==NULL)
+ error(EXIT_FAILURE, 0, "%zu bytes for tmp in "
+ "`gal_data_fixed_alloc_size_for_string'",
+ maxlen+1*sizeof *strarr[i]);
+
+ /* Put the old array into the newly allocated space. `tmp' was
+ cleared (all values set to `\0', so we don't need to set the final
+ one explicity after the copy.*/
+ for(j=0;strarr[i][j]!='\0';++j)
+ tmp[j]=strarr[i][j];
+
+ /* Free the old array and put in the new one. */
+ free(strarr[i]);
+ strarr[i]=tmp;
+ }
+
+ /* Return the allocated space. */
+ return maxlen+1;
+}
+
+
+
+
+
static void
fits_table_prepare_arrays(gal_data_t *cols, size_t numcols, int tabletype,
char ***outtform, char ***outttype,
@@ -2195,7 +2247,7 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t
numcols, int tabletype,
/* If this is a string column, set all the strings to same size,
then write the value of tform depending on the type. */
- col->disp_width=gal_data_string_fixed_alloc_size(col);
+ col->disp_width=fits_string_fixed_alloc_size(col);
fmt[0]=gal_fits_type_to_bin_tform(col->type);
if( col->type==GAL_TYPE_STRING )
asprintf(&tform[i], "%d%c", col->disp_width, fmt[0]);
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index 4b29476..205032a 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -72,10 +72,10 @@ __BEGIN_C_DECLS /* From C++ preparations */
/* Number of bytes in the unsigned integer hosting the bit-flags (`flag'
element) of `gal_data_t'. */
-#define GAL_DATA_FLAG_SIZE 1
+#define GAL_DATA_FLAG_SIZE 1
/* Bit 0: The has-blank flag has been checked, so a flag value of 0 for the
- blank flag is strustable. This can be very useful to avoid
+ blank flag is trustable. This can be very useful to avoid
repetative checks when the necessary value of the bit is 0. */
#define GAL_DATA_FLAG_BLANK_CH 0x1
@@ -91,10 +91,11 @@ __BEGIN_C_DECLS /* From C++ preparations */
/* Bit 4: Dataset is sorted and decreasing. */
#define GAL_DATA_FLAG_SORTED_D 0x10
-/* Maximum internal flag value, using bitwise shift operators, this can
- be used to define internal flags for libraries/programs that depend
- on Gnuastro without causing any conflict with the internal flags or
- having to check the values manually on every release. */
+/* Maximum internal flag value. Higher-level flags can be defined with the
+ bitwise shift operators on this value to define internal flags for
+ libraries/programs that depend on Gnuastro without causing any possible
+ conflict with the internal flags or having to check the values manually
+ on every release. */
#define GAL_DATA_FLAG_MAXFLAG GAL_DATA_FLAG_SORTED_D
@@ -197,7 +198,7 @@ typedef struct gal_data_t
{
/* Basic information on array of data. */
void *restrict array; /* Array keeping data elements. */
- uint8_t type; /* Type of data (from `gal_data_alltypes'). */
+ uint8_t type; /* Type of data (see `gnuastro/type.h'). */
size_t ndim; /* Number of dimensions in the array. */
size_t *dsize; /* Size of array along each dimension. */
size_t size; /* Total number of data-elements. */
@@ -247,9 +248,6 @@ gal_data_malloc_array(uint8_t type, size_t size);
void *
gal_data_calloc_array(uint8_t type, size_t size);
-void *
-gal_data_alloc_number(uint8_t type, void *number);
-
void
gal_data_initialize(gal_data_t *data, void *array, uint8_t type, size_t ndim,
size_t *dsize, struct wcsprm *wcs, int clear,
@@ -260,9 +258,6 @@ gal_data_alloc(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);
-size_t
-gal_data_string_fixed_alloc_size(gal_data_t *data);
-
void
gal_data_free_contents(gal_data_t *data);
@@ -280,7 +275,7 @@ gal_data_t *
gal_data_array_calloc(size_t size);
void
-gal_data_array_free(gal_data_t *data, size_t num, int free_array);
+gal_data_array_free(gal_data_t *dataarr, size_t num, int free_array);
diff --git a/lib/threads.c b/lib/threads.c
index b72a077..a4d99ef 100644
--- a/lib/threads.c
+++ b/lib/threads.c
@@ -274,7 +274,7 @@ gal_threads_attr_barrier_init(pthread_attr_t *attr,
pthread_barrier_t *b,
int value1;
double value2;
float *array;
- }
+ };
--------- Function to run on each thread ---------
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6b9a8c1..3d7db21 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -177,6 +177,7 @@ AM_CPPFLAGS = -I../lib
# Environment variables for the test scripts.
AM_TESTS_ENVIRONMENT = \
+export mkdir_p="$(MKDIR_P)"; \
export topsrc=$(top_srcdir); \
export haslibjpeg=$(MAYBE_HASLIBJPEG); \
export hasghostscript=$(MAYBE_HASGHOSTSCRIPT);
@@ -185,21 +186,32 @@ export hasghostscript=$(MAYBE_HASGHOSTSCRIPT);
-# Compilations that are to be done with `make check'.
+# Library checks
+# ==============
+#
+# The Gnuastro library is checked by compiling programs and linking them
+# with the library. As described in the last paragraph of the "Scripts
+# based test suites" section of the Automake manual, all targets specified
+# by `check_PROGRAMS' are compiled prior to actually running the targets of
+# `TESTS'. So they do not need to be specified as any dependency, they will
+# be present when the `.sh' based tests are run.
LDADD = -lgnuastro
check_PROGRAMS = versioncpp multithread
versioncpp_SOURCES = lib/versioncpp.cpp
multithread_SOURCES = lib/multithread.c
+lib/multithread.sh: mkprof/mosaic1.sh.log
-# The actual test scripts that are run:
-TESTS = prepconf.sh $(check_PROGRAMS) $(MAYBE_ARITHMETIC_TESTS)
\
- $(MAYBE_CONVERTT_TESTS) $(MAYBE_CONVOLVE_TESTS) $(MAYBE_COSMICCAL_TESTS) \
- $(MAYBE_CROP_TESTS) $(MAYBE_FITS_TESTS) $(MAYBE_MKCATALOG_TESTS) \
- $(MAYBE_MKNOISE_TESTS) $(MAYBE_MKPROF_TESTS) $(MAYBE_NOISECHISEL_TESTS) \
- $(MAYBE_STATISTICS_TESTS) $(MAYBE_SUBTRACTSKY_TESTS) \
+# Final Tests
+# ===========
+TESTS = prepconf.sh lib/versioncpp.sh lib/multithread.sh \
+ $(MAYBE_ARITHMETIC_TESTS) $(MAYBE_CONVERTT_TESTS) \
+ $(MAYBE_CONVOLVE_TESTS) $(MAYBE_COSMICCAL_TESTS) $(MAYBE_CROP_TESTS) \
+ $(MAYBE_FITS_TESTS) $(MAYBE_MKCATALOG_TESTS) $(MAYBE_MKNOISE_TESTS) \
+ $(MAYBE_MKPROF_TESTS) $(MAYBE_NOISECHISEL_TESTS) \
+ $(MAYBE_STATISTICS_TESTS) $(MAYBE_SUBTRACTSKY_TESTS) \
$(MAYBE_TABLE_TESTS) $(MAYBE_WARP_TESTS)
diff --git a/tests/lib/multithread.c b/tests/lib/multithread.c
index 13f1b95..1043a41 100644
--- a/tests/lib/multithread.c
+++ b/tests/lib/multithread.c
@@ -4,7 +4,7 @@ A test program to multithreaded building using Gnuastro's
helpers.
Original author:
Mohammad Akhlaghi <address@hidden>
Contributing author(s):
-Copyright (C) 2016, Free Software Foundation, Inc.
+Copyright (C) 2017, 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
@@ -22,134 +22,102 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <stdio.h>
#include <stdlib.h>
+#include "gnuastro/fits.h"
#include "gnuastro/threads.h"
-/* The params structure will keep the input information for each thread. As
- you see below, we will actually be defining an array of these
- structures, one for each thread. The reason for this is that the
- function that spins off threads only passes one argument, so as that
- argument, we will be passing the pointer to this structure. You can
- easily add new elements to this structure to use in the threads
- function. */
+/* This structure can keep all information you want to pass onto the worker
+ function on each thread. */
struct params
{
- size_t id; /* Id of this thread. */
- size_t *indexs; /* Indexes of actions to be done in this thread. */
- pthread_barrier_t *b; /* Pointer the barrier for all threads. */
+ gal_data_t *image; /* Dataset to print values of. */
};
-
-/* Worker function on threads */
+/* This is the main worker function which will be called by the different
+ threads. `gal_threads_params' is defined in `gnuastro/threads.h' and
+ contains the pointer to the paramter we want. Note that its input and
+ output must have `void *' types. */
void *
-worker(void *inparam)
+worker_on_thread(void *in_prm)
{
- /* The first thing to do is to say what the input pointer actually is. */
- struct params *prm=(struct params*)inparam;
+ /* Low-level definitions to be done first. */
+ struct gal_threads_params *tprm=(struct gal_threads_params *)in_prm;
+ struct params *p=(struct params *)tprm->params;
+
+
+ /* Subsequent definitions. */
+ float *array=p->image->array;
+ size_t i, index, *dsize=p->image->dsize;
- /* Now you can go onto do defining the function like any other
- function: first you define the variables and so on... */
- size_t i;
- /* Go over the jobs indexed for this thread: */
- for(i=0; prm->indexs[i] != GAL_BLANK_SIZE_T; ++i)
+ /* Go over all the pixels that were assigned to this thread. */
+ for(i=0; tprm->indexs[i] != GAL_BLANK_SIZE_T; ++i)
{
- /* The indexes of the actions will make it possible to point to
- whatever data structure or input you want. So in this test, we
- will just print the thread ID and action id. */
- printf("thread %zu: %zu\n", prm->id, prm->indexs[i]);
+ /* For easy reading. */
+ index = tprm->indexs[i];
+
+
+ /* Print the information. */
+ printf("(%zu, %zu) on thread %zu: %g\n", index%dsize[1]+1,
+ index/dsize[1]+1, tprm->id, array[index]);
}
- /* Wait until all other threads finish. When there was only one thread,
- we explicitly set the pointer to the barrier structure to NULL, so
- only wait when a barrier is actually defined.*/
- if(prm->b)
- pthread_barrier_wait(prm->b);
- /* Return the NULL pointer. */
+ /* Wait for all the other threads to finish, then return. */
+ if(tprm->b) pthread_barrier_wait(tprm->b);
return NULL;
}
-/* This is the thread spinner function. */
+/* A simple program to open a FITS image, distributes its pixels between
+ different threads and print the value of each pixel and the thread it
+ was assigned to, this will test both the opening of a FITS file and also
+ the multi-threaded functions. After running `make check' you can see the
+ outputs in `tests/multithread.log'.
+
+ Please run the following command for an explanation on easily linking
+ and compiling C programs that use Gnuastro's libraries (without having
+ to worry about the libraries to link to) anywhere on your system:
+
+ $ info gnuastro "Automatic linking script"
+*/
int
main(void)
{
- int err;
- pthread_t t; /* All thread ids saved in this, not used. */
- struct params *prm;
- size_t numbarriers;
- pthread_attr_t attr;
- pthread_barrier_t b;
- size_t i, *indexs, thrdcols;
- size_t numthreads=8, numactions=1000;
-
- /* Allocate the array of `param' structures. Note that in most cases, the
- number of threads will not be a constant like this simple case, it
- will be a variable passed to the thread-spinner. So we are using
- dynamic allocation for more general use as a tutorial. */
- prm=malloc(numthreads*sizeof *prm);
- if(prm==NULL)
+ struct params p;
+ char *filename="psf.fits", *hdu="1";
+ size_t numthreads=gal_threads_number();
+
+
+ /* Read the image into memory as a float32 data type. */
+ p.image=gal_fits_img_read_to_type(filename, hdu, GAL_TYPE_FLOAT32, -1);
+
+
+ /* Print some basic information before the actual contents: */
+ printf("Pixel values of %s (HDU: %s) on %zu threads.\n", filename, hdu,
+ numthreads);
+ printf("Used to check the compiled library's capability in opening a "
+ "FITS file, and also spinning-off threads.\n");
+
+
+ /* A small sanity check: this is only intended for 2D arrays. */
+ if(p.image->ndim!=2)
{
- fprintf(stderr, "%zu bytes could not be allocated for prm.",
- numthreads*sizeof *prm);
+ fprintf(stderr, "only 2D images are supported.");
exit(EXIT_FAILURE);
}
- /* Distribute the actions into the threads: */
- gal_threads_dist_in_threads(numactions, numthreads, &indexs, &thrdcols);
- /* Do the job: when only one thread is necessary, there is no need to
- spin off one thread, just call the function directly (spinning off
- threads is expensive). This is for the generic thread spinner
- function, not this simple function where `numthreads' is a
- constant. */
- if(numthreads==1)
- {
- prm[0].id=0;
- prm[0].b=NULL;
- prm[0].indexs=indexs;
- worker(&prm[0]);
- }
- else
- {
- /* Initialize the attributes. Note that this running thread
- (that spinns off the nt threads) is also a thread, so the
- number the barriers should be one more than the number of
- threads spinned off. */
- numbarriers = (numactions<numthreads ? numactions : numthreads) + 1;
- gal_threads_attr_barrier_init(&attr, &b, numbarriers);
-
- /* Spin off the threads: */
- for(i=0;i<numthreads;++i)
- if(indexs[i*thrdcols]!=GAL_BLANK_SIZE_T)
- {
- prm[i].id=i;
- prm[i].b=&b;
- prm[i].indexs=&indexs[i*thrdcols];
- err=pthread_create(&t, &attr, worker, &prm[i]);
- if(err)
- {
- fprintf(stderr, "can't create thread %zu", i);
- exit(EXIT_FAILURE);
- }
- }
-
- /* Wait for all threads to finish and free the spaces. */
- pthread_barrier_wait(&b);
- pthread_attr_destroy(&attr);
- pthread_barrier_destroy(&b);
- }
+ /* Spin-off the threads and do the processing on each thread. */
+ gal_threads_spin_off(worker_on_thread, &p, p.image->size, numthreads);
- /* Clean up. */
- free(prm);
- free(indexs);
- /* Return. */
+ /* Clean up and return. */
+ gal_data_free(p.image);
return EXIT_SUCCESS;
}
diff --git a/tests/lib/multithread.sh b/tests/lib/multithread.sh
new file mode 100755
index 0000000..378da79
--- /dev/null
+++ b/tests/lib/multithread.sh
@@ -0,0 +1,48 @@
+# Run the program to test reading a FITS file to memory and writing it on
+# the command-line in multi-threaded mode.
+#
+# See the Tests subsection of the manual for a complete explanation
+# (in the Installing gnuastro section).
+#
+# Original author:
+# Mohammad Akhlaghi <address@hidden>
+# Contributing author(s):
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+
+
+
+# Preliminaries
+# =============
+#
+# Set the variabels (The executable is in the build tree). Do the
+# basic checks to see if the executable is made or if the defaults
+# file exists (basicchecks.sh is in the source tree).
+img=psf.fits
+execname=./multithread
+
+
+
+
+
+# SKIP or FAIL?
+# =============
+#
+# If the actual executable wasn't built, then this is a hard error and must
+# be FAIL. But if the input doesn't exist, its not this test's fault. So
+# just SKIP this test.
+if [ ! -f $execname ]; then echo "$execname not built"; exit 99; fi;
+if [ ! -f $img ]; then echo "$img not built"; exit 77; fi;
+
+
+
+
+
+# Actual test script
+# ==================
+$execname
diff --git a/tests/lib/versioncpp.sh b/tests/lib/versioncpp.sh
new file mode 100755
index 0000000..0d5654f
--- /dev/null
+++ b/tests/lib/versioncpp.sh
@@ -0,0 +1,45 @@
+# Run the program to build a report the Gnuastro version in C++.
+#
+# See the Tests subsection of the manual for a complete explanation
+# (in the Installing gnuastro section).
+#
+# Original author:
+# Mohammad Akhlaghi <address@hidden>
+# Contributing author(s):
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. This file is offered as-is,
+# without any warranty.
+
+
+
+
+
+# Preliminaries
+# =============
+#
+# Set the variabels (The executable is in the build tree). Do the
+# basic checks to see if the executable is made or if the defaults
+# file exists (basicchecks.sh is in the source tree).
+execname=./versioncpp
+
+
+
+
+
+# Skip?
+# =====
+#
+# If the actual executable wasn't built, then this is a hard error and must
+# be FAIL. But if the input doesn't exist, its not this test's fault. So
+# just SKIP this test.
+if [ ! -f $execname ]; then echo "$execname not built"; exit 99; fi;
+
+
+
+
+
+# Actual test script
+# ==================
+$execname
diff --git a/tests/prepconf.sh b/tests/prepconf.sh
index d5a1b76..0c9bafb 100755
--- a/tests/prepconf.sh
+++ b/tests/prepconf.sh
@@ -22,14 +22,17 @@
# along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+
+
# Make the .gnuastro directory
# ----------------------------
#
-# This directory will keep all the utility configuration files for
-# this run of `make check'.
-if [ ! -d .gnuastro ]; then
- mkdir .gnuastro
-fi
+# This directory will keep the default configuration files for all the
+# programs. If it already exists, delete it. `mkdir_p' is the equivalent to
+# GNU's `mkdir -p' which might not exist on some systems. It comes from
+# Autoconf's tests and is exported to the test shell scripts from the
+# `tests/Makefile.am' file.
+$mkdir_p .gnuastro
@@ -41,19 +44,13 @@ fi
# Copy the common options while adding the following optios only for make
# check.
#
-# - The onlydirconf option is added so the utilities don't go looking
-# into the user's home and system wide directories (which might contain
-# configuration files from older versions). If the option names have
-# changed or an option has been removed, such sitations will cause a
-# failed test.
+# - `lastconfig' will make sure that the program stop searching for
+# configuration files after this one.
#
-# - When checking on multiple threads, the log files generated by the
-# utilities can get mixed and cause failures, so it is better for the
-# utility test scripts to not generate any log files. In the utility
-# design, it is best that a fatal error is reported on the standard
-# error (which will be recorded in the test outputs), not in a log
-# file. However, a solution that would allow us to keep the log files
-# would be to make the log file names depend on the input filenames.
+# - Log files are not necessary during tests, they are mainly used for
+# reporting extra information about successful tests. Failed messages
+# will be printed on the command-line not in a log-file. So to keep
+# this directory clean, we'll ask the programs to not generate any.
cat > addedoptions.txt <<EOF
@@ -70,9 +67,8 @@ rm addedoptions.txt
# Bring utility configuration files
# ---------------------------------
#
-# Each utility's configuration file is read and appended with the
-# addedoptions.txt file to create the configuration file which will be used
-# by `make check'.
+# Each utility's configuration file is copied in the `tests' directory for
+# easy readability.
for prog in arithmetic convertt convolve cosmiccal crop fits \
mkcatalog mknoise mkprof noisechisel statistics \
table warp
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnuastro-commits] master 9256566: Updating doc, lib. check as scripts, and lib. cleanup,
Mohammad Akhlaghi <=