Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions examples/dedx_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ int main(int argc, char *argv[]) {
for (i = 0; i < 300; ++i)
printf(" %3i %s\n", i, dedx_get_material_name(i));

/* Material / ion property accessors. Each accessor writes to *err, so the
* values are read into temporaries first — passing one &err to several
* calls inside a single printf would leave the writes unsequenced. */
{
int err = 0;
int carbon_a = dedx_get_nucleon_number(DEDX_CARBON, &err);
float carbon_mass = dedx_get_atom_mass(DEDX_CARBON, &err);
float water_rho = dedx_get_density(DEDX_WATER, &err);
int water_gas = dedx_is_gas(DEDX_WATER, &err);
float air_rho = dedx_get_density(DEDX_AIR, &err);
int air_gas = dedx_is_gas(DEDX_AIR, &err);
printf("\nCarbon ion: A=%d, atomic mass=%.4f u\n", carbon_a, carbon_mass);
printf("Water: density=%.4f g/cm^3, gas=%d\n", water_rho, water_gas);
printf("Air: density=%.4g g/cm^3, gas=%d\n", air_rho, air_gas);
}

// printf("NB: %i\n", DEDX_WATER);
return 0;
}
32 changes: 32 additions & 0 deletions include/dedx.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,38 @@ void dedx_get_composition(int target, float composition[][2], unsigned int *comp
*/
float dedx_get_i_value(int target, int *err);

/** @brief Return the nucleon number (mass number A) of an elemental ion.
* @param[in] ion Elemental ion identifier (atomic number Z, 1–112).
* @param[out] err Error code; DEDX_OK on success, DEDX_ERR_NOT_AN_ELEMENT
* if @p ion is outside the tabulated element range.
* @return Nucleon number, or -1 on error.
*/
int dedx_get_nucleon_number(int ion, int *err);

/** @brief Return the standard atomic mass of an elemental ion.
* @param[in] ion Elemental ion identifier (atomic number Z, 1–112).
* @param[out] err Error code; DEDX_OK on success, DEDX_ERR_NOT_AN_ELEMENT
* if @p ion is outside the tabulated element range.
* @return Atomic mass in u (unified atomic mass units), or -1 on error.
*/
float dedx_get_atom_mass(int ion, int *err);

/** @brief Return the default density of a target material.
* @param[in] material Material identifier.
* @param[out] err Error code; DEDX_OK on success, DEDX_ERR_TARGET_NOT_FOUND
* if @p material has no embedded density metadata.
* @return Density in g/cm³, or 0 on error.
*/
float dedx_get_density(int material, int *err);

/** @brief Report whether a target material is gaseous.
* @param[in] target Material identifier.
* @param[out] err Error code; always set to DEDX_OK — an unknown target is
* reported as non-gas rather than as an error.
* @return 1 if the target is flagged gaseous, 0 otherwise (including unknown targets).
*/
Comment thread
grzanka marked this conversation as resolved.
int dedx_is_gas(int target, int *err);

/** @brief Return a null-terminated list of supported program identifiers.
* @return Pointer to a static array terminated by 0; do not free.
*/
Expand Down
29 changes: 29 additions & 0 deletions src/dedx.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,35 @@ float dedx_get_i_value(int target, int *err) {
return dedx_internal_get_i_value(target, DEDX_GAS, err);
}

/* Highest atomic number with tabulated mass/nucleon data (see dedx_amu / dedx_nucl). */
#define DEDX_MAX_ELEMENT_Z 112

int dedx_get_nucleon_number(int ion, int *err) {
/* The internal lookup only guards the upper bound; reject ion <= 0 here
* so we never index the table with a negative offset. */
if (ion < 1 || ion > DEDX_MAX_ELEMENT_Z) {
*err = DEDX_ERR_NOT_AN_ELEMENT;
return -1;
}
return dedx_internal_get_nucleon(ion, err);
}

float dedx_get_atom_mass(int ion, int *err) {
if (ion < 1 || ion > DEDX_MAX_ELEMENT_Z) {
*err = DEDX_ERR_NOT_AN_ELEMENT;
return -1.0f;
}
return dedx_internal_get_atom_mass(ion, err);
}

float dedx_get_density(int material, int *err) {
return dedx_internal_read_density(material, err);
}

int dedx_is_gas(int target, int *err) {
return dedx_internal_target_is_gas(target, err) != 0 ? 1 : 0;
}

const int *dedx_get_program_list(void) {
/* returns a list of available programs, terminated with -1 */
return dedx_available_programs;
Expand Down
127 changes: 127 additions & 0 deletions tests/test_accessors.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include <dedx.h>
#include <dedx_error.h>
#include <math.h>
#include <stdio.h>

/* Tests for the public material/ion property accessors:
* dedx_get_nucleon_number, dedx_get_atom_mass, dedx_get_density, dedx_is_gas.
* These promote previously-internal helpers to the public API (issue #119).
*
* All assertions funnel through the three expect_* helpers below so the only
* lines that stay uncovered on a passing run are their (shared) failure paths.
*/

static int failures = 0;

static void expect_int(const char *label, long got, long expected) {
if (got != expected) {
fprintf(stderr, "FAIL %s: got %ld expected %ld\n", label, got, expected);
failures++;
}
}

static void expect_near(const char *label, double got, double expected, double rel) {
double scale = fabs(expected) > 1e-12 ? fabs(expected) : 1.0;
if (fabs(got - expected) > rel * scale) {
fprintf(stderr, "FAIL %s: got %.8g expected %.8g\n", label, got, expected);
failures++;
}
}

static void expect_true(const char *label, int condition) {
if (!condition) {
fprintf(stderr, "FAIL %s\n", label);
failures++;
}
}

int main(void) {
int err;
float air;

/* --- nucleon number: valid elements --- */
err = -1;
expect_int("nucleon H value", dedx_get_nucleon_number(DEDX_HYDROGEN, &err), 1);
expect_int("nucleon H err", err, DEDX_OK);

err = -1;
expect_int("nucleon He value", dedx_get_nucleon_number(DEDX_HELIUM, &err), 4);
expect_int("nucleon He err", err, DEDX_OK);

err = -1;
expect_int("nucleon C value", dedx_get_nucleon_number(DEDX_CARBON, &err), 12);
expect_int("nucleon C err", err, DEDX_OK);

/* Highest tabulated element (Z=112) must be accepted (upper boundary). */
err = -1;
expect_true("nucleon Z=112 value", dedx_get_nucleon_number(112, &err) > 0);
expect_int("nucleon Z=112 err", err, DEDX_OK);

/* --- nucleon number: out-of-range guards (lower bound the internal lacks) --- */
err = DEDX_OK;
expect_int("nucleon 0 value", dedx_get_nucleon_number(0, &err), -1);
expect_int("nucleon 0 err", err, DEDX_ERR_NOT_AN_ELEMENT);

err = DEDX_OK;
expect_int("nucleon negative value", dedx_get_nucleon_number(-5, &err), -1);
expect_int("nucleon negative err", err, DEDX_ERR_NOT_AN_ELEMENT);

err = DEDX_OK;
expect_int("nucleon 113 value", dedx_get_nucleon_number(113, &err), -1);
expect_int("nucleon 113 err", err, DEDX_ERR_NOT_AN_ELEMENT);

/* --- atom mass: valid elements --- */
err = -1;
expect_near("mass H value", dedx_get_atom_mass(DEDX_HYDROGEN, &err), 1.00794, 1e-4);
expect_int("mass H err", err, DEDX_OK);

err = -1;
expect_near("mass C value", dedx_get_atom_mass(DEDX_CARBON, &err), 12.0107, 1e-4);
expect_int("mass C err", err, DEDX_OK);

err = -1;
expect_near("mass O value", dedx_get_atom_mass(DEDX_OXYGEN, &err), 15.9994, 1e-4);
expect_int("mass O err", err, DEDX_OK);

/* --- atom mass: out-of-range guards --- */
err = DEDX_OK;
expect_true("mass 0 sentinel", dedx_get_atom_mass(0, &err) == -1.0f);
expect_int("mass 0 err", err, DEDX_ERR_NOT_AN_ELEMENT);

err = DEDX_OK;
expect_true("mass 200 sentinel", dedx_get_atom_mass(200, &err) == -1.0f);
expect_int("mass 200 err", err, DEDX_ERR_NOT_AN_ELEMENT);

/* --- density: known liquid and gaseous materials --- */
err = -1;
expect_near("density water value", dedx_get_density(DEDX_WATER, &err), 1.0, 0.02);
expect_int("density water err", err, DEDX_OK);

err = -1;
air = dedx_get_density(DEDX_AIR, &err);
expect_true("density air range", air > 0.0f && air < 0.01f);
expect_int("density air err", err, DEDX_OK);

/* --- density: unknown material returns a safe sentinel + error --- */
err = DEDX_OK;
expect_true("density unknown sentinel", dedx_get_density(9999, &err) == 0.0f);
expect_int("density unknown err", err, DEDX_ERR_TARGET_NOT_FOUND);

/* --- is_gas: liquid vs gas --- */
err = -1;
expect_int("is_gas water value", dedx_is_gas(DEDX_WATER, &err), 0);
expect_int("is_gas water err", err, DEDX_OK);

err = -1;
expect_int("is_gas air value", dedx_is_gas(DEDX_AIR, &err), 1);
expect_int("is_gas air err", err, DEDX_OK);

/* Unknown target is reported as non-gas, never an error (documented). */
err = -1;
expect_int("is_gas unknown value", dedx_is_gas(9999, &err), 0);
expect_int("is_gas unknown err", err, DEDX_OK);

if (failures == 0)
printf("test_accessors: all checks passed\n");
return failures;
}
Loading