star-sf

Set of surface and volume scattering functions
git clone git://git.meso-star.fr/star-sf.git
Log | Files | Refs | README | LICENSE

test_ssf_phase_rdgfa.c (4506B)


      1 /* Copyright (C) 2016-2018, 2021-2025 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "ssf.h"
     17 #include "test_ssf_utils.h"
     18 
     19 #include <string.h>
     20 
     21 int
     22 main(int argc, char** argv)
     23 {
     24   static const size_t NSAMPS = 10000;
     25 
     26   struct mem_allocator allocator;
     27   struct ssf_info info = SSF_INFO_NULL;
     28   struct ssf_phase_rdgfa_setup_args args = SSF_PHASE_RDGFA_SETUP_ARGS_DEFAULT;
     29   struct ssf_phase_rdgfa_desc desc = SSF_PHASE_RDGFA_DESC_NULL;
     30   struct ssf_phase_rdgfa_interval interval = SSF_PHASE_RDGFA_INTERVAL_NULL;
     31   struct ssf_phase* phase;
     32   struct ssf_phase* dummy;
     33   struct ssp_rng* rng;
     34   double cumulative_prev;
     35   double wo[3];
     36   int err = 0;
     37   size_t i;
     38   (void)argc, (void)argv;
     39 
     40   if(argc <= 1) {
     41     fprintf(stderr, "Usage: %s <simd_none|simd_128|simd_256>\n", argv[0]);
     42     goto error;
     43   }
     44 
     45   if(!strcmp(argv[1], "simd_none")) {
     46     args.simd = SSF_SIMD_NONE;
     47   } else if(!strcmp(argv[1], "simd_128")) {
     48     args.simd = SSF_SIMD_128;
     49   } else if(!strcmp(argv[1], "simd_256")) {
     50     args.simd = SSF_SIMD_256;
     51   } else {
     52     fprintf(stderr, "Invalid argument '%s'.\n", argv[1]);
     53     goto error;
     54   }
     55 
     56   CHK(ssf_get_info(NULL) == RES_BAD_ARG);
     57   CHK(ssf_get_info(&info) == RES_OK);
     58   if(args.simd == SSF_SIMD_128) {
     59     CHK(info.simd_128 != 0);
     60   }
     61   if(args.simd == SSF_SIMD_256) {
     62     CHK(info.simd_256 != 0);
     63   }
     64 
     65   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
     66   CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
     67 
     68   CHK(ssf_phase_create(&allocator, &ssf_phase_rdgfa, &phase) == RES_OK);
     69   CHK(ssf_phase_create(&allocator, &phase_dummy, &dummy) == RES_OK);
     70 
     71   args.wavelength = 532;
     72   args.fractal_dimension = 1.80;
     73   args.gyration_radius =  111.6372805638;
     74   args.nintervals = 1000;
     75   CHK(ssf_phase_rdgfa_setup(NULL, &args) == RES_BAD_ARG);
     76   CHK(ssf_phase_rdgfa_setup(phase, NULL) == RES_BAD_ARG);
     77   CHK(ssf_phase_rdgfa_setup(dummy, &args) == RES_BAD_ARG);
     78   CHK(ssf_phase_rdgfa_setup(phase, &args) == RES_OK);
     79 
     80   CHK(ssf_phase_rdgfa_get_desc(NULL, &desc) == RES_BAD_ARG);
     81   CHK(ssf_phase_rdgfa_get_desc(phase, NULL) == RES_BAD_ARG);
     82   CHK(ssf_phase_rdgfa_get_desc(dummy, &desc) == RES_BAD_ARG);
     83   CHK(ssf_phase_rdgfa_get_desc(phase, &desc) == RES_OK);
     84 
     85   CHK(desc.wavelength == args.wavelength);
     86   CHK(desc.fractal_dimension == args.fractal_dimension);
     87   CHK(desc.gyration_radius == args.gyration_radius);
     88   CHK(desc.nintervals = args.nintervals);
     89 
     90   CHK(ssf_phase_rdgfa_get_interval(NULL, 0, &interval) == RES_BAD_ARG);
     91   CHK(ssf_phase_rdgfa_get_interval(phase, desc.nintervals+1, &interval)
     92     == RES_BAD_ARG);
     93   CHK(ssf_phase_rdgfa_get_interval(phase, 0, NULL) == RES_BAD_ARG);
     94 
     95   cumulative_prev = 0;
     96   FOR_EACH(i, 0, desc.nintervals) {
     97     double range[2];
     98 
     99     range[0] = PI/(double)desc.nintervals * (double)(i+0);
    100     range[1] = PI/(double)desc.nintervals * (double)(i+1);
    101 
    102     CHK(ssf_phase_rdgfa_get_interval(phase, i, &interval) == RES_OK);
    103     CHK(eq_eps(interval.range[0], range[0], fabs(range[0]*1.e-6)));
    104     CHK(eq_eps(interval.range[1], range[1], fabs(range[1]*1.e-6)));
    105     CHK(interval.cumulative > cumulative_prev);
    106     CHK(interval.cumulative <= 1.0);
    107 
    108     cumulative_prev = interval.cumulative;
    109   }
    110 
    111   ssp_ran_sphere_uniform(rng, wo, NULL);
    112   FOR_EACH(i, 0, NSAMPS) {
    113     double wi[3];
    114     double pdf;
    115     ssf_phase_sample(phase, rng, wo, wi, &pdf);
    116     CHK(eq_eps(pdf, ssf_phase_eval(phase, wo, wi), fabs(pdf*1.e-6)));
    117     CHK(d3_is_normalized(wi));
    118 
    119 #if 0
    120     fprintf(stderr, "v %g %g %g\n", wi[0]*pdf, wi[1]*pdf, wi[2]*pdf);
    121     fprintf(stderr, "p %lu\n", (unsigned long)(i+1));
    122 #endif
    123   }
    124 
    125   CHK(ssf_phase_ref_put(phase) == RES_OK);
    126   CHK(ssf_phase_ref_put(dummy) == RES_OK);
    127   CHK(ssp_rng_ref_put(rng) == RES_OK);
    128 
    129   check_memory_allocator(&allocator);
    130   mem_shutdown_proxy_allocator(&allocator);
    131   CHK(mem_allocated_size() == 0);
    132 exit:
    133   return err;
    134 error:
    135   err = -1;
    136   goto exit;
    137 }
    138