doi={10.21105/joss.04642},url={https://doi.org/10.21105/joss.04642},year={2023},publisher={The Open Journal},volume={8},number={85},pages={4642},author={D. D. Hendriks and R. G. Izzard},title={binary_c-python: A Python-based stellar population synthesis tool and interface to binary_c},journal={Journal of Open Source Software}}
-name:Department of Physics, School of Mathematics and Physics, University of Surrey, Guildford, GU2 7XH, Surrey, UK
index:1
date:28 July2022
date:06 December2023
bibliography:paper.bib
---
# Summary
A common requirement in science is to store and share large sets of simulation data in an efficient, nested, flexible and human-readable way. Such datasets contain number counts and distributions, i.e. histograms and maps, of arbitrary dimension and variable type, e.g. floating-point number, integer or character string. Modern high-level programming languages like Perl and Python have associated arrays, knowns as dictionaries or hashes, respectively, to fulfil this storage need. Low-level languages used more commonly for fast computational simulations, such as C and Fortran, lack this functionality. We present a `libcdict`, a C dictionary library, to mostly solve this problem. `Libcdict` provides C and Fortran application programming interfaces (APIs) to native dictionaries, called `cdict`s, and functions for `cdict` to load and save these as JSON and hence for easy interpretation in other software and languages like Perl, Python and R.
A common requirement in science is to store and share large sets of simulation data in an efficient, nested, flexible and human-readable way. Such datasets contain number counts and distributions, i.e. histograms and maps, of arbitrary dimension and variable type, e.g. floating-point number, integer or character string. Modern high-level programming languages like Perl and Python have associated arrays, knowns as dictionaries or hashes, respectively, to fulfil this storage need. Low-level languages used more commonly for fast computational simulations, such as C and Fortran, lack this functionality. We present a `libcdict`, a C dictionary library, to solve this problem. `Libcdict` provides C and Fortran application programming interfaces (APIs) to native dictionaries, called `cdict`s, and functions for `cdict` to load and save these as JSON and hence for easy interpretation in other software and languages like Perl, Python and R.
# Statement of need
Users of high-level languages such as Perl or Python have access to associated-array data structures through dictionaries and hashes, respectively. These allow arbitrary data types to be stored in array-like structures. These are in turn accessed through key-value pairs which allow the value to be a further, nested associated array, allowing arbitrary nesting of data. Compiled low-level languages, like C and Fortran, are more suited to high-speed and repeated calculations typical in science. These languages lack native associated-array functionality. While there are pure hash-table solutions out there, such as `glib` [@glib_manual_hashtable;@glib_gitlab] and `uthash` [@uthash_github], these do not combine a simple API for setting and adding to nested structures, a small library footprint, fast input and output, and standardised JSON output to easily interface with other languages and tools. `libcdict` provides an API for such functionality which allows `cdict`s to be nested in `cdict`s, hence arbitrarily-nested dictionaries of variables in C just as in Perl or Python.
Users of high-level languages such as Perl or Python have access to associated-array data structures through dictionaries and hashes, respectively. These allow arbitrary data types to be stored in array-like structures. These are in turn accessed through key-value pairs which allow the value to be a further, nested associated array, allowing arbitrary nesting of data. Compiled low-level languages, like C and Fortran, are more suited to high-speed and repeated calculations typical in science. These languages lack native associated-array functionality. While there are pure hash-table solutions out there, such as `glib` [@glib_manual_hashtable] and `uthash` [@uthash_github], these do not combine a simple API for setting and adding to nested structures, a small library footprint, fast input and output, and standardised JSON output to easily interface with other languages and tools. `libcdict` provides an API for such functionality which allows `cdict`s to be nested in `cdict`s, hence arbitrarily-nested dictionaries of variables in C just as in Perl or Python.
`libcdict` is written in C and provides an API through a set of C macros. Nested `cdict` structures have values in them set with a single line of code. `libcdict` has been used for the last year in the `binary_c` single- and binary-star population nucleosynthesis framework [@izzard:2004; @izzard:2006; @izzard:2009; @izzard:2018; @izzard:2023] which computes the evolution of millions of single- and binary-stellar systems in only a few hours using its `binary_c-python` Python frontend [@Hendriks:2023]. We provide `libcdict` as open-source code on Gitlab subject to the GPL3. `libcdict` also has a comprehensive test suite run through its configuration program `cdict-config`.
@@ -36,9 +37,9 @@ Users of high-level languages such as Perl or Python have access to associated-a
`libcdict` is flexible but pragmatic. Keys to `cdict`s can be any C scalar or pointer. Values can be scalars, pointers, arrays or other `cdict`s, but arrays must be of a single C type. Values can store metadata of arbitrary type. Pointer values are optionally garbage collected when a `cdict` is freed. A set of API macros provides simple nesting facilities so that placing a value in a nested location given a list of keys is a simple task for the C programmer. Issues such as C variable typing are automatically handled for the user.
Variables are internally hashed using `uthash` [@uthash_github]. `libcdict` provides a custom JSON output function and inputs JSON using `jsmn` [@jsmn_github; @jsmn_homepage]. Floating-point input and output uses `fast double parser` [@fastdoubleparser_github; @lemire:2021] and `Ryū` [@ryugithub; @adams:2018; @adams:2019], respectively, both of which are considerably faster than equivalent C library functions. `libdict` allows customizable floating-point accuracy for output and when comparing floating-point numbers, e.g. during sorting of key or variable lists.
Variables are internally hashed using `uthash` [@uthash_github]. `libcdict` provides a custom JSON output function and inputs JSON using `jsmn` [@jsmn_github]. Floating-point input and output uses `fast double parser` [@fastdoubleparser_github; @lemire:2021] and `Ryū` [@ryugithub; @adams:2018; @adams:2019], respectively, both of which are considerably faster than equivalent C library functions. `libdict` allows customizable floating-point accuracy for output and when comparing floating-point numbers, e.g. during sorting of key or variable lists.
Installation uses `meson` [@meson_github; @meson_homepage] and `ninja` [@ninja_github; @ninja_homepage]. `libcdict` has been tested with the GCC (10.3.0) and Clang (12.0.0) compilers.
Installation uses `meson` [@meson_github] and `ninja` [@ninja_github]. `libcdict` has been tested with the GCC (10.3.0) and Clang (12.0.0) compilers.
# `libcdict` in stellar-population statistics calculations