Tests for interpolation stack interface routines.
#include <stdio.h>
#include <math.h>
#include "tests.h"
#define ARGS(...) __VA_ARGS__
#define _GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N
#define EXPAND(x) x
#define FOREACH(name, ...) \
{ \
enum {NUM_ ## name = sizeof( name ) / sizeof( name [0])}; \
int name ## _idx[2]; \
for (name ## _idx[0] = 0; name ## _idx[0] < NUM_ ## name; \
++ name ## _idx[0]) { \
for (name ## _idx[1] = 0; name ## _idx[1] < NUM_ ## name; \
++ name ## _idx[1]) { \
configs_differ += (name ## _idx[0]) != (name ## _idx[1]); \
{__VA_ARGS__} \
configs_differ -= (name ## _idx[0]) != (name ## _idx[1]); \
} \
} \
}
#define FOREACH_ENUM(name, values, ...) \
{ \
enum yac_ ## name name [] = {values}; \
FOREACH(name, __VA_ARGS__) \
}
#define FOREACH_TYPE(name, type, values, ...) \
{ \
type name[] = {values}; \
FOREACH(name, __VA_ARGS__) \
}
#define FOREACH_INT(name, values, ...) \
FOREACH_TYPE(name, int, ARGS(values), __VA_ARGS__)
#define FOREACH_DBLE(name, values, ...) \
FOREACH_TYPE(name, double, ARGS(values), __VA_ARGS__)
#define FOREACH_BOOL(name, ...) FOREACH_INT(name, ARGS(0, 1), __VA_ARGS__)
#define FOREACH_STRING(name, values, ...) \
FOREACH_TYPE(name, ARGS(char const *), ARGS(values), __VA_ARGS__)
#define FOREACH_STRUCT(name, struct_name, values, ...) \
FOREACH_TYPE(name, ARGS(struct struct_name), ARGS(values), __VA_ARGS__)
#define _CHECK_STACKS(interp_name, config) \
{ \
int config_idx; \
struct yac_interp_stack_config * a = yac_interp_stack_config_new(); \
struct yac_interp_stack_config * b = yac_interp_stack_config_new(); \
config_idx = 0, yac_interp_stack_config_add_ ## interp_name ( a, config ); \
config_idx = 1, yac_interp_stack_config_add_ ## interp_name ( b, config ); \
check_compare_stacks(a, b, configs_differ); \
}
#define _CONFIG_ARGS1(arg_name) arg_name[arg_name ## _idx[config_idx]]
#define _CONFIG_ARGS2(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS1(__VA_ARGS__)
#define _CONFIG_ARGS3(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS2(__VA_ARGS__)
#define _CONFIG_ARGS4(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS3(__VA_ARGS__)
#define _CONFIG_ARGS5(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS4(__VA_ARGS__)
#define _CONFIG_ARGS6(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS5(__VA_ARGS__)
#define _CONFIG_ARGS7(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS6(__VA_ARGS__)
#define _CONFIG_ARGS8(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS7(__VA_ARGS__)
#define _CONFIG_ARGS9(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS8(__VA_ARGS__)
#define _CONFIG_ARGS10(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS9(__VA_ARGS__)
#define _CONFIG_ARGS11(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS10(__VA_ARGS__)
#define _CONFIG_ARGS12(arg_name, ...) \
_CONFIG_ARGS1(arg_name), _CONFIG_ARGS11(__VA_ARGS__)
#define CHECK_STACKS(interp_name, ... ) \
_CHECK_STACKS(interp_name, \
EXPAND(_GET_NTH_ARG(__VA_ARGS__, _CONFIG_ARGS12, \
_CONFIG_ARGS11, \
_CONFIG_ARGS10, \
_CONFIG_ARGS9, \
_CONFIG_ARGS8, \
_CONFIG_ARGS7, \
_CONFIG_ARGS6, \
_CONFIG_ARGS5, \
_CONFIG_ARGS4, \
_CONFIG_ARGS3, \
_CONFIG_ARGS2, \
_CONFIG_ARGS1)(__VA_ARGS__)))
static void check_compare_stacks(
int configs_differ);
static void yac_interp_stack_config_add_spmap_(
double spread_distance, double max_search_distance,
struct yac_spmap_cell_area_config src_cell_area_config,
struct yac_spmap_cell_area_config tgt_cell_area_config);
int configs_differ = 0;
{
check_compare_stacks(a, b, 1);
}
{
check_compare_stacks(a, b, 0);
}
FOREACH_ENUM(
interp_avg_weight_type,
FOREACH_BOOL(
partial_coverage,
CHECK_STACKS(average, interp_avg_weight_type, partial_coverage)))
FOREACH_ENUM(
interp_ncc_weight_type,
FOREACH_BOOL(
partial_coverage,
CHECK_STACKS(ncc, interp_ncc_weight_type, partial_coverage)))
FOREACH_ENUM(
interp_nnn_weight_type,
FOREACH_INT(
counts, ARGS(1,3,9),
FOREACH_DBLE(
max_search_distance, ARGS(0.0, M_PI_2),
FOREACH_DBLE(
scales, -1.0,
CHECK_STACKS(
nnn, interp_nnn_weight_type, counts,
max_search_distance, scales)))))
FOREACH_ENUM(
interp_nnn_weight_type,
FOREACH_INT(
counts, ARGS(1,3,9),
FOREACH_DBLE(
max_search_distance, ARGS(0.0, M_PI_2),
FOREACH_DBLE(
scales, ARGS(0.5, 1.0),
CHECK_STACKS(
nnn, interp_nnn_weight_type, counts,
max_search_distance, scales)))))
FOREACH_INT(
order, ARGS(1,2),
FOREACH_BOOL(
enforced_conserv,
FOREACH_BOOL(
partial_coverage,
FOREACH_ENUM(
interp_method_conserv_normalisation,
CHECK_STACKS(conservative,
order, enforced_conserv, partial_coverage,
interp_method_conserv_normalisation)))))
{
#define CELL_AREA_CONFIGS \
{.cell_area_provider = YAC_INTERP_SPMAP_CELL_AREA_YAC, \
.sphere_radius = 1.0, \
.file_config.filename = NULL, \
.file_config.varname = NULL, \
.file_config.min_global_id = 0}, \
{.cell_area_provider = YAC_INTERP_SPMAP_CELL_AREA_YAC, \
.sphere_radius = 2.0, \
.file_config.filename = NULL, \
.file_config.varname = NULL, \
.file_config.min_global_id = 0}, \
{.cell_area_provider = YAC_INTERP_SPMAP_CELL_AREA_FILE, \
.sphere_radius = 0.0, \
.file_config.filename = "area.nc", \
.file_config.varname = "cell_area", \
.file_config.min_global_id = 0}, \
{.cell_area_provider = YAC_INTERP_SPMAP_CELL_AREA_FILE, \
.sphere_radius = 0.0, \
.file_config.filename = "area.nc_", \
.file_config.varname = "cell_area", \
.file_config.min_global_id = 0}, \
{.cell_area_provider = YAC_INTERP_SPMAP_CELL_AREA_FILE, \
.sphere_radius = 0.0, \
.file_config.filename = "area.nc", \
.file_config.varname = "cell_area_", \
.file_config.min_global_id = 0}, \
{.cell_area_provider = YAC_INTERP_SPMAP_CELL_AREA_FILE, \
.sphere_radius = 0.0, \
.file_config.filename = "area.nc", \
.file_config.varname = "cell_area", \
.file_config.min_global_id = 1}, \
{.cell_area_provider = YAC_INTERP_SPMAP_CELL_AREA_FILE, \
.sphere_radius = 0.0, \
.file_config.filename = "area.nc_", \
.file_config.varname = "cell_area_", \
.file_config.min_global_id = 1} \
FOREACH_STRUCT(
src_cell_area_config, yac_spmap_cell_area_config, CELL_AREA_CONFIGS,
FOREACH_STRUCT(
tgt_cell_area_config, yac_spmap_cell_area_config, CELL_AREA_CONFIGS,
FOREACH_DBLE(
spread_distance, ARGS(0.0, 1.0, 2.0),
FOREACH_DBLE(
max_search_distance, ARGS(0.0, 1.0, 2.0),
FOREACH_ENUM(
interp_spmap_weight_type,
FOREACH_ENUM(
interp_spmap_scale_type,
ARGS(
CHECK_STACKS(spmap_,
spread_distance, max_search_distance,
interp_spmap_weight_type, interp_spmap_scale_type,
src_cell_area_config, tgt_cell_area_config)))))))
}
FOREACH_STRING(
filename, ARGS(
"test_interp_stack_config_file_a.nc",
"test_interp_stack_config_file_b.nc"),
CHECK_STACKS(user_file, filename))
FOREACH_DBLE(
fixed_value, ARGS(-1.0, 0.0, 1.0),
CHECK_STACKS(fixed, fixed_value))
FOREACH_STRING(
constructor_key, ARGS(NULL, "constructor_a", "constructor_b"),
FOREACH_STRING(
do_search_key, ARGS(NULL, "do_search_key_a", "do_search_key_b"),
CHECK_STACKS(check, constructor_key, do_search_key)))
FOREACH_INT(
creep_distance, ARGS(-1, 0, 1),
CHECK_STACKS(creep, creep_distance))
FOREACH_STRING(
compute_weights_key, ARGS("compute_weights_a", "compute_weights_b"),
CHECK_STACKS(user_callback, compute_weights_key))
return TEST_EXIT_CODE;
}
static void check_compare_stacks_(
int configs_differ) {
configs_differ = configs_differ != 0;
PUT_ERR("error in yac_interp_stack_config_compare (a != a)")
if ((cmp_a != cmp_b) ^ configs_differ)
if ((cmp_a != 0) ^ configs_differ)
if ((cmp_b != 0) ^ configs_differ)
}
static void check_compare_stacks(
int configs_differ) {
check_compare_stacks_(
check_compare_stacks_(a, b, configs_differ);
}
static void yac_interp_stack_config_add_spmap_(
double spread_distance, double max_search_distance,
struct yac_spmap_cell_area_config src_cell_area_config,
struct yac_spmap_cell_area_config tgt_cell_area_config) {
interp_stack_config,
spread_distance, max_search_distance,
weight_type, scale_type,
src_cell_area_config.sphere_radius,
src_cell_area_config.file_config.filename,
src_cell_area_config.file_config.varname,
src_cell_area_config.file_config.min_global_id,
tgt_cell_area_config.sphere_radius,
tgt_cell_area_config.file_config.filename,
tgt_cell_area_config.file_config.varname,
tgt_cell_area_config.file_config.min_global_id);
}
enum yac_interp_ncc_weight_type weight_type
int main(int argc, char **argv)
@ YAC_INTERP_AVG_ARITHMETIC
@ YAC_INTERP_CONSERV_DESTAREA
@ YAC_INTERP_CONSERV_FRACAREA
@ YAC_INTERP_NCC_DIST
distance weighted average of n source points
@ YAC_INTERP_NCC_AVG
average of n source points
@ YAC_INTERP_NNN_GAUSS
distance with Gauss weights of n source points
@ YAC_INTERP_NNN_RBF
radial basis functions
@ YAC_INTERP_NNN_AVG
average of n source points
@ YAC_INTERP_NNN_DIST
distance weighted average of n source points
@ YAC_INTERP_NNN_ZERO
all weights are set to zero
yac_interp_spmap_scale_type
@ YAC_INTERP_SPMAP_NONE
weights are not scaled
@ YAC_INTERP_SPMAP_INVTGTAREA
@ YAC_INTERP_SPMAP_SRCAREA
@ YAC_INTERP_SPMAP_FRACAREA
yac_interp_spmap_weight_type
int yac_interp_stack_config_compare(void const *a_, void const *b_)
void yac_interp_stack_config_add_spmap(struct yac_interp_stack_config *interp_stack_config, double spread_distance, double max_search_distance, enum yac_interp_spmap_weight_type weight_type, enum yac_interp_spmap_scale_type scale_type, double src_sphere_radius, char const *src_filename, char const *src_varname, int src_min_global_id, double tgt_sphere_radius, char const *tgt_filename, char const *tgt_varname, int tgt_min_global_id)
void yac_interp_stack_config_add_fixed(struct yac_interp_stack_config *interp_stack_config, double value)
void yac_interp_stack_config_add_average(struct yac_interp_stack_config *interp_stack_config, enum yac_interp_avg_weight_type reduction_type, int partial_coverage)
void yac_interp_stack_config_delete(struct yac_interp_stack_config *interp_stack_config)
struct yac_interp_stack_config * yac_interp_stack_config_copy(struct yac_interp_stack_config *interp_stack)
struct yac_interp_stack_config * yac_interp_stack_config_new()