UP | HOME

MEMORY back end

Table of Contents

The in-memory back end keeps everything in the memory of the calling process and writes nothing to disk. It supports the same data as the other two back ends – numerical and string attributes, dense datasets, sparse datasets, buffered quantities and the determinant list – and is selected by passing TREXIO_MEMORY to trexio_open.

It exists so that data can be passed through the TREXIO API between parts of one program without a file in between: a producer writes into the handle and a consumer reads from the same handle, using the same calls it would use on a file.

Because there is no file, three things differ from the other back ends, and all three follow from that:

Internally it mirrors the TEXT back end without the file I/O: reading a group returns the in-RAM struct, an empty one if the group has not been written yet. The struct-based categories – numerical attributes, numerical and string datasets, string attributes – live in per-group structs, while sparse, buffered and determinant data live in a generic name-keyed blob store on the handle.

1. Template for group-related structures in memory back end

typedef struct $group$_mem_s {
  $group_num_dtype_double$ $group_num$;
  $group_dset_dtype$*  $group_dset$;
  uint64_t dims_$group_dset$[16];
  uint64_t len_$group_str$;
  uint32_t rank_$group_dset$;
  uint32_t to_flush;
  bool $group_num$_isSet;
  char*    $group_str$;
} $group$_mem_t;

2. Template for general structure in memory back end

Polymorphism of the trexio_t type is handled by ensuring that the back-end struct starts with a trexio_t parent attribute, so it can be safely cast to trexio_t.

typedef struct trexio_memory_s {
  trexio_t   parent ;
  trexio_mem_blob_t* blobs;
  $group$_mem_t* $group$;
} trexio_memory_t;

3. Initialize function (constant part)

trexio_mem_blob_t*
trexio_mem_blob_find (trexio_memory_t* const file, const char* name)
{
  trexio_mem_blob_t* b = file->blobs;
  while (b != NULL) {
    if (strncmp(b->name, name, sizeof(b->name)) == 0) return b;
    b = b->next;
  }
  return NULL;
}

trexio_mem_blob_t*
trexio_mem_blob_get (trexio_memory_t* const file, const char* name, const int32_t rank)
{
  trexio_mem_blob_t* b = trexio_mem_blob_find(file, name);
  if (b != NULL) return b;
  b = (trexio_mem_blob_t*) calloc(1, sizeof(trexio_mem_blob_t));
  if (b == NULL) return NULL;
  strncpy(b->name, name, sizeof(b->name)-1);
  b->name[sizeof(b->name)-1] = '\0';
  b->rank = rank;
  b->next = file->blobs;
  file->blobs = b;
  return b;
}

void
trexio_mem_blob_free_all (trexio_memory_t* const file)
{
  trexio_mem_blob_t* b = file->blobs;
  while (b != NULL) {
    trexio_mem_blob_t* next = b->next;
    free(b->index);
    free(b->list);
    free(b->value);
    free(b);
    b = next;
  }
  file->blobs = NULL;
}

/* Grow the blob to hold at least `need` items. */
static trexio_exit_code
trexio_mem_blob_reserve (trexio_mem_blob_t* const b, const int64_t need,
                         const bool want_index, const bool want_list, const bool want_value)
{
  if (need <= b->capacity) return TREXIO_SUCCESS;
  int64_t cap = (b->capacity > 0) ? b->capacity : 1024L;
  while (cap < need) cap *= 2L;

  if (want_index) {
    int32_t* p = (int32_t*) realloc(b->index, (size_t) cap * (size_t) b->rank * sizeof(int32_t));
    if (p == NULL) return TREXIO_ALLOCATION_FAILED;
    b->index = p;
  }
  if (want_list) {
    int64_t* p = (int64_t*) realloc(b->list, (size_t) cap * (size_t) b->rank * sizeof(int64_t));
    if (p == NULL) return TREXIO_ALLOCATION_FAILED;
    b->list = p;
  }
  if (want_value) {
    double* p = (double*) realloc(b->value, (size_t) cap * sizeof(double));
    if (p == NULL) return TREXIO_ALLOCATION_FAILED;
    b->value = p;
  }
  b->capacity = cap;
  return TREXIO_SUCCESS;
}

trexio_exit_code
trexio_mem_blob_append_sparse (trexio_mem_blob_t* const b, const int64_t size,
                               const int32_t* index, const double* value)
{
  trexio_exit_code rc = trexio_mem_blob_reserve(b, b->n_items + size, true, false, true);
  if (rc != TREXIO_SUCCESS) return rc;
  memcpy(b->index + b->n_items * b->rank, index, (size_t) size * (size_t) b->rank * sizeof(int32_t));
  memcpy(b->value + b->n_items, value, (size_t) size * sizeof(double));
  b->n_items += size;
  return TREXIO_SUCCESS;
}

trexio_exit_code
trexio_mem_blob_read_sparse (const trexio_mem_blob_t* const b, const int64_t offset, const int64_t size,
                             int32_t* const index, double* const value, int64_t* const eof)
{
  if (b == NULL || offset >= b->n_items) { *eof = 0L; return TREXIO_END; }
  const int64_t avail = b->n_items - offset;
  const int64_t n = (size <= avail) ? size : avail;
  memcpy(index, b->index + offset * b->rank, (size_t) n * (size_t) b->rank * sizeof(int32_t));
  memcpy(value, b->value + offset, (size_t) n * sizeof(double));
  if (n < size) { *eof = n; return TREXIO_END; }
  return TREXIO_SUCCESS;
}

trexio_exit_code
trexio_mem_blob_append_value (trexio_mem_blob_t* const b, const int64_t size, const double* value)
{
  trexio_exit_code rc = trexio_mem_blob_reserve(b, b->n_items + size, false, false, true);
  if (rc != TREXIO_SUCCESS) return rc;
  memcpy(b->value + b->n_items, value, (size_t) size * sizeof(double));
  b->n_items += size;
  return TREXIO_SUCCESS;
}

trexio_exit_code
trexio_mem_blob_read_value (const trexio_mem_blob_t* const b, const int64_t offset, const int64_t size,
                            double* const value, int64_t* const eof)
{
  if (b == NULL || offset >= b->n_items) { *eof = 0L; return TREXIO_END; }
  const int64_t avail = b->n_items - offset;
  const int64_t n = (size <= avail) ? size : avail;
  memcpy(value, b->value + offset, (size_t) n * sizeof(double));
  if (n < size) { *eof = n; return TREXIO_END; }
  return TREXIO_SUCCESS;
}

trexio_exit_code
trexio_mem_blob_append_list (trexio_mem_blob_t* const b, const int64_t size, const int64_t* list)
{
  trexio_exit_code rc = trexio_mem_blob_reserve(b, b->n_items + size, false, true, false);
  if (rc != TREXIO_SUCCESS) return rc;
  memcpy(b->list + b->n_items * b->rank, list, (size_t) size * (size_t) b->rank * sizeof(int64_t));
  b->n_items += size;
  return TREXIO_SUCCESS;
}

trexio_exit_code
trexio_mem_blob_read_list (const trexio_mem_blob_t* const b, const int64_t offset, const int64_t size,
                           int64_t* const list, int64_t* const eof)
{
  if (b == NULL || offset >= b->n_items) { *eof = 0L; return TREXIO_END; }
  const int64_t avail = b->n_items - offset;
  const int64_t n = (size <= avail) ? size : avail;
  memcpy(list, b->list + offset * b->rank, (size_t) n * (size_t) b->rank * sizeof(int64_t));
  if (n < size) { *eof = n; return TREXIO_END; }
  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_inquire (const char* file_name)
{
  /* In-memory files do not persist on disk and are never pre-existing. */
  (void) file_name;
  return TREXIO_FAILURE;
}
trexio_exit_code
trexio_memory_init (trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  trexio_memory_t* const f = (trexio_memory_t*) file;

  /* Put all pointers to NULL but leave parent untouched */
  memset(&(f->parent)+1, 0, sizeof(trexio_memory_t)-sizeof(trexio_t));

  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_lock (trexio_t* const file)
{
  /* Nothing to lock for an in-memory, single-process file. */
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_unlock (trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  return TREXIO_SUCCESS;
}

4. Deinitialize function (templated part)

trexio_exit_code
trexio_memory_deinit (trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  trexio_exit_code rc;

  /* Free the in-RAM blob store (sparse / buffered / determinant data). */
  trexio_mem_blob_free_all((trexio_memory_t*) file);

  /* Error handling for this call is added by the generator */
  rc = trexio_memory_free_$group$( (trexio_memory_t*) file);

  return TREXIO_SUCCESS;
}

5. Flush function (templated part)

trexio_exit_code
trexio_memory_flush (trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  trexio_exit_code rc;
  trexio_memory_t* f = (trexio_memory_t*) file;

  rc = trexio_memory_flush_$group$(f); if (rc != TREXIO_SUCCESS) return rc;

  return TREXIO_SUCCESS;
}

6. Template for memory read a group

$group$_mem_t*
trexio_memory_read_$group$ (trexio_memory_t* const file)
{
  if (file == NULL) return NULL;

  /* If the data structure exists, return it; otherwise create an empty one.
     There is no file to read from for the in-memory back end. */
  if (file->$group$ != NULL) {
    return file->$group$;
  }

  $group$_mem_t* $group$ = MALLOC($group$_mem_t);
  if ($group$ == NULL) return NULL;

  memset($group$, 0, sizeof($group$_mem_t));

  file->$group$ = $group$;
  return $group$;
}

7. Template for memory has a group

trexio_exit_code
trexio_memory_has_$group$ (trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  trexio_memory_t* const f = (trexio_memory_t*) file;

  if (f->$group$ != NULL) {
    return TREXIO_SUCCESS;
  } else {
    return TREXIO_HAS_NOT;
  }
}

8. Template for memory flush a group

trexio_exit_code
trexio_memory_flush_$group$ (trexio_memory_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  if (file->parent.mode == 'r') return TREXIO_READONLY;

  /* Nothing to flush: the data already lives in memory. */
  if (file->$group$ != NULL) file->$group$->to_flush = 0;

  return TREXIO_SUCCESS;
}

9. Template for memory free memory

trexio_exit_code
trexio_memory_free_$group$ (trexio_memory_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  $group$_mem_t* $group$ = file->$group$;
  if ($group$ == NULL) return TREXIO_SUCCESS;

  // START REPEAT GROUP_DSET_NUM
  if ($group$->$group_dset$ != NULL) FREE ($group$->$group_dset$);
  // END REPEAT GROUP_DSET_NUM

  // START REPEAT GROUP_DSET_STR
  if ($group$->$group_dset$ != NULL) {
    if ($group$->rank_$group_dset$ != 0) FREE ($group$->$group_dset$[0]);
    FREE ($group$->$group_dset$);
  }
  // END REPEAT GROUP_DSET_STR

  // START REPEAT GROUP_ATTR_STR
  if ($group$->$group_str$ != NULL) FREE ($group$->$group_str$);
  // END REPEAT GROUP_ATTR_STR

  FREE ($group$);
  file->$group$ = NULL;

  return TREXIO_SUCCESS;
}

10. Template for has/read/write a numerical attribute

trexio_exit_code
trexio_memory_read_$group_num$ (trexio_t* const file, $group_num_dtype_double$* const num)
{
  if (file  == NULL) return TREXIO_INVALID_ARG_1;
  if (num   == NULL) return TREXIO_INVALID_ARG_2;

  $group$_mem_t* $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  *num = $group$->$group_num$;

  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_write_$group_num$ (trexio_t* const file, const $group_num_dtype_double$ num)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (file->mode == 'r') return TREXIO_READONLY;

  $group$_mem_t* $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  $group$->$group_num$ = num;
  $group$->$group_num$_isSet = true;
  $group$->to_flush = 1;

  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_has_$group_num$ (trexio_t* const file)
{
  if (file  == NULL) return TREXIO_INVALID_ARG_1;

  $group$_mem_t* $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if ($group$->$group_num$_isSet == true){
    return TREXIO_SUCCESS;
  } else {
    return TREXIO_HAS_NOT;
  }
}

11. Template for has/read/write a dataset of numerical data

trexio_exit_code
trexio_memory_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $group_dset$,
                                 const uint32_t rank, const uint64_t* dims)
{
  if (file  == NULL) return TREXIO_INVALID_ARG_1;
  if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
  if (rank < 1) return TREXIO_INVALID_ARG_3;
  if (dims == NULL) return TREXIO_INVALID_ARG_4;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if (rank != $group$->rank_$group_dset$) return TREXIO_INVALID_ARG_3;

  uint64_t dim_size = 1;
  for (uint32_t i=0; i<rank; ++i){
    if (dims[i] != $group$->dims_$group_dset$[i]) return TREXIO_INVALID_ARG_4;
    dim_size *= dims[i];
  }

  for (uint64_t i=0 ; i<dim_size ; ++i) {
    $group_dset$[i] = $group$->$group_dset$[i];
  }

  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$* $group_dset$,
                                  const uint32_t rank, const uint64_t* dims)
{
  if (file  == NULL)  return TREXIO_INVALID_ARG_1;
  if ($group_dset$ == NULL)  return TREXIO_INVALID_ARG_2;
  if (rank < 1) return TREXIO_INVALID_ARG_3;
  if (dims == NULL) return TREXIO_INVALID_ARG_4;

  if (file->mode == 'r') return TREXIO_READONLY;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if ($group$->$group_dset$ != NULL) {
    FREE($group$->$group_dset$);
  }

  $group$->rank_$group_dset$ = rank;

  uint64_t dim_size = 1;
  for (uint32_t i=0; i<$group$->rank_$group_dset$; ++i){
    $group$->dims_$group_dset$[i] = dims[i];
    dim_size *= dims[i];
  }

  $group$->$group_dset$ = CALLOC(dim_size, $group_dset_dtype$);
  if ($group$->$group_dset$ == NULL) return TREXIO_ALLOCATION_FAILED;

  for (uint64_t i=0 ; i<dim_size ; ++i) {
    $group$->$group_dset$[i] = $group_dset$[i];
  }

  $group$->to_flush = 1;
  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_has_$group_dset$ (trexio_t* const file)
{
  if (file  == NULL) return TREXIO_INVALID_ARG_1;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if ($group$->rank_$group_dset$ > 0){
    return TREXIO_SUCCESS;
  } else {
    return TREXIO_HAS_NOT;
  }
}

12. Template for has/read/write a dataset of strings

trexio_exit_code
trexio_memory_read_$group_dset$ (trexio_t* const file, char* const dset, const uint32_t rank, const uint64_t* dims, const uint32_t max_str_len)
{
  if (file  == NULL) return TREXIO_INVALID_ARG_1;
  if (dset == NULL) return TREXIO_INVALID_ARG_2;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if (rank != $group$->rank_$group_dset$) return TREXIO_INVALID_ARG_3;

  for (uint32_t i=0 ; i<rank ; ++i) {
    if (dims[i] != $group$->dims_$group_dset$[i]) return TREXIO_INVALID_ARG_4;
  }

  strcpy(dset, "");
  for (uint64_t i=0 ; i<dims[0] ; ++i) {
    strncat(dset, $group$->$group_dset$[i], max_str_len);
    strcat(dset, TREXIO_DELIM);
  }

  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_write_$group_dset$ (trexio_t* const file, const char** dset, const uint32_t rank, const uint64_t* dims)
{
  if (file  == NULL)  return TREXIO_INVALID_ARG_1;
  if (dset == NULL)  return TREXIO_INVALID_ARG_2;

  if (file->mode == 'r') return TREXIO_READONLY;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if ($group$->$group_dset$ != NULL) {
    if ($group$->rank_$group_dset$ != 0) FREE($group$->$group_dset$[0]);
    FREE($group$->$group_dset$);
  }

  $group$->rank_$group_dset$ = rank;

  for (uint32_t i=0; i<$group$->rank_$group_dset$; ++i){
    $group$->dims_$group_dset$[i] = dims[i];
  }

  $group$->$group_dset$ = CALLOC(dims[0], char*);
  if ($group$->$group_dset$ == NULL) return TREXIO_ALLOCATION_FAILED;

  /* Compute the exact amount of memory needed to store all the strings
   * contiguously instead of assuming an arbitrary maximum string length,
   * which would silently truncate or overflow longer strings. */
  size_t tmp_str_size = 0;
  for (uint64_t i=0 ; i<dims[0] ; ++i) {
    tmp_str_size += strlen(dset[i]) + 2;
  }

  char* tmp_str = CALLOC(tmp_str_size, char);
  if (tmp_str == NULL) return TREXIO_ALLOCATION_FAILED;

  for (uint64_t i=0 ; i<dims[0] ; ++i) {
    size_t tmp_len = strlen(dset[i])+1;
    $group$->$group_dset$[i] = tmp_str;
    strncpy(tmp_str, dset[i], tmp_len);
    tmp_str[tmp_len-1] = '\0';
    tmp_str += tmp_len + 1;
  }

  $group$->to_flush = 1;

  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_has_$group_dset$ (trexio_t* const file)
{
  if (file  == NULL) return TREXIO_INVALID_ARG_1;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if ($group$->rank_$group_dset$ > 0){
    return TREXIO_SUCCESS;
  } else {
    return TREXIO_HAS_NOT;
  }
}

13. Template for has/read/write a string attribute

trexio_exit_code
trexio_memory_read_$group_str$ (trexio_t* const file, char* const str, const uint32_t max_str_len)
{
  if (file  == NULL) return TREXIO_INVALID_ARG_1;
  if (str == NULL) return TREXIO_INVALID_ARG_2;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  strncpy(str, $group$->$group_str$, max_str_len);
  str[max_str_len-1] = '\0';

  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_write_$group_str$ (trexio_t* const file, const char *str)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (str  == NULL) return TREXIO_INVALID_ARG_2;

  if (file->mode == 'r') return TREXIO_READONLY;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if ($group$->$group_str$ != NULL) FREE($group$->$group_str$);

  size_t tmp_len = strlen(str);

  $group$->$group_str$ = CALLOC(tmp_len + 1, char);
  if ($group$->$group_str$ == NULL) return TREXIO_ALLOCATION_FAILED;

  $group$->len_$group_str$ = tmp_len + 1;

  strncpy($group$->$group_str$, str, tmp_len + 1);
  $group$->$group_str$[tmp_len] = '\0';

  $group$->to_flush = 1;

  return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_memory_has_$group_str$ (trexio_t* const file)
{
  if (file  == NULL) return TREXIO_INVALID_ARG_1;

  $group$_mem_t* const $group$ = trexio_memory_read_$group$((trexio_memory_t*) file);
  if ($group$ == NULL) return TREXIO_FAILURE;

  if ($group$->len_$group_str$ > 0){
    return TREXIO_SUCCESS;
  } else {
    return TREXIO_HAS_NOT;
  }
}

14. Template for memory delete a group (UNSAFE mode)

trexio_exit_code
trexio_memory_delete_$group$ (trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  trexio_memory_t* f = (trexio_memory_t*) file;

  /* Dropping the in-memory struct deletes the group. */
  trexio_exit_code rc_free = trexio_memory_free_$group$(f);
  if (rc_free != TREXIO_SUCCESS) return rc_free;

  return TREXIO_SUCCESS;
}

15. Template for has/read/write the dataset of sparse data

Sparse data (e.g. two-electron integrals, Cholesky vectors, 2-RDMs) is held in a name-keyed in-RAM blob of growable index/value arrays. Writing appends; reading returns chunks from a given item offset.

trexio_exit_code trexio_memory_write_$group_dset$(trexio_t* const file,
                                                  const int64_t offset_file, const int64_t size,
                                                  const int64_t size_max, const int64_t size_start,
                                                  const int32_t* index_sparse, const double* value_sparse)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (file->mode == 'r') return TREXIO_READONLY;
  (void) offset_file; (void) size_max; (void) size_start;

  trexio_mem_blob_t* b = trexio_mem_blob_get((trexio_memory_t*) file, "$group_dset$", $group_dset_rank$);
  if (b == NULL) return TREXIO_ALLOCATION_FAILED;

  return trexio_mem_blob_append_sparse(b, size, index_sparse, value_sparse);
}
trexio_exit_code trexio_memory_read_$group_dset$(trexio_t* const file,
                                                 const int64_t offset_file, const int64_t size,
                                                 const int64_t size_max, int64_t* const eof_read_size,
                                                 int32_t* const index_sparse, double* const value_sparse)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5;
  (void) size_max;

  trexio_mem_blob_t* b = trexio_mem_blob_find((trexio_memory_t*) file, "$group_dset$");
  return trexio_mem_blob_read_sparse(b, offset_file, size, index_sparse, value_sparse, eof_read_size);
}

trexio_exit_code trexio_memory_read_$group_dset$_size(trexio_t* const file, int64_t* const size_max)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (size_max == NULL) return TREXIO_INVALID_ARG_2;

  trexio_mem_blob_t* b = trexio_mem_blob_find((trexio_memory_t*) file, "$group_dset$");
  *size_max = (b == NULL) ? 0L : b->n_items;
  return TREXIO_SUCCESS;
}
trexio_exit_code trexio_memory_has_$group_dset$(trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  trexio_mem_blob_t* b = trexio_mem_blob_find((trexio_memory_t*) file, "$group_dset$");
  return (b != NULL && b->n_items > 0) ? TREXIO_SUCCESS : TREXIO_HAS_NOT;
}

16. Template for has/read/write a buffered vector

Buffered vectors (e.g. CI/CSF coefficients) are held in a name-keyed in-RAM blob of growable values. Writing appends; reading returns a chunk.

trexio_exit_code trexio_memory_write_$group_dset$(trexio_t* const file, const int64_t offset_file,
                                                  const uint32_t rank, const uint64_t* dims, const double* dset)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (offset_file < 0) return TREXIO_INVALID_ARG_2;
  if (rank < 1) return TREXIO_INVALID_ARG_3;
  if (dims == NULL) return TREXIO_INVALID_ARG_4;
  if (dset == NULL) return TREXIO_INVALID_ARG_5;
  if (file->mode == 'r') return TREXIO_READONLY;
  (void) offset_file;

  trexio_mem_blob_t* b = trexio_mem_blob_get((trexio_memory_t*) file, "$group_dset$", 1);
  if (b == NULL) return TREXIO_ALLOCATION_FAILED;

  return trexio_mem_blob_append_value(b, (int64_t) dims[0], dset);
}
trexio_exit_code trexio_memory_read_$group_dset$(trexio_t* const file, const int64_t offset_file,
                                                 const uint32_t rank, const uint64_t* dims,
                                                 int64_t* const eof_read_size, double* const dset)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (offset_file < 0) return TREXIO_INVALID_ARG_2;
  if (rank < 1) return TREXIO_INVALID_ARG_3;
  if (dims == NULL) return TREXIO_INVALID_ARG_4;
  if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5;
  if (dset == NULL) return TREXIO_INVALID_ARG_6;

  trexio_mem_blob_t* b = trexio_mem_blob_find((trexio_memory_t*) file, "$group_dset$");
  return trexio_mem_blob_read_value(b, offset_file, (int64_t) dims[0], dset, eof_read_size);
}

trexio_exit_code trexio_memory_read_$group_dset$_size(trexio_t* const file, int64_t* const size_max)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (size_max == NULL) return TREXIO_INVALID_ARG_2;

  trexio_mem_blob_t* b = trexio_mem_blob_find((trexio_memory_t*) file, "$group_dset$");
  *size_max = (b == NULL) ? 0L : b->n_items;
  return TREXIO_SUCCESS;
}
trexio_exit_code trexio_memory_has_$group_dset$(trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  trexio_mem_blob_t* b = trexio_mem_blob_find((trexio_memory_t*) file, "$group_dset$");
  return (b != NULL && b->n_items > 0) ? TREXIO_SUCCESS : TREXIO_HAS_NOT;
}

17. Source code for the determinant part

The determinant list (bit-field occupation strings) is stored in a single name-keyed in-RAM blob of int64 values; the coefficients use the buffered mechanism above. These functions are constant (not templated).

trexio_exit_code trexio_memory_write_determinant_list(trexio_t* const file, const int64_t offset_file,
                                                      const uint32_t rank, const uint64_t* dims, const int64_t* list)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (offset_file < 0) return TREXIO_INVALID_ARG_2;
  if (rank != 2) return TREXIO_INVALID_ARG_3;
  if (dims == NULL) return TREXIO_INVALID_ARG_4;
  if (list == NULL) return TREXIO_INVALID_ARG_5;
  if (file->mode == 'r') return TREXIO_READONLY;
  (void) offset_file;

  trexio_mem_blob_t* b = trexio_mem_blob_get((trexio_memory_t*) file, "determinant_list", (int32_t) dims[1]);
  if (b == NULL) return TREXIO_ALLOCATION_FAILED;

  return trexio_mem_blob_append_list(b, (int64_t) dims[0], list);
}
trexio_exit_code trexio_memory_read_determinant_list(trexio_t* const file, const int64_t offset_file,
                                                     const uint32_t rank, const uint64_t* dims,
                                                     int64_t* const eof_read_size, int64_t* const list)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;
  if (offset_file < 0) return TREXIO_INVALID_ARG_2;
  if (rank != 2) return TREXIO_INVALID_ARG_3;
  if (dims == NULL) return TREXIO_INVALID_ARG_4;
  if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5;
  if (list == NULL) return TREXIO_INVALID_ARG_6;

  trexio_mem_blob_t* b = trexio_mem_blob_find((trexio_memory_t*) file, "determinant_list");
  return trexio_mem_blob_read_list(b, offset_file, (int64_t) dims[0], list, eof_read_size);
}
trexio_exit_code trexio_memory_has_determinant_list(trexio_t* const file)
{
  if (file == NULL) return TREXIO_INVALID_ARG_1;

  trexio_mem_blob_t* b = trexio_mem_blob_find((trexio_memory_t*) file, "determinant_list");
  return (b != NULL && b->n_items > 0) ? TREXIO_SUCCESS : TREXIO_HAS_NOT;
}

Author: TREX-CoE

Created: 2026-11-10 Tue 16:46

Validate