commit f519ed6cab752075a1749e6656a2a75e59743deb
parent 66fa585aff034ac42504b3b92ab3ea0058291f30
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 16 Feb 2016 13:31:52 +0100
Update the schiff API to handle scattering angle distributions
Refactor the estimator to prepare the integration of phase functions.
Diffstat:
6 files changed, 232 insertions(+), 116 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -59,7 +59,10 @@ set(VERSION_MINOR 3)
set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
-set(SSCHIFF_FILES_SRC sschiff_device.c sschiff_estimator.c)
+set(SSCHIFF_FILES_SRC
+ sschiff_device.c
+ sschiff_estimator.c
+ sschiff_scattering_angles_distributions.c)
set(SSCHIFF_FILES_INC_API sschiff.h)
set(SSCHIFF_FILES_INC sschiff_device.h)
set(SSCHIFF_FILES_DOC COPYING.en COPYING.fr README.md)
diff --git a/src/sschiff.h b/src/sschiff.h
@@ -110,14 +110,25 @@ struct sschiff_estimator_state {
} values[SSCHIFF_DATA_COUNT__];
};
+/* Type of the function use to distribute the scattering angles in [0, PI].
+ * nangles is assumed to be greater than or equal to 2 and the angles is
+ * ensured to have `nangles' entries. */
+typedef void (*sschiff_scattering_angles_distribution_T)
+ (double angles[], const size_t nangles);
+
/* Opaque types */
struct sschiff_device;
struct sschiff_estimator;
+BEGIN_DECLS
+
+/* Built-in uniform distribution of scattering angles */
+SSCHIFF_API const sschiff_scattering_angles_distribution_T
+sschiff_uniform_scattering_angles;
+
/*******************************************************************************
* Star Schiff API
******************************************************************************/
-BEGIN_DECLS
SSCHIFF_API res_T
sschiff_device_create
@@ -143,7 +154,8 @@ sschiff_integrate
struct sschiff_geometry_distribution* distribution,
const double* wavelengths, /* list of wavelengths to estimate in micron */
const size_t wavelengths_count, /* # wavelengths to estimate */
- const size_t scattering_angles_count, /* # of scattering angles to handle */
+ const sschiff_scattering_angles_distribution_T angles, /* angles distrib */
+ const size_t scattering_angles_count, /* # scattering angles. Must be >= 2 */
const size_t sampled_geometries_count, /* # geometries to sample */
const size_t sampled_directions_count, /* # directions to sample per geometry */
struct sschiff_estimator** estimator);
diff --git a/src/sschiff_estimator.c b/src/sschiff_estimator.c
@@ -264,6 +264,48 @@ compute_path_length
return RES_OK;
}
+static FINLINE void
+accum_cross_section
+ (const struct sschiff_material_properties* props,
+ const double* wavelengths,
+ const size_t nwavelengths,
+ const double rcp_pdf,
+ const double path_length,
+ struct accum* accums)
+{
+ size_t iwlen;
+ ASSERT(props && wavelengths && nwavelengths && rcp_pdf>0 && path_length>0);
+
+ 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 = wavelengths[iwlen] / n_e;
+ k_e = 2.0 * PI / lambda_e;
+
+ /* 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;
+
+ /* 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;
+
+ /* Scattering cross section */
+ w_scattering = w_extinction - w_absorption;
+ accums[iwlen].weights[SSCHIFF_SCATTERING_CROSS_SECTION] += w_scattering;
+
+ /* Average projected area */
+ accums[iwlen].weights[SSCHIFF_AVERAGE_PROJECTED_AREA] += rcp_pdf;
+ }
+}
+
static res_T
accum_monte_carlo_weight
(struct sschiff_device* dev,
@@ -272,6 +314,8 @@ accum_monte_carlo_weight
const struct sschiff_material_properties* props,
const double* wavelengths, /* In micron */
const size_t nwavelengths,
+ const double* angles, /* Scattering angles */
+ const size_t nangles,
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 */
@@ -289,8 +333,8 @@ accum_monte_carlo_weight
float x[3], y[3];
float rcp_pdf;
res_T res = RES_OK;
- ASSERT(scn && rng && props && wavelengths && accums && basis && pos);
- ASSERT(lower && upper);
+ ASSERT(scn && rng && props && wavelengths && nwavelengths && angles && nangles);
+ ASSERT(accums && basis && pos && lower && upper);
f2_sub(plane_size, upper, lower); /* In micron */
rcp_pdf = plane_size[0] * plane_size[1];
@@ -304,6 +348,8 @@ accum_monte_carlo_weight
f3_add(org, pos, f3_mulf(org, axis_z, lower[2]));
do {
+ double path_length;
+
/* Uniformly sample a position onto the projection plane and use it as the
* origin of the ray to trace */
sample[0] = ssp_rng_uniform_double(rng, -1.0, 1.0);
@@ -314,45 +360,21 @@ accum_monte_carlo_weight
S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit));
- if(!S3D_HIT_NONE(&hit)) {
- double path_length;
- size_t iwlen;
+ if(S3D_HIT_NONE(&hit)) /* NULL cross section and phase function weight */
+ break;
- res = compute_path_length(dev, scn, &hit, ray_org, axis_z, &path_length);
- if(res != RES_OK) { /* Handle numerical/geometry issues */
- ++nfailures;
- continue;
- }
-
- 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 = wavelengths[iwlen] / n_e;
- k_e = 2.0 * PI / lambda_e;
-
- /* 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;
- /* 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;
+ res = compute_path_length(dev, scn, &hit, ray_org, axis_z, &path_length);
+ if(res != RES_OK) { /* Handle numerical/geometry issues */
+ ++nfailures;
+ continue;
+ }
+ accum_cross_section
+ (props, wavelengths, nwavelengths, rcp_pdf, path_length, accums);
- /* Scattering cross section */
- w_scattering = w_extinction - w_absorption;
- accums[iwlen].weights[SSCHIFF_SCATTERING_CROSS_SECTION] += w_scattering;
+ /* TODO phase function integration */
+ (void)angles, (void)nangles;
- /* Average projected area */
- accums[iwlen].weights[SSCHIFF_AVERAGE_PROJECTED_AREA] += rcp_pdf;
- }
- }
} while(res != RES_OK && nfailures < MAX_FAILURES);
if(res != RES_OK) {
@@ -370,6 +392,8 @@ radiative_properties
const int istep,
const double* wavelengths, /* Sorted in ascending order */
const size_t nwavelengths,
+ const double* angles, /* Sorted in ascending order in [0, PI] */
+ const size_t nangles,
const size_t ndirs,
struct s3d_scene* scene,
const struct sschiff_material_properties* props,
@@ -434,7 +458,7 @@ radiative_properties
}
res = accum_monte_carlo_weight(dev, scene, rng, props, wavelengths,
- nwavelengths, basis, centroid, lower, upper, accums);
+ nwavelengths, angles, nangles, basis, centroid, lower, upper, accums);
if(res != RES_OK) goto error;
#if 0
@@ -550,6 +574,7 @@ sschiff_integrate
struct sschiff_geometry_distribution* distrib,
const double* wavelengths,
const size_t nwavelengths,
+ const sschiff_scattering_angles_distribution_T angles_distrib,
const size_t nangles,
const size_t ngeoms,
const size_t ndirs,
@@ -563,13 +588,15 @@ sschiff_integrate
struct s3d_scene** scenes = NULL;
struct ssp_rng** rngs = NULL;
struct ssp_rng_proxy* rng_proxy = NULL;
+ double* angles = NULL;
size_t i;
int igeom;
ATOMIC res = (ATOMIC)RES_OK;
(void)nangles;
- if(!dev || !rng || !distrib || !wavelengths || !nwavelengths || !nangles
- || !ngeoms || !ndirs || !out_estimator || !check_distribution(distrib)) {
+ if(!dev || !rng || !distrib || !wavelengths || !nwavelengths
+ || !angles_distrib || nangles < 2 || !ngeoms || !ndirs || !out_estimator
+ || !check_distribution(distrib)) {
return RES_BAD_ARG;
}
@@ -583,6 +610,24 @@ sschiff_integrate
log_error(dev, "Couldn't create the proxy allocator\n");
goto error;
}
+
+ /* Setup the scattering angles */
+ angles = sa_add(angles, nangles);
+ if(!angles) {
+ log_error(dev,
+ "Not enough memory: couldn't allocate the list of scattering angles.\n");
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ angles_distrib(angles, nangles);
+ if(angles[0] != 0.f && !eq_eps(angles[1], PI, 1.e-6)) {
+ log_error(dev,
+"Invalid scattering angles distribution. The first and the last angles must be\n"
+"0 and PI, respectively\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
/* Create the containers of per thread data structures */
if(!sa_add(mtls, dev->nthreads)) {
log_error(dev,
@@ -707,8 +752,8 @@ sschiff_integrate
/* Schiff Estimation */
res_local = radiative_properties(dev, rngs[ithread], igeom, wlengths,
- nwavelengths, ndirs, scenes[ithread], mtls[ithread], mc_accums[ithread],
- accums[ithread]);
+ nwavelengths, angles, nangles, ndirs, scenes[ithread], mtls[ithread],
+ mc_accums[ithread], accums[ithread]);
if(res != RES_OK) ATOMIC_SET(&res, res_local);
S3D(scene_end_session(scenes[ithread]));
@@ -731,6 +776,7 @@ sschiff_integrate
exit:
if(rng_proxy) SSP(rng_proxy_ref_put(rng_proxy));
+ if(angles) sa_release(angles);
/* Release per thread data */
if(mtls) {
FOR_EACH(i, 0, dev->nthreads) if(mtls[i]) sa_release(mtls[i]);
diff --git a/src/sschiff_scattering_angles_distributions.c b/src/sschiff_scattering_angles_distributions.c
@@ -0,0 +1,48 @@
+/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com)
+ *
+ * This software is governed by the CeCILL license under French law and
+ * abiding by the rules of distribution of free software. You can use,
+ * modify and/or redistribute the software under the terms of the CeCILL
+ * license as circulated by CEA, CNRS and INRIA at the following URL
+ * "http://www.cecill.info".
+ *
+ * As a counterpart to the access to the source code and rights to copy,
+ * modify and redistribute granted by the license, users are provided only
+ * with a limited warranty and the software's author, the holder of the
+ * economic rights, and the successive licensors have only limited
+ * liability.
+ *
+ * In this respect, the user's attention is drawn to the risks associated
+ * with loading, using, modifying and/or developing or reproducing the
+ * software by the user in light of its specific status of free software,
+ * that may mean that it is complicated to manipulate, and that also
+ * therefore means that it is reserved for developers and experienced
+ * professionals having in-depth computer knowledge. Users are therefore
+ * encouraged to load and test the software's suitability as regards their
+ * requirements in conditions enabling the security of their systems and/or
+ * data to be ensured and, more generally, to use and operate it in the
+ * same conditions as regards security.
+ *
+ * The fact that you are presently reading this means that you have had
+ * knowledge of the CeCILL license and that you accept its terms. */
+
+#include "sschiff.h"
+#include <rsys/math.h>
+
+static void
+uniform(double* angles, const size_t nangles)
+{
+ size_t iangle;
+ const double step = PI / (double)(nangles - 1);
+ ASSERT(nangles >= 2);
+
+ angles[0] = 0.0;
+ FOR_EACH(iangle, 1, nangles-1) {
+ angles[iangle] = angles[iangle-1] + step;
+ }
+ angles[nangles-1] = PI;
+}
+
+const sschiff_scattering_angles_distribution_T
+sschiff_uniform_scattering_angles = uniform;
+
diff --git a/src/test_sschiff_estimator_cylinder.c b/src/test_sschiff_estimator_cylinder.c
@@ -559,7 +559,7 @@ main(int argc, char** argv)
2.010619438e+2, 2.018997018e+2, 2.027374599e+2
};
const size_t nx = sizeof(x)/sizeof(double);
- const size_t nscatt_angles = 1;
+ const size_t nscatt_angles = 2;
const size_t ngeoms = 100;
const size_t ndirs = 10;
size_t i;
@@ -587,8 +587,9 @@ main(int argc, char** argv)
distrib.context = &sampler_ctx;
time_current(&t0);
- CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1, nscatt_angles,
- ngeoms, ndirs, &estimator), RES_OK);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1,
+ sschiff_uniform_scattering_angles, 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));
diff --git a/src/test_sschiff_estimator_sphere.c b/src/test_sschiff_estimator_sphere.c
@@ -246,7 +246,7 @@ check_schiff_estimation
struct time t0, t1;
size_t i;
- const size_t nscatt_angles = 1;
+ const size_t nscatt_angles = 2;
const size_t ngeoms = 100;
const size_t ndirs = 100;
const double wavelength = sampler_ctx->wavelength;
@@ -271,8 +271,8 @@ check_schiff_estimation
sampler_ctx->mean_radius = results[i].mean_radius;
time_current(&t0);
- CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1, nscatt_angles,
- ngeoms, ndirs, &estimator), RES_OK);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1,
+ sschiff_uniform_scattering_angles, 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));
@@ -365,70 +365,75 @@ main(int argc, char** argv)
distrib.sample = sample_sphere;
distrib.context = &sampler_ctx;
- 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_integrate(NULL, NULL, NULL, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG);
+
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1,
+ sschiff_uniform_scattering_angles, 1, 1, 1, &estimator), RES_BAD_ARG);
+ CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1,
+ sschiff_uniform_scattering_angles, 2, 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);
@@ -458,7 +463,8 @@ 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_integrate(dev, rng, &distrib, &wlen, 1,
+ sschiff_uniform_scattering_angles, 2, 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);