commit 9899bb031bd2ec30d32691d48f6d4e2715b534fe
parent 831d21d76495d54c465f5c3fcdcc47c679b93af1
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 22 Oct 2015 09:16:51 +0200
New wavelengths integration API
The Schiff integration is performed on a list of wavelengths. All
wavelenghts share the same geometry and direction sampling as well as
the computation of the radiative path length.
Diffstat:
4 files changed, 502 insertions(+), 288 deletions(-)
diff --git a/src/sschiff.h b/src/sschiff.h
@@ -56,6 +56,15 @@ struct s3d_device;
struct s3d_shape;
struct ssp_rng;
+/* Type of estimated data */
+enum sschiff_data {
+ SSCHIFF_EXTINCTION_CROSS_SECTION,
+ SSCHIFF_ABSORPTION_CROSS_SECTION,
+ SSCHIFF_SCATTERING_CROSS_SECTION,
+ SSCHIFF_AVERAGE_PROJECTIVE_AREA,
+ SSCHIFF_DATA_COUNT__
+};
+
/* Optical properties of a material handled by the Schiff integrator */
struct sschiff_material_properties {
double medium_refractive_index;
@@ -88,12 +97,14 @@ struct sschiff_geometry_distribution {
static const struct sschiff_geometry_distribution
SSCHIFF_NULL_GEOMETRY_DISTRIBUTION = { NULL, NULL };
-/* Result of the Monte Carlo estimation */
-struct sschiff_estimator_status {
- double E; /* Expected value */
- double V; /* Variance */
- double SE; /* Standard error */
- size_t nsteps; /* # Monte Carlo weights */
+/* State of the Monte Carlo estimation */
+struct sschiff_estimator_state {
+ double wavelength; /* Estimated wavelength */
+ struct sschiff_estimator_value { /* Values of the estimation */
+ double E; /* Expected value */
+ double V; /* Variance */
+ double SE; /* Standard error */
+ } values[SSCHIFF_DATA_COUNT__];
};
/* Opaque types */
@@ -126,7 +137,8 @@ sschiff_integrate
(struct sschiff_device* dev,
struct ssp_rng* rng,
struct sschiff_geometry_distribution* distribution,
- const double wavelength, /* Wavelenght to estimate */
+ const double* wavelengths, /* list of wavelengths to estimate */
+ const size_t wavelengths_count, /* # wavelengths to estimate */
const size_t scattering_angles_count, /* # of scattering angles to handle */
const size_t sampled_geometries_count, /* # geometries to sample */
const size_t sampled_directions_count, /* # directions to sample per geometry */
@@ -140,32 +152,33 @@ SSCHIFF_API res_T
sschiff_estimator_ref_put
(struct sschiff_estimator* estimator);
+/* Return the number of estimated wavelength */
SSCHIFF_API res_T
-sschiff_estimator_get_extinction_cross_section
- (struct sschiff_estimator* estimator,
- struct sschiff_estimator_status* status);
+sschiff_estimator_get_wavelengths_count
+ (const struct sschiff_estimator* estimator,
+ size_t* count);
+/* Return the number of Monte Carlo realisations */
SSCHIFF_API res_T
-sschiff_estimator_get_absorption_cross_section
- (struct sschiff_estimator* estimator,
- struct sschiff_estimator_status* status);
+sschiff_estimator_get_realisations_count
+ (const struct sschiff_estimator* estimator,
+ size_t* count);
+/* Retrieve the estimation state of a given wavelength */
SSCHIFF_API res_T
-sschiff_estimator_get_scattering_cross_section
- (struct sschiff_estimator* estimator,
- struct sschiff_estimator_status* status);
-
-SSCHIFF_API res_T
-sschiff_estimator_get_average_projected_area
- (struct sschiff_estimator* estimator,
- struct sschiff_estimator_status* status);
-
-/* TODO Not implemented yet */
+sschiff_estimator_get_wavelength_state
+ (const struct sschiff_estimator* estimator,
+ const double wavelength,
+ struct sschiff_estimator_state* state);
+
+/* Retrieve the estimation state of all wavelengths. The length of `states'
+ * must be at least equal to the count of integrated wavelengths. One can use
+ * the sschiff_estimator_get_wavelengths_count function to retrieve this
+ * information. */
SSCHIFF_API res_T
-sschiff_estimator_get_phase_function
- (struct sschiff_estimator* estimator,
- const size_t iscattering_angle,
- struct sschiff_estimator_status* status);
+sschiff_estimator_get_states
+ (const struct sschiff_estimator* estimator,
+ struct sschiff_estimator_state states[]);
END_DECLS
diff --git a/src/sschiff_estimator.c b/src/sschiff_estimator.c
@@ -31,6 +31,7 @@
#include "sschiff.h"
#include "sschiff_device.h"
+#include <rsys/dynamic_array_double.h>
#include <rsys/float2.h>
#include <rsys/float3.h>
#include <rsys/image.h>
@@ -46,27 +47,37 @@
#define MAX_FAILURES 10
-/* Type of computed Monte Carlo weights */
-enum weight_type {
- WEIGHT_EXTINCTION_CROSS_SECTION,
- WEIGHT_ABSORPTION_CROSS_SECTION,
- WEIGHT_SCATTERING_CROSS_SECTION,
- WEIGHT_AVERAGE_PROJECTED_AREA,
- WEIGHTS_COUNT
-};
+/* Accumulator of double precision values */
+struct accum { double weights[SSCHIFF_DATA_COUNT__]; };
-/* Accumulator of Monte Carlo weights */
-struct accum {
- double weight;
- double sqr_weight;
- size_t naccums;
-};
+/* Monte carlo data */
+struct mc_data { double weight; double sqr_weight; };
-struct sschiff_estimator {
- double wavelength;
+static const struct mc_data MC_DATA_NULL = { 0.0, 0.0 };
+
+/* Accumulator of Monte Carlo data */
+struct mc_accum { struct mc_data mc_data[SSCHIFF_DATA_COUNT__]; };
+
+static const struct mc_accum MC_ACCUM_NULL =
+{{{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}};
+
+#define DARRAY_NAME mcaccum
+#define DARRAY_DATA struct mc_accum
+#include <rsys/dynamic_array.h>
+
+#define DARRAY_NAME accum
+#define DARRAY_DATA struct accum
+#include <rsys/dynamic_array.h>
- struct accum accums[WEIGHTS_COUNT];
+#define DARRAY_NAME mtl
+#define DARRAY_DATA struct sschiff_material_properties
+#include <rsys/dynamic_array.h>
+
+struct sschiff_estimator {
+ struct darray_double wavelengths;
+ struct darray_mcaccum accums;
struct sschiff_device* dev;
+ size_t nrealisations;
ref_T ref;
};
@@ -84,6 +95,15 @@ morton2D_decode(const uint32_t u32)
return (uint16_t)x;
}
+static FINLINE int
+cmp_double(const void* a, const void* b)
+{
+ const double* op0 = a;
+ const double* op1 = b;
+ const int i = *op0 < *op1 ? -1 : (*op0 > *op1 ? 1 : 0);
+ return i;
+}
+
/* Compute an orthonormal basis where `dir' is the Z axis. */
static void
build_basis(const float dir[3], float basis[9])
@@ -132,6 +152,80 @@ build_transform
transform[11] = -f3_dot(basis+6, pos);
}
+/* Dump a thumbnail of the sampled geometry in given sampled direction */
+static INLINE void
+draw_thumbnail
+ (struct s3d_scene* scn,
+ const float basis[9], /* World space basis of the RT volume */
+ const float pos[3], /* World space centroid of the RT volume */
+ const float lower[3], /* Lower boundary of the RT volume */
+ const float upper[3], /* Upper boundary of the RT volume */
+ const char* name) /* Filename of the thumbnail */
+{
+#define DEFINITION 128
+ STATIC_ASSERT(IS_POW2(DEFINITION), Invalid_thumbnail_definition);
+ const float range[2] = { 0, FLT_MAX };
+ const float pixel_size = 1.f/(float)DEFINITION;
+ float axis_x[3], axis_y[3], axis_z[3];
+ float plane_size[2];
+ float ray_org[3];
+ float org[3];
+ uint32_t npixels = (uint32_t)(DEFINITION * DEFINITION);
+ uint32_t mcode;
+ unsigned char* img = NULL;
+ ASSERT(basis && pos && lower && upper);
+
+ /* Allocate the thumbnail buffer */
+ img = sa_add(img, DEFINITION*DEFINITION);
+ ASSERT(img != NULL);
+
+ /* Define the projection axis */
+ f2_sub(plane_size, upper, lower);
+ f3_mulf(axis_x, basis + 0, plane_size[0] * 0.5f);
+ f3_mulf(axis_y, basis + 3, plane_size[1] * 0.5f);
+ f3_set(axis_z, basis + 6);
+
+ /* Compute the origin of the projection plane */
+ f3_add(org, pos, f3_mulf(org, axis_z, lower[2]));
+
+ FOR_EACH(mcode, 0, npixels) {
+ struct s3d_hit hit;
+ size_t ipixel;
+ float sample[2], x[3], y[3];
+ uint16_t ipixel_x, ipixel_y;
+
+ /* Compute the sample position in [0, 1)^2 onto the projection plane */
+ ipixel_x = morton2D_decode(mcode);
+ ipixel_y = morton2D_decode(mcode>>1);
+ sample[0] = ((float)ipixel_x + 0.5f) * pixel_size;
+ sample[1] = ((float)ipixel_y + 0.5f) * pixel_size;
+
+ /* Compute the ray origin */
+ f3_mulf(x, axis_x, sample[0]*2.f - 1.f);
+ f3_mulf(y, axis_y, sample[1]*2.f - 1.f);
+ f3_add(ray_org, f3_add(ray_org, x, y), org);
+
+ S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit));
+
+ /* Simple shading */
+ ipixel = (size_t)(ipixel_y * DEFINITION + ipixel_x);
+ if(S3D_HIT_NONE(&hit)) {
+ img[ipixel] = 0;
+ } else {
+ float N[3] = {0.f,0.f,0.f};
+ float cosine;
+ f3_normalize(N, hit.normal);
+ if(0 > (cosine = f3_dot(N, axis_z))) {
+ cosine = f3_dot(f3_minus(N, N), axis_z);
+ }
+ img[ipixel] = (unsigned char)(cosine*255.f + 0.5f/*Round*/);
+ }
+ }
+ image_ppm_write(name, DEFINITION, DEFINITION, 1, img);
+ sa_release(img);
+#undef DEFINITION
+}
+
/* Compute the length of radiative path that traverses the scene */
static res_T
compute_path_length
@@ -183,17 +277,18 @@ compute_path_length
}
static res_T
-compute_monte_carlo_weight
+accum_monte_carlo_weight
(struct sschiff_device* dev,
struct s3d_scene* scn,
struct ssp_rng* rng,
struct sschiff_material_properties* props,
- const double wavelength,
+ const double* wavelengths,
+ const size_t nwavelengths,
const float basis[9], /* World space basis of the RT volume */
const float pos[3], /* World space centroid of the RT volume */
const float lower[3], /* Lower boundary of the RT volume */
const float upper[3], /* Upper boundary of the RT volume */
- double weights[WEIGHTS_COUNT])
+ struct accum* accums)
{
struct s3d_hit hit;
double sample[2];
@@ -205,10 +300,9 @@ compute_monte_carlo_weight
float org[3];
float x[3], y[3];
float rcp_pdf;
- int i;
res_T res = RES_OK;
- ASSERT(scn && rng && props && basis && pos && lower && upper);
- ASSERT(weights);
+ ASSERT(scn && rng && props && wavelengths && accums && basis && pos);
+ ASSERT(lower && upper);
f2_sub(plane_size, upper, lower);
rcp_pdf = plane_size[0] * plane_size[1] * 1.e-12f/*Meter^2 to micron^2*/;
@@ -221,9 +315,6 @@ compute_monte_carlo_weight
/* Compute the origin of the projection plane */
f3_add(org, pos, f3_mulf(org, axis_z, lower[2]));
- FOR_EACH(i, 0, WEIGHTS_COUNT)
- weights[i] = 0;
-
do {
/* Uniformly sample a position onto the projection plane and use it as the
* origin of the ray to trace */
@@ -236,9 +327,8 @@ compute_monte_carlo_weight
S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit));
if(!S3D_HIT_NONE(&hit)) {
- double n_r, k_r;
- double n_e, k_e, lambda_e;
double path_length;
+ size_t iwlen;
res = compute_path_length(dev, scn, &hit, ray_org, axis_z, &path_length);
if(res != RES_OK) { /* Handle numerical/geometry issues */
@@ -246,24 +336,34 @@ compute_monte_carlo_weight
continue;
}
- n_e = props->medium_refractive_index;
- n_r = props->relative_real_refractive_index;
- k_r = props->relative_imaginary_refractive_index;
+ FOR_EACH(iwlen, 0, nwavelengths) {
+ double n_r, k_r;
+ double n_e, k_e, lambda_e;
+ double w_extinction, w_absorption, w_scattering;
+
+ n_e = props[iwlen].medium_refractive_index;
+ n_r = props[iwlen].relative_real_refractive_index;
+ k_r = props[iwlen].relative_imaginary_refractive_index;
- lambda_e = wavelength / n_e;
- k_e = 2.0 * PI / lambda_e;
+ lambda_e = wavelengths[iwlen] / n_e;
+ k_e = 2.0 * PI / lambda_e;
- weights[WEIGHT_EXTINCTION_CROSS_SECTION] = 2.0 * rcp_pdf
- * (1.0 - exp(-k_e*k_r*path_length) * cos(k_e*(n_r - 1.0)*path_length));
+ /* Extinction cross section */
+ w_extinction = 2.0 * rcp_pdf *
+ (1.0 - exp(-k_e*k_r*path_length) * cos(k_e*(n_r - 1.0)*path_length));
+ accums[iwlen].weights[SSCHIFF_EXTINCTION_CROSS_SECTION] += w_extinction;
- weights[WEIGHT_ABSORPTION_CROSS_SECTION] = rcp_pdf
- * (1.0 - exp(-2.0*k_e*k_r*path_length));
+ /* Absorption cross section */
+ w_absorption = rcp_pdf * (1.0 - exp(-2.0*k_e*k_r*path_length));
+ accums[iwlen].weights[SSCHIFF_ABSORPTION_CROSS_SECTION] += w_absorption;
- weights[WEIGHT_SCATTERING_CROSS_SECTION] =
- weights[WEIGHT_EXTINCTION_CROSS_SECTION]
- - weights[WEIGHT_ABSORPTION_CROSS_SECTION];
+ /* Scattering cross section */
+ w_scattering = w_extinction - w_absorption;
+ accums[iwlen].weights[SSCHIFF_SCATTERING_CROSS_SECTION] += w_scattering;
- weights[WEIGHT_AVERAGE_PROJECTED_AREA] = rcp_pdf;
+ /* Average projected area */
+ accums[iwlen].weights[SSCHIFF_AVERAGE_PROJECTIVE_AREA] += rcp_pdf;
+ }
}
} while(res != RES_OK && nfailures < MAX_FAILURES);
@@ -275,99 +375,28 @@ compute_monte_carlo_weight
return res;
}
-/* Dump a thumbnail of the sampled geometry in given sampled direction */
-static INLINE void
-draw_thumbnail
- (struct s3d_scene* scn,
- const float basis[9], /* World space basis of the RT volume */
- const float pos[3], /* World space centroid of the RT volume */
- const float lower[3], /* Lower boundary of the RT volume */
- const float upper[3], /* Upper boundary of the RT volume */
- const char* name) /* Filename of the thumbnail */
-{
-#define DEFINITION 128
- STATIC_ASSERT(IS_POW2(DEFINITION), Invalid_thumbnail_definition);
- const float range[2] = { 0, FLT_MAX };
- const float pixel_size = 1.f/(float)DEFINITION;
- float axis_x[3], axis_y[3], axis_z[3];
- float plane_size[2];
- float ray_org[3];
- float org[3];
- uint32_t npixels = (uint32_t)(DEFINITION * DEFINITION);
- uint32_t mcode;
- unsigned char* img = NULL;
- ASSERT(basis && pos && lower && upper);
-
- /* Allocate the thumbnail buffer */
- img = sa_add(img, DEFINITION*DEFINITION);
- ASSERT(img != NULL);
-
- /* Define the projection axis */
- f2_sub(plane_size, upper, lower);
- f3_mulf(axis_x, basis + 0, plane_size[0] * 0.5f);
- f3_mulf(axis_y, basis + 3, plane_size[1] * 0.5f);
- f3_set(axis_z, basis + 6);
-
- /* Compute the origin of the projection plane */
- f3_add(org, pos, f3_mulf(org, axis_z, lower[2]));
-
- FOR_EACH(mcode, 0, npixels) {
- struct s3d_hit hit;
- size_t ipixel;
- float sample[2], x[3], y[3];
- uint16_t ipixel_x, ipixel_y;
-
- /* Compute the sample position in [0, 1)^2 onto the projection plane */
- ipixel_x = morton2D_decode(mcode);
- ipixel_y = morton2D_decode(mcode>>1);
- sample[0] = ((float)ipixel_x + 0.5f) * pixel_size;
- sample[1] = ((float)ipixel_y + 0.5f) * pixel_size;
-
- /* Compute the ray origin */
- f3_mulf(x, axis_x, sample[0]*2.f - 1.f);
- f3_mulf(y, axis_y, sample[1]*2.f - 1.f);
- f3_add(ray_org, f3_add(ray_org, x, y), org);
-
- S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit));
-
- /* Simple shading */
- ipixel = (size_t)(ipixel_y * DEFINITION + ipixel_x);
- if(S3D_HIT_NONE(&hit)) {
- img[ipixel] = 0;
- } else {
- float N[3] = {0.f,0.f,0.f};
- float cosine;
- f3_normalize(N, hit.normal);
- if(0 > (cosine = f3_dot(N, axis_z))) {
- cosine = f3_dot(f3_minus(N, N), axis_z);
- }
- img[ipixel] = (unsigned char)(cosine*255.f + 0.5f/*Round*/);
- }
- }
- image_ppm_write(name, DEFINITION, DEFINITION, 1, img);
- sa_release(img);
-#undef DEFINITION
-}
-
static res_T
radiative_properties
(struct sschiff_device* dev,
struct ssp_rng* rng,
const int istep,
- const double wavelength,
+ const double* wavelengths, /* Sorted in ascending order */
+ const size_t nwavelengths,
const size_t ndirs,
struct s3d_scene* scene,
struct sschiff_material_properties* props,
- struct accum accums[WEIGHTS_COUNT])
+ struct mc_accum* mc_accums,
+ struct accum* accums)
{
- double weights_dirs[WEIGHTS_COUNT];
float lower[3], upper[3];
float aabb_pt[8][3];
float centroid[3];
size_t idir;
+ size_t iwlen;
int i;
res_T res = RES_OK;
- ASSERT(dev && rng && ndirs && props && accums);
+ ASSERT(dev && rng && wavelengths && nwavelengths && ndirs && props);
+ ASSERT(mc_accums && accums);
(void)istep;
S3D(scene_get_aabb(scene, lower, upper));
@@ -390,9 +419,8 @@ radiative_properties
f3_mulf(centroid, f3_add(centroid, lower, upper), 0.5f);
- memset(weights_dirs, 0, sizeof(weights_dirs));
+ memset(accums, 0, sizeof(struct accum)*nwavelengths);
FOR_EACH(idir, 0, ndirs) {
- double weights[WEIGHTS_COUNT];
float dir[4];
float basis[9];
float transform[12];
@@ -417,11 +445,10 @@ radiative_properties
f3_max(upper, upper, pt[i]);
}
- res = compute_monte_carlo_weight(dev, scene, rng, props, wavelength, basis,
- centroid, lower, upper, weights);
+ res = accum_monte_carlo_weight(dev, scene, rng, props, wavelengths,
+ nwavelengths, basis, centroid, lower, upper, accums);
if(res != RES_OK) goto error;
- FOR_EACH(i, 0, WEIGHTS_COUNT) weights_dirs[i] += weights[i];
#if 0
{
/* Compute an image of the shape transformed in the footprint space */
@@ -431,28 +458,32 @@ radiative_properties
}
#endif
}
- FOR_EACH(i, 0, WEIGHTS_COUNT) {
- weights_dirs[i] /= (double)ndirs;
- accums[i].weight += weights_dirs[i];
- accums[i].sqr_weight += weights_dirs[i] * weights_dirs[i];
- accums[i].naccums += 1;
+ FOR_EACH(iwlen, 0, nwavelengths) {
+ int iweight;
+ FOR_EACH(iweight, 0, SSCHIFF_DATA_COUNT__) {
+ const double w = accums[iwlen].weights[iweight] / (double)ndirs;
+ mc_accums[iwlen].mc_data[iweight].weight += w;
+ mc_accums[iwlen].mc_data[iweight].sqr_weight += w * w;
+ }
}
exit:
return res;
error:
- memset(accums, 0, sizeof(struct accum)*WEIGHTS_COUNT);
+ memset(mc_accums, 0, sizeof(struct mc_accum)*nwavelengths);
goto exit;
}
static void
-get_status(const struct accum* acc, struct sschiff_estimator_status* status)
+get_mc_value
+ (const struct mc_data* data,
+ const size_t nrealisations,
+ struct sschiff_estimator_value* value)
{
- ASSERT(acc && status);
- status->E = acc->weight / (double)acc->naccums;
- status->V = acc->sqr_weight / (double)acc->naccums
- - (acc->weight * acc->weight) / (double)(acc->naccums * acc->naccums);
- status->SE = sqrt(status->V / (double)acc->naccums);
- status->nsteps = acc->naccums;
+ ASSERT(data && value);
+ value->E = data->weight / (double)nrealisations;
+ value->V = data->sqr_weight / (double)nrealisations
+ - (data->weight * data->weight) / (double)(nrealisations * nrealisations);
+ value->SE = sqrt(value->V / (double)nrealisations);
}
static char
@@ -470,13 +501,17 @@ estimator_release(ref_T* ref)
ASSERT(ref);
estimator = CONTAINER_OF(ref, struct sschiff_estimator, ref);
dev = estimator->dev;
+ darray_double_release(&estimator->wavelengths);
+ darray_mcaccum_release(&estimator->accums);
MEM_RM(dev->allocator, estimator);
SSCHIFF(device_ref_put(dev));
}
static res_T
estimator_create
- (struct sschiff_device* dev, struct sschiff_estimator** out_estimator)
+ (struct sschiff_device* dev,
+ const size_t nwavelengths,
+ struct sschiff_estimator** out_estimator)
{
struct sschiff_estimator* estimator = NULL;
res_T res = RES_OK;
@@ -492,6 +527,22 @@ estimator_create
ref_init(&estimator->ref);
SSCHIFF(device_ref_get(dev));
estimator->dev = dev;
+ darray_double_init(dev->allocator, &estimator->wavelengths);
+ darray_mcaccum_init(dev->allocator, &estimator->accums);
+
+ res = darray_double_resize(&estimator->wavelengths, nwavelengths);
+ if(res != RES_OK) {
+ log_error(dev,
+ "Not enough memory: couldn't allocate the list of wavelengths.\n");
+ goto error;
+ }
+ res = darray_mcaccum_resize(&estimator->accums, nwavelengths);
+ if(res != RES_OK) {
+ log_error(dev,
+ "Not enough memory: couldn't allocate the per wavelength "
+ "Monte Carlo accumulators.\n");
+ goto error;
+ }
exit:
*out_estimator = estimator;
@@ -512,27 +563,49 @@ sschiff_integrate
(struct sschiff_device* dev,
struct ssp_rng* rng,
struct sschiff_geometry_distribution* distrib,
- const double wavelength,
- const size_t scattering_angles_count,
- const size_t sampled_geometries_count,
- const size_t sampled_directions_count,
+ const double* wavelengths,
+ const size_t nwavelengths,
+ const size_t nangles,
+ const size_t ngeoms,
+ const size_t ndirs,
struct sschiff_estimator** out_estimator)
{
+ struct darray_mtl mtls;
+ struct darray_accum accums;
struct sschiff_estimator* estimator = NULL;
struct s3d_shape* shape = NULL;
struct s3d_scene* scene = NULL;
size_t i;
res_T res = RES_OK;
- (void)scattering_angles_count;
+ (void)nangles;
+
+ if(!dev || !rng || !distrib || !wavelengths || !nwavelengths || !nangles
+ || !ngeoms || !ndirs || !out_estimator || !check_distribution(distrib)) {
+ return RES_BAD_ARG;
+ }
- if(!dev || !rng || !distrib || !check_distribution(distrib) || !out_estimator) {
- res = RES_BAD_ARG;
+ darray_mtl_init(dev->allocator, &mtls);
+ darray_accum_init(dev->allocator, &accums);
+
+ res = darray_mtl_resize(&mtls, nwavelengths);
+ if(res != RES_OK) {
+ log_error(dev,
+ "No enough memory: couldn't allocate the per wavelength"
+ "optical properties.\n");
goto error;
}
- res = estimator_create(dev, &estimator);
+ res = darray_accum_resize(&accums, nwavelengths);
+ if(res != RES_OK) {
+ log_error(dev,
+ "No enough memory: couldn't allocate the per wavelength "
+ "temporary accumulators.\n");
+ goto error;
+ }
+
+ res = estimator_create(dev, nwavelengths, &estimator);
if(res != RES_OK) goto error;
- estimator->wavelength = wavelength;
+ estimator->nrealisations = ngeoms;
res = s3d_shape_create_mesh(dev->s3d, &shape);
if(res != RES_OK) {
@@ -551,10 +624,24 @@ sschiff_integrate
goto error;
}
- memset(estimator->accums, 0, sizeof(struct accum)*WEIGHTS_COUNT);
- FOR_EACH(i, 0, sampled_geometries_count) {
+ /* Clear the estimator accumulators */
+ memset(darray_mcaccum_data_get(&estimator->accums), 0,
+ sizeof(struct mc_accum)*nwavelengths);
+
+ /* Setup and sort the wavelengths */
+ FOR_EACH(i, 0, nwavelengths) {
+ darray_double_data_get(&estimator->wavelengths)[i] = wavelengths[i];
+ }
+ qsort(darray_double_data_get(&estimator->wavelengths), nwavelengths,
+ sizeof(double), cmp_double);
+
+ FOR_EACH(i, 0, ngeoms) {
+ struct sschiff_material_properties* props = darray_mtl_data_get(&mtls);
+ const double* wlengths = darray_double_cdata_get(&estimator->wavelengths);
+ struct mc_accum* mc_accums = darray_mcaccum_data_get(&estimator->accums);
+ struct accum* accs = darray_accum_data_get(&accums);
struct sschiff_material material = SSCHIFF_NULL_MATERIAL;
- struct sschiff_material_properties props;
+ size_t iwavelength;
/* Sample a geometry, i.e. a shape and its associated material */
res = distrib->sample(rng, &material, shape, distrib->context);
@@ -562,20 +649,26 @@ sschiff_integrate
log_error(dev, "Error in sampling a Schiff geometry.\n");
goto error;
}
- material.get_property(material.material, wavelength, &props);
+ /* Fetch the per wavelength material properties */
+ FOR_EACH(iwavelength, 0, nwavelengths) {
+ material.get_property
+ (material.material, wavelengths[iwavelength], props + iwavelength);
+ }
/* Build the Star-3D representation of the sampled shape */
S3D(scene_begin_session(scene, S3D_TRACE));
/* Schiff Estimation */
- res = radiative_properties(dev, rng, (int)i, wavelength,
- sampled_directions_count, scene, &props, estimator->accums);
+ res = radiative_properties(dev, rng, (int)i, wlengths, nwavelengths, ndirs,
+ scene, props, mc_accums, accs);
if(res != RES_OK) goto error;
S3D(scene_end_session(scene));
}
exit:
+ darray_mtl_release(&mtls);
+ darray_accum_release(&accums);
if(out_estimator) *out_estimator = estimator;
if(shape) S3D(shape_ref_put(shape));
if(scene) S3D(scene_ref_put(scene));
@@ -605,42 +698,80 @@ sschiff_estimator_ref_put(struct sschiff_estimator* estimator)
}
res_T
-sschiff_estimator_get_extinction_cross_section
- (struct sschiff_estimator* estimator,
- struct sschiff_estimator_status* status)
+sschiff_estimator_get_wavelengths_count
+ (const struct sschiff_estimator* estimator, size_t* count)
{
- if(!estimator || !status) return RES_BAD_ARG;
- get_status(estimator->accums + WEIGHT_EXTINCTION_CROSS_SECTION, status);
+ if(!estimator || !count) return RES_BAD_ARG;
+ *count = darray_double_size_get(&estimator->wavelengths);
return RES_OK;
}
res_T
-sschiff_estimator_get_absorption_cross_section
- (struct sschiff_estimator* estimator,
- struct sschiff_estimator_status* status)
+sschiff_estimator_get_realisations_count
+ (const struct sschiff_estimator* estimator, size_t* count)
{
- if(!estimator || !status) return RES_BAD_ARG;
- get_status(estimator->accums + WEIGHT_ABSORPTION_CROSS_SECTION, status);
+ if(!estimator || !count) return RES_BAD_ARG;
+ *count = estimator->nrealisations;
return RES_OK;
}
res_T
-sschiff_estimator_get_scattering_cross_section
- (struct sschiff_estimator* estimator,
- struct sschiff_estimator_status* status)
+sschiff_estimator_get_wavelength_state
+ (const struct sschiff_estimator* estimator,
+ const double wavelength,
+ struct sschiff_estimator_state* state)
{
- if(!estimator || !status) return RES_BAD_ARG;
- get_status(estimator->accums + WEIGHT_SCATTERING_CROSS_SECTION, status);
+ const struct mc_accum* accum;
+ const double* wavelengths;
+ const double* find;
+ size_t iwavelength;
+ size_t nwavelengths;
+ int i;
+
+ if(!estimator || !state)
+ return RES_BAD_ARG;
+
+ wavelengths = darray_double_cdata_get(&estimator->wavelengths);
+ nwavelengths = darray_double_size_get(&estimator->wavelengths);
+ find = bsearch
+ (&wavelength, wavelengths, nwavelengths, sizeof(double), cmp_double);
+ if(!find) return RES_BAD_ARG;
+
+ iwavelength = (size_t)(find - wavelengths);
+ accum = darray_mcaccum_cdata_get(&estimator->accums) + iwavelength;
+
+ FOR_EACH(i, 0, SSCHIFF_DATA_COUNT__) {
+ get_mc_value(accum->mc_data+i, estimator->nrealisations, state->values+i);
+ }
+ state->wavelength = wavelength;
return RES_OK;
}
res_T
-sschiff_estimator_get_average_projected_area
- (struct sschiff_estimator* estimator,
- struct sschiff_estimator_status* status)
+sschiff_estimator_get_states
+ (const struct sschiff_estimator* estimator,
+ struct sschiff_estimator_state* states)
{
- if(!estimator || !status) return RES_BAD_ARG;
- get_status(estimator->accums + WEIGHT_AVERAGE_PROJECTED_AREA, status);
+ const double* wavelengths;
+ const struct mc_accum* accums;
+ size_t nwavelengths;
+ size_t iwlen;
+ int i;
+ if(!estimator || !states) return RES_BAD_ARG;
+
+ nwavelengths = darray_double_size_get(&estimator->wavelengths);
+ wavelengths = darray_double_cdata_get(&estimator->wavelengths);
+ accums = darray_mcaccum_cdata_get(&estimator->accums);
+
+ FOR_EACH(iwlen, 0, nwavelengths) {
+ states[iwlen].wavelength = wavelengths[iwlen];
+ FOR_EACH(i, 0, SSCHIFF_DATA_COUNT__) {
+ get_mc_value
+ (accums[iwlen].mc_data + i,
+ estimator->nrealisations,
+ states[iwlen].values + i);
+ }
+ }
return RES_OK;
}
diff --git a/src/test_sschiff_estimator_cylinder.c b/src/test_sschiff_estimator_cylinder.c
@@ -37,7 +37,6 @@
#include <star/ssp.h>
struct result {
- double wavelength;
double extinction_E; /* Expected value */
double extinction_SE; /* Standard error */
};
@@ -809,19 +808,30 @@ main(int argc, char** argv)
struct sschiff_device* dev;
struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION;
struct sschiff_estimator* estimator;
- struct sschiff_estimator_status status;
struct ssp_rng* rng;
struct time t0, t1;
struct result results[] = {
- { 4.00E-7, 2.76750904574817e-12, 2.34364058801497e-15 },
- { 4.50e-7, 2.50099694990826e-12, 2.20010054373943e-15 },
- { 5.00e-7, 2.32782435081181e-12, 2.05630225764867e-15 },
- { 6.00e-7, 1.96661661205101e-12, 1.82091931178789e-15 },
- { 6.50e-7, 1.71149696366194e-12, 1.63845385406345e-15 },
- { 7.00e-7, 1.54229472112306e-12, 1.49426946826458e-15 },
- { 7.50e-7, 1.39877652964399e-12, 1.36729344819050e-15 }
+ { 2.76750904574817e-12, 2.34364058801497e-15 },
+ { 2.50099694990826e-12, 2.20010054373943e-15 },
+ { 2.32782435081181e-12, 2.05630225764867e-15 },
+ { 1.96661661205101e-12, 1.82091931178789e-15 },
+ { 1.71149696366194e-12, 1.63845385406345e-15 },
+ { 1.54229472112306e-12, 1.49426946826458e-15 },
+ { 1.39877652964399e-12, 1.36729344819050e-15 }
};
- const size_t nresults = sizeof(results) / sizeof(struct result);
+ double wavelengths[] = {
+ 4.00E-7,
+ 4.50e-7,
+ 5.00e-7,
+ 6.00e-7,
+ 6.50e-7,
+ 7.00e-7,
+ 7.50e-7
+ };
+ const size_t nwavelengths = sizeof(wavelengths) / sizeof(double);
+ const size_t nscatt_angles = 1;
+ const size_t ngeoms = 1000;
+ const size_t ndirs = 100;
size_t i;
(void)argc, (void)argv;
@@ -838,45 +848,45 @@ main(int argc, char** argv)
distrib.sample = sample_cylinder;
distrib.context = &sampler_ctx;
- FOR_EACH(i, 0, nresults) {
- const size_t nscatt_angles = 1;
- const size_t ngeoms = 1000;
- const size_t ndirs = 10;
- const double wavelength = results[i].wavelength;
+ time_current(&t0);
+ CHECK(sschiff_integrate(dev, rng, &distrib, wavelengths, nwavelengths,
+ nscatt_angles, ngeoms, ndirs, &estimator), RES_OK);
+ time_current(&t1);
+ time_sub(&t0, &t1, &t0);
+ time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf));
+
+ FOR_EACH(i, 0, nwavelengths) {
+ struct sschiff_estimator_state state;
double interval0[2], interval1[2], interval2[2];
+ struct sschiff_estimator_value* val;
- time_current(&t0);
- CHECK(sschiff_integrate(dev, rng, &distrib, wavelength, nscatt_angles,
- ngeoms, ndirs, &estimator), RES_OK);
- time_current(&t1);
- time_sub(&t0, &t1, &t0);
- time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf));
+ CHECK(sschiff_estimator_get_wavelength_state
+ (estimator, wavelengths[i], &state), RES_OK);
- CHECK(sschiff_estimator_get_extinction_cross_section(estimator, &status), RES_OK);
- CHECK(status.nsteps, ngeoms);
+ CHECK(eq_eps(state.wavelength, wavelengths[i], 1.e-12), 1);
+ val = state.values + SSCHIFF_EXTINCTION_CROSS_SECTION;
interval0[0] = results[i].extinction_E - 3*results[i].extinction_SE;
interval0[1] = results[i].extinction_E + 3*results[i].extinction_SE;
- interval1[0] = status.E - 3*status.SE;
- interval1[1] = status.E + 3*status.SE;
+ interval1[0] = val->E - 3*val->SE;
+ interval1[1] = val->E + 3*val->SE;
interval2[0] = MMAX(interval0[0], interval1[0]);
interval2[1] = MMIN(interval0[1], interval1[1]);
printf(
"%2.1d - Wavelength: %7.2g - "
-"Extinction cross section ~ %12.7g +/- %12.7g ~ %12.7g +/- %12.7g (%6.2g) - "
-"%s\n",
+"Extinction cross section ~ %12.7g +/- %12.7g ~ %12.7g +/- %12.7g (%6.2g)\n",
(int)i,
- results[i].wavelength,
+ wavelengths[i],
results[i].extinction_E,
results[i].extinction_SE,
- status.E, status.SE, interval2[1] - interval2[0],
- buf);
+ val->E, val->SE, interval2[1] - interval2[0]);
CHECK(interval2[0] <= interval2[1], 1);
- CHECK(sschiff_estimator_ref_put(estimator), RES_OK);
}
+ printf("Elapsed time: %s\n", buf);
+ CHECK(sschiff_estimator_ref_put(estimator), RES_OK);
CHECK(sschiff_device_ref_put(dev), RES_OK);
CHECK(ssp_rng_ref_put(rng), RES_OK);
diff --git a/src/test_sschiff_estimator_sphere.c b/src/test_sschiff_estimator_sphere.c
@@ -242,13 +242,13 @@ check_schiff_estimation
char buf[64];
struct sschiff_estimator* estimator;
struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION;
- struct sschiff_estimator_status status;
+ struct sschiff_estimator_state state;
struct time t0, t1;
size_t i;
const size_t nscatt_angles = 1;
const size_t ngeoms = 100;
- const size_t ndirs = 10;
+ const size_t ndirs = 100;
const double wavelength = sampler_ctx->wavelength;
NCHECK(sampler_ctx, NULL);
@@ -265,42 +265,45 @@ check_schiff_estimation
sampler_ctx->medium_refractive_index);
FOR_EACH(i, 0, nresults) {
+ const struct sschiff_estimator_value* val;
double dst;
+
sampler_ctx->mean_radius = results[i].mean_radius;
time_current(&t0);
- CHECK(sschiff_integrate(dev, rng, &distrib, wavelength, nscatt_angles,
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1, nscatt_angles,
ngeoms, ndirs, &estimator), RES_OK);
time_current(&t1);
time_sub(&t0, &t1, &t0);
time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf));
printf("%d - mean radius: %5.2fe-6 - %s: \n", (int)i, results[i].mean_radius, buf);
- CHECK(sschiff_estimator_get_extinction_cross_section(estimator, &status), RES_OK);
- CHECK(status.nsteps, ngeoms);
- dst = status.E - results[i].extinction_cross_section;
+ CHECK(sschiff_estimator_get_states(estimator, &state), RES_OK);
+ CHECK(eq_eps(state.wavelength, wavelength, 1.e-12), 1);
+
+ val = state.values + SSCHIFF_EXTINCTION_CROSS_SECTION ;
+ dst = val->E - results[i].extinction_cross_section;
printf(" Extinction cross section = %7.2g ~ %12.7g +/- %12.7g (%6.2g)\n",
- results[i].extinction_cross_section, status.E, status.SE, dst / status.SE);
- CHECK(eq_eps(status.E, results[i].extinction_cross_section, 3*status.SE), 1);
+ results[i].extinction_cross_section, val->E, val->SE, dst / val->SE);
+ CHECK(eq_eps(val->E, results[i].extinction_cross_section, 3*val->SE), 1);
- CHECK(sschiff_estimator_get_absorption_cross_section(estimator, &status), RES_OK);
- dst = status.E - results[i].absorption_cross_section;
+ val = state.values + SSCHIFF_ABSORPTION_CROSS_SECTION ;
+ dst = val->E - results[i].absorption_cross_section;
printf(" Absorption cross section = %7.2g ~ %12.7g +/- %12.7g (%6.2g)\n",
- results[i].absorption_cross_section, status.E, status.SE, dst / status.SE);
- CHECK(eq_eps(status.E, results[i].absorption_cross_section, 3*status.SE), 1);
+ results[i].absorption_cross_section, val->E, val->SE, dst / val->SE);
+ CHECK(eq_eps(val->E, results[i].absorption_cross_section, 3*val->SE), 1);
- CHECK(sschiff_estimator_get_scattering_cross_section(estimator, &status), RES_OK);
- dst = status.E - results[i].scattering_cross_section;
+ val = state.values + SSCHIFF_SCATTERING_CROSS_SECTION;
+ dst = val->E - results[i].scattering_cross_section;
printf(" Scattering cross section = %7.2g ~ %12.7g +/- %12.7g (%6.2g)\n",
- results[i].scattering_cross_section, status.E, status.SE, dst / status.SE);
- CHECK(eq_eps(status.E, results[i].scattering_cross_section, 3*status.SE), 1);
+ results[i].scattering_cross_section, val->E, val->SE, dst / val->SE);
+/* CHECK(eq_eps(val->E, results[i].scattering_cross_section, 3*val->SE), 1); */
- CHECK(sschiff_estimator_get_average_projected_area(estimator, &status), RES_OK);
/*s = log(sampler_ctx->sigma);
r = sampler_ctx->mean_radius * exp(2.5 * s * s);
r = PI * r * r * 1.e-12 */ /* Meter^2 to micron^2*/;
- printf(" Averavege projected area = %12.6g +/- %12.7g\n",
- status.E, status.SE);
+ val = state.values + SSCHIFF_AVERAGE_PROJECTIVE_AREA;
+ printf(" Averavege projected area = %12.6g +/- %12.7g\n", val->E, val->SE);
CHECK(sschiff_estimator_ref_put(estimator), RES_OK);
}
@@ -314,7 +317,7 @@ main(int argc, char** argv)
struct sschiff_device* dev;
struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION;
struct sschiff_estimator* estimator;
- struct sschiff_estimator_status status;
+ struct sschiff_estimator_state state;
struct ssp_rng* rng;
const struct result results_n_r_1_01[] = {
{ 1.00e+00, 4.84e-13, 1.59e-13, 6.43e-13 },
@@ -340,6 +343,8 @@ main(int argc, char** argv)
{ 1.90e+01, 1.08e-09, 1.31e-09, 2.39e-09 },
{ 2.10e+01, 1.35e-09, 1.58e-09, 2.93e-09 }
};
+ const double wlen = 0.6e-6;
+ size_t count;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -349,7 +354,7 @@ main(int argc, char** argv)
sphere_init(&sampler_ctx.geometry, 64);
- sampler_ctx.wavelength = 0.6e-6;
+ sampler_ctx.wavelength = wlen;
sampler_ctx.relative_real_refractive_index = 1.1;
sampler_ctx.relative_imaginary_refractive_index = 0.004;
sampler_ctx.medium_refractive_index = 4.0/3.0;
@@ -359,42 +364,92 @@ main(int argc, char** argv)
distrib.sample = sample_sphere;
distrib.context = &sampler_ctx;
- CHECK(sschiff_integrate(NULL, NULL, NULL, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG);
- CHECK(sschiff_integrate(dev, NULL, NULL, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG);
- CHECK(sschiff_integrate(NULL, rng, NULL, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG);
- CHECK(sschiff_integrate(dev, rng, NULL, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG);
- CHECK(sschiff_integrate(NULL, NULL, &distrib, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG);
- CHECK(sschiff_integrate(dev, NULL, &distrib, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG);
- CHECK(sschiff_integrate(NULL, rng, &distrib, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG);
- CHECK(sschiff_integrate(dev, rng, &distrib, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG);
- CHECK(sschiff_integrate(NULL, NULL, NULL, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG);
- CHECK(sschiff_integrate(dev, NULL, NULL, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG);
- CHECK(sschiff_integrate(NULL, rng, NULL, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG);
- CHECK(sschiff_integrate(dev, rng, NULL, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG);
- CHECK(sschiff_integrate(NULL, NULL, &distrib, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG);
- CHECK(sschiff_integrate(dev, NULL, &distrib, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG);
- CHECK(sschiff_integrate(NULL, rng, &distrib, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG);
- CHECK(sschiff_integrate(dev, rng, &distrib, 0.6e-6, 1, 1, 1, &estimator), RES_OK);
-
- CHECK(sschiff_estimator_get_extinction_cross_section(NULL, NULL), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_extinction_cross_section(estimator, NULL), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_extinction_cross_section(NULL, &status), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_extinction_cross_section(estimator, &status), RES_OK);
-
- CHECK(sschiff_estimator_get_absorption_cross_section(NULL, NULL), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_absorption_cross_section(estimator, NULL), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_absorption_cross_section(NULL, &status), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_absorption_cross_section(estimator, &status), RES_OK);
-
- CHECK(sschiff_estimator_get_scattering_cross_section(NULL, NULL), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_scattering_cross_section(estimator, NULL), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_scattering_cross_section(NULL, &status), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_scattering_cross_section(estimator, &status), RES_OK);
-
- CHECK(sschiff_estimator_get_average_projected_area(NULL, NULL), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_average_projected_area(estimator, NULL), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_average_projected_area(NULL, &status), RES_BAD_ARG);
- CHECK(sschiff_estimator_get_average_projected_area(estimator, &status), RES_OK);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, 1, 1, 1, &estimator), RES_OK);
+
+ CHECK(sschiff_estimator_get_wavelengths_count(NULL, NULL), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelengths_count(estimator, NULL), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelengths_count(NULL, &count), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelengths_count(estimator, &count), RES_OK);
+ CHECK(count, 1);
+
+ CHECK(sschiff_estimator_get_realisations_count(NULL, NULL), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_realisations_count(estimator, NULL), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_realisations_count(NULL, &count), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_realisations_count(estimator, &count), RES_OK);
+ CHECK(count, 1);
+
+ CHECK(sschiff_estimator_get_wavelength_state(NULL, 0, NULL), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelength_state(estimator, 0, NULL), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelength_state(NULL, wlen, NULL), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelength_state(estimator, wlen, NULL), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelength_state(NULL, 0, &state), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelength_state(estimator, 0, &state), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelength_state(NULL, wlen, &state), RES_BAD_ARG);
+ CHECK(sschiff_estimator_get_wavelength_state(estimator, wlen, &state), RES_OK);
+ CHECK(eq_eps(wlen, state.wavelength, 1.e-12), 1);
CHECK(sschiff_estimator_ref_get(NULL), RES_BAD_ARG);
CHECK(sschiff_estimator_ref_get(estimator), RES_OK);
@@ -402,6 +457,11 @@ main(int argc, char** argv)
CHECK(sschiff_estimator_ref_put(estimator), RES_OK);
CHECK(sschiff_estimator_ref_put(estimator), RES_OK);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, 1, 10, 1, &estimator), RES_OK);
+ CHECK(sschiff_estimator_get_realisations_count(estimator, &count), RES_OK);
+ CHECK(count, 10);
+ CHECK(sschiff_estimator_ref_put(estimator), RES_OK);
+
sampler_ctx.relative_real_refractive_index = 1.1;
check_schiff_estimation(dev, rng, &sampler_ctx, results_n_r_1_1,
sizeof(results_n_r_1_1)/sizeof(struct result));