commit 36e6495a6ce4a902804fd304167ea5e925ba0d5b
parent 95e48a5dec4e525da8745148506868086a5ce7a6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 30 Oct 2020 14:57:10 +0100
Add the load procedures
Diffstat:
| M | doc/atrck | | | 8 | ++++---- |
| M | src/atrck.c | | | 283 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
| M | src/atrck.h | | | 11 | +++++++++++ |
| M | src/atrck_c.h | | | 105 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 402 insertions(+), 5 deletions(-)
diff --git a/doc/atrck b/doc/atrck
@@ -11,12 +11,12 @@
---
<bands-list> ::= <band> [ <band> ... ]
-<band> ::= <band-id> <band-center> <band-size> <#quad-pts>
+<band> ::= <band-id> <band-low> <band-upp> <#quad-pts>
<quad-pts-list>
<band-id> ::= INT64
-<band-center> ::= DOUBLE
-<band-size> ::= DOUBLE
+<band-low> ::= DOUBLE
+<band-upp> ::= DOUBLE
<#quad-pts> ::= INT64
---
@@ -33,5 +33,5 @@
<padding>
[ <ka-list> ... ]
<ka-list> ::= <ka> [ <ka> ... ]
-<ka> ::= DOUBLE
+<ka> ::= FLOAT
diff --git a/src/atrck.c b/src/atrck.c
@@ -13,22 +13,253 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#define _POSIX_C_SOURCE 200809L /* mmap support */
+#define _DEFAULT_SOURCE 1 /* MAP_POPULATE support */
+#define _BSD_SOURCE 1 /* MAP_POPULATE for glibc < 2.19 */
+
#include "atrck.h"
#include "atrck_c.h"
#include "atrck_log.h"
-#include <unistd.h>
+#include <unistd.h> /* sysconf support */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h> /* mmap */
/*******************************************************************************
* Helper functions
******************************************************************************/
static void
+reset_atrck(struct atrck* atrck)
+{
+ ASSERT(atrck);
+ atrck->pagesize = 0;
+ atrck->nnodes = 0;
+ darray_band_purge(&atrck->bands);
+}
+
+static res_T
+read_quad_pt
+ (struct atrck* atrck,
+ struct quad_pt* quad_pt,
+ FILE* stream,
+ const char* stream_name,
+ size_t iband,
+ size_t iquad_pt)
+{
+ res_T res = RES_OK;
+ ASSERT(atrck && quad_pt && stream_name);
+
+ #define READ(Var, Name) { \
+ if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
+ log_err(atrck, \
+ "%s: band %lu: quadrature point %lu: could not read the %s.\n", \
+ stream_name, iband, iquad_pt, Name); \
+ res = RES_IO_ERR; \
+ goto error; \
+ } \
+ } (void)0
+ READ(&quad_pt->absissa, "quadrature point absissa");
+ READ(&quad_pt->weight, "quadrature point weight");
+ #undef READ
+
+ quad_pt->ka_list = NULL;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+read_band
+ (struct atrck* atrck,
+ struct band* band,
+ FILE* stream,
+ const char* stream_name)
+{
+ double cumul;
+ size_t iquad_pt;
+ uint64_t nquad_pts;
+ res_T res = RES_OK;
+ ASSERT(atrck && band && stream_name);
+
+ /* Read band definition */
+ #define READ(Var, Name) { \
+ if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
+ log_err(atrck, "%s: band %lu: could not read the %s.\n", \
+ stream_name, (unsigned long)band->id, (Name)); \
+ res = RES_IO_ERR; \
+ goto error; \
+ } \
+ } (void)0
+ READ(&band->id, "band identifier");
+ READ(&band->low, "band lower bound");
+ READ(&band->upp, "band upper bound");
+ READ(&nquad_pts, "#quadrature points");
+ #undef READ
+
+ /* Check band description */
+ if(band->low < 0 || band->low > band->upp) {
+ log_err(atrck,
+ "%s: band %lu: invalid band range [%g, %g].\n",
+ stream_name, (unsigned long)band->id, band->low, band->upp);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(nquad_pts == 0) {
+ log_err(atrck,
+ "%s: band %lu: invalid number fo quadrature points (#points=%lu).\n",
+ stream_name, (unsigned long)band->id, (unsigned long)nquad_pts);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the list of quadrature points */
+ res = darray_quad_pt_resize(&band->quad_pts, nquad_pts);
+ if(res != RES_OK) {
+ log_err(atrck,
+ "%s: band %lu: could not allocate the list of quadrature points "
+ "(#points=%lu).\n",
+ stream_name, (unsigned long)band->id, (unsigned long)nquad_pts);
+ goto error;
+ }
+
+ /* Allocate the cumulative used to sample the quadrature points */
+ res = darray_double_resize(&band->quad_pts_cumul, nquad_pts);
+ if(res != RES_OK) {
+ log_err(atrck,
+ "%s: band %lu: could not allocate the cumulative of quadrature points "
+ "(#points=%lu).\n",
+ stream_name, (unsigned long)band->id, (unsigned long)nquad_pts);
+ goto error;
+ }
+
+ /* Read the data of the quadrature points of the band */
+ cumul = 0;
+ FOR_EACH(iquad_pt, 0, nquad_pts) {
+ struct quad_pt* quad_pt = darray_quad_pt_data_get(&band->quad_pts)+iquad_pt;
+
+ /* Read current quadrature point */
+ res = read_quad_pt(atrck, quad_pt, stream, stream_name, band->id, iquad_pt);
+ if(res != RES_OK) goto error;
+
+ /* Compute the quadrature point cumulative */
+ cumul += quad_pt->weight;
+ darray_double_data_get(&band->quad_pts_cumul)[iquad_pt] = cumul;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+load_stream(struct atrck* atrck, FILE* stream, const char* stream_name)
+{
+ size_t map_len;
+ size_t iband;
+ uint64_t nbands;
+ res_T res = RES_OK;
+ ASSERT(atrck && stream && stream_name);
+
+ reset_atrck(atrck);
+
+ /* Read file header */
+ #define READ(Var, Name) { \
+ if(fread((Var), sizeof(*(Var)), 1, stream) != 1) { \
+ log_err(atrck, "%s: could not read the %s.\n", stream_name, (Name)); \
+ res = RES_IO_ERR; \
+ goto error; \
+ } \
+ } (void)0
+ READ(&atrck->pagesize, "page size");
+ READ(&nbands, "number of bands");
+ READ(&atrck->nnodes, "number of nodes");
+ #undef READ
+
+ /* Check band description */
+ if(!IS_POW2(atrck->pagesize)) {
+ log_err(atrck, "%s: invalid pagesize %lu.\n",
+ stream_name, (unsigned long)atrck->pagesize);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(!nbands) {
+ log_err(atrck, "%s: invalid number of bands %lu.\n",
+ stream_name, (unsigned long)nbands);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(!atrck->nnodes) {
+ log_err(atrck, "%s: invalid number of nodes %lu.\n",
+ stream_name, (unsigned long)atrck->nnodes);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the bands */
+ res = darray_band_resize(&atrck->bands, nbands);
+ if(res != RES_OK) {
+ log_err(atrck, "%s: could not allocate the list of bands (#bands=%lu).\n",
+ stream_name, (unsigned long)nbands);
+ goto error;
+ }
+
+ /* Read the band description */
+ FOR_EACH(iband, 0, nbands) {
+ struct band* band = darray_band_data_get(&atrck->bands) + iband;
+ res = read_band(atrck, band, stream, stream_name);
+ if(res != RES_OK) goto error;
+ }
+
+ /* Compute the length in bytes of the ka to map for each quadrature point */
+ map_len = ALIGN_SIZE(atrck->nnodes * sizeof(double), atrck->pagesize);
+
+ /* Load the per band, per quadrature point and per node correlated K */
+ FOR_EACH(iband, 0, nbands) {
+ struct band* band = darray_band_data_get(&atrck->bands) + iband;
+ size_t iquad_pt;
+ FOR_EACH(iquad_pt, 0, darray_quad_pt_size_get(&band->quad_pts)) {
+ struct quad_pt* quad_pt = NULL;
+ off_t offset = 0;
+
+ quad_pt = darray_quad_pt_data_get(&band->quad_pts)+iquad_pt;
+ offset = (off_t)ALIGN_SIZE((uint64_t)ftell(stream), atrck->pagesize);
+ quad_pt->map_len = map_len;
+ quad_pt->ka_list = mmap(NULL, quad_pt->map_len, PROT_READ,
+ MAP_PRIVATE|MAP_POPULATE, fileno(stream), offset);
+ if(quad_pt->ka_list == MAP_FAILED) {
+ log_err(atrck,
+ "%s: band %lu: quadrature point %lu: coult not map the correlated K "
+ "-- %s.\n",
+ stream_name,
+ (unsigned long)band->id,
+ (unsigned long)iquad_pt,
+ strerror(errno));
+ res = RES_IO_ERR;
+ goto error;
+ }
+ }
+ }
+
+exit:
+ return res;
+error:
+ reset_atrck(atrck);
+ goto exit;
+}
+
+static void
release_atrck(ref_T* ref)
{
struct atrck* atrck;
ASSERT(ref);
atrck = CONTAINER_OF(ref, struct atrck, ref);
if(atrck->logger == &atrck->logger__) logger_release(&atrck->logger__);
+ darray_band_release(&atrck->bands);
MEM_RM(atrck->allocator, atrck);
}
@@ -70,6 +301,7 @@ atrck_create
atrck->allocator = allocator;
atrck->verbose = verbose;
atrck->pagesize_os = (size_t)sysconf(_SC_PAGESIZE);
+ darray_band_init(allocator, &atrck->bands);
if(logger) {
atrck->logger = logger;
} else {
@@ -103,3 +335,52 @@ atrck_ref_put(struct atrck* atrck)
return RES_OK;
}
+res_T
+atrck_load(struct atrck* atrck, const char* path)
+{
+ FILE* file = NULL;
+ res_T res = RES_OK;
+
+ if(!atrck || !path) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ file = fopen(path, "r");
+ if(!file) {
+ log_err(atrck, "%s: error opening file `%s'.\n", FUNC_NAME, path);
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+ res = load_stream(atrck, file, path);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(file) fclose(file);
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+atrck_load_stream
+ (struct atrck* atrck,
+ FILE* stream,
+ const char* stream_name)
+{
+ if(!atrck || !stream) return RES_BAD_ARG;
+ return load_stream(atrck, stream, stream_name ? stream_name : "<stream>");
+}
+
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+void
+quad_pt_release(struct quad_pt* quad_pt)
+{
+ ASSERT(quad_pt);
+ if(quad_pt->ka_list && quad_pt->ka_list != MAP_FAILED)
+ munmap(quad_pt->ka_list, quad_pt->map_len);
+}
diff --git a/src/atrck.h b/src/atrck.h
@@ -63,6 +63,17 @@ ATRCK_API res_T
atrck_ref_put
(struct atrck* atrck);
+ATRCK_API res_T
+atrck_load
+ (struct atrck* atrck,
+ const char* path);
+
+ATRCK_API res_T
+atrck_load_stream
+ (struct atrck* atrck,
+ FILE* stream,
+ const char* stream_name); /* Can be NULL */
+
END_DECLS
#endif /* ATRCK_H */
diff --git a/src/atrck_c.h b/src/atrck_c.h
@@ -16,12 +16,117 @@
#ifndef ATRCK_C_H
#define ATRCK_C_H
+#include <rsys/dynamic_array_double.h>
#include <rsys/logger.h>
#include <rsys/ref_count.h>
struct mem_allocator;
+struct quad_pt {
+ double* ka_list; /* Per node ka */
+ size_t map_len;
+ double absissa;
+ double weight;
+};
+
+static INLINE void
+quad_pt_init(struct mem_allocator* allocator, struct quad_pt* quad)
+{
+ ASSERT(quad);
+ (void)allocator;
+ quad->ka_list = NULL;
+ quad->map_len = 0;;
+ quad->absissa = 0;
+ quad->weight = 0;
+}
+
+extern LOCAL_SYM INLINE void
+quad_pt_release
+ (struct quad_pt* quad);
+
+/* Define the dynamic array of quadrature points */
+#define DARRAY_NAME quad_pt
+#define DARRAY_DATA struct quad_pt
+#include <rsys/dynamic_array.h>
+
+struct band {
+ uint64_t id;
+ double low; /* Lower bound in cm^-1 */
+ double upp; /* Upper bound in cm^-1 */
+ struct darray_quad_pt quad_pts;
+ struct darray_double quad_pts_cumul;
+};
+
+static INLINE void
+band_init(struct mem_allocator* allocator, struct band* band)
+{
+ ASSERT(band);
+ band->id = UINT64_MAX;
+ band->low = DBL_MAX;
+ band->upp =-DBL_MAX;
+ darray_quad_pt_init(allocator, &band->quad_pts);
+ darray_double_init(allocator, &band->quad_pts_cumul);
+}
+
+static INLINE void
+band_release(struct band* band)
+{
+ ASSERT(band);
+ darray_quad_pt_release(&band->quad_pts);
+ darray_double_release(&band->quad_pts_cumul);
+}
+
+static INLINE res_T
+band_copy(struct band* dst, const struct band* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+
+ dst->id = src->id;
+ dst->low = src->low;
+ dst->upp = src->upp;
+ res = darray_quad_pt_copy(&dst->quad_pts, &src->quad_pts);
+ if(res != RES_OK) return res;
+ res = darray_double_copy(&dst->quad_pts_cumul, &src->quad_pts_cumul);
+ if(res != RES_OK) return res;
+ return RES_OK;
+}
+
+static INLINE res_T
+band_copy_and_release(struct band* dst, struct band* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+
+ dst->id = src->id;
+ dst->low = src->low;
+ dst->upp = src->upp;
+ res = darray_quad_pt_copy_and_release(&dst->quad_pts, &src->quad_pts);
+ if(res != RES_OK) return res;
+ res = darray_double_copy_and_release
+ (&dst->quad_pts_cumul, &src->quad_pts_cumul);
+ if(res != RES_OK) return res;
+ return RES_OK;
+
+}
+
+/* Define the dynamic array of bands */
+#define DARRAY_NAME band
+#define DARRAY_DATA struct band
+#define DARRAY_FUNCTOR_INIT band_init
+#define DARRAY_FUNCTOR_RELEASE band_release
+#define DARRAY_FUNCTOR_COPY band_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE band_copy_and_release
+#include <rsys/dynamic_array.h>
+
+struct mem_allocator;
+
struct atrck {
+ /* Loaded data */
+ uint64_t pagesize;
+ uint64_t nnodes;
+ struct darray_band bands;
+
size_t pagesize_os;
struct mem_allocator* allocator;