ssol_ranst_sun_wl.c (5129B)
1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com) 2 * Copyright (C) 2016, 2018 CNRS 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include "ssol.h" 18 #include "ssol_ranst_sun_wl.h" 19 20 #include <star/ssp.h> 21 22 #include <rsys/double33.h> 23 #include <rsys/math.h> 24 #include <rsys/mem_allocator.h> 25 #include <rsys/rsys.h> 26 #include <rsys/ref_count.h> 27 28 /******************************************************************************* 29 * Distributions types for wavelengths 30 ******************************************************************************/ 31 struct ran_piecewise_wl_state { 32 struct ssp_ranst_piecewise_linear* spectrum; 33 }; 34 35 struct ran_dirac_wl_state { 36 double wavelength; 37 }; 38 39 enum wl_ran_type { 40 WL_DIRAC, 41 WL_PIECEWISE, 42 WL_TYPES_COUNT__ 43 }; 44 45 /* One single type for all distributions. Only the state type depends on the 46 * distribution type */ 47 struct ranst_sun_wl { 48 double(*get) 49 (const struct ranst_sun_wl* ran, struct ssp_rng* rng); 50 union { 51 struct ran_piecewise_wl_state piecewise; 52 struct ran_dirac_wl_state dirac; 53 } state; 54 enum wl_ran_type type; 55 56 ref_T ref; 57 struct mem_allocator* allocator; 58 }; 59 60 /******************************************************************************* 61 * Helper functions 62 ******************************************************************************/ 63 static void 64 distrib_sun_wl_release(ref_T* ref) 65 { 66 struct ranst_sun_wl* ran; 67 ASSERT(ref); 68 ran = CONTAINER_OF(ref, struct ranst_sun_wl, ref); 69 switch (ran->type) { 70 case WL_DIRAC: 71 break; 72 case WL_PIECEWISE: 73 SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum)); 74 ran->state.piecewise.spectrum = NULL; 75 break; 76 default: FATAL("Unreachable code\n"); break; 77 } 78 MEM_RM(ran->allocator, ran); 79 } 80 81 /******************************************************************************* 82 * Piecewise random variate 83 ******************************************************************************/ 84 static double 85 ran_piecewise_get 86 (const struct ranst_sun_wl* ran, 87 struct ssp_rng* rng) 88 { 89 ASSERT(ran && rng && ran->type == WL_PIECEWISE); 90 ASSERT(ran->state.piecewise.spectrum); 91 return ssp_ranst_piecewise_linear_get(ran->state.piecewise.spectrum, rng); 92 } 93 94 /******************************************************************************* 95 * Dirac distribution 96 ******************************************************************************/ 97 static double 98 ran_dirac_get 99 (const struct ranst_sun_wl* ran, 100 struct ssp_rng* rng) 101 { 102 (void) rng; 103 ASSERT(ran && rng && ran->type == WL_DIRAC); 104 return ran->state.dirac.wavelength; 105 } 106 107 /******************************************************************************* 108 * Local functions 109 ******************************************************************************/ 110 res_T 111 ranst_sun_wl_create 112 (struct mem_allocator* allocator, 113 struct ranst_sun_wl** out_ran) 114 { 115 struct ranst_sun_wl* ran = NULL; 116 117 if (!out_ran) return RES_BAD_ARG; 118 119 allocator = allocator ? allocator : &mem_default_allocator; 120 121 ran = MEM_CALLOC(allocator, 1, sizeof(struct ranst_sun_wl)); 122 if (!ran) return RES_MEM_ERR; 123 124 ref_init(&ran->ref); 125 ran->allocator = allocator; 126 *out_ran = ran; 127 128 return RES_OK; 129 } 130 131 res_T 132 ranst_sun_wl_ref_get(struct ranst_sun_wl* ran) 133 { 134 if (!ran) return RES_BAD_ARG; 135 ref_get(&ran->ref); 136 return RES_OK; 137 } 138 139 res_T 140 ranst_sun_wl_ref_put(struct ranst_sun_wl* ran) 141 { 142 if (!ran) return RES_BAD_ARG; 143 ref_put(&ran->ref, distrib_sun_wl_release); 144 return RES_OK; 145 } 146 147 double 148 ranst_sun_wl_get(const struct ranst_sun_wl* ran, struct ssp_rng* rng) 149 { 150 ASSERT(ran); 151 return ran->get(ran, rng); 152 } 153 154 res_T 155 ranst_sun_wl_setup 156 (struct ranst_sun_wl* ran, 157 const double* wavelengths, 158 const double* intensities, 159 const size_t sz) 160 { 161 res_T res = RES_OK; 162 if(!ran || !wavelengths || !intensities || !sz) 163 return RES_BAD_ARG; 164 165 if(sz <= 1) { 166 ran->type = WL_DIRAC; 167 ran->get = &ran_dirac_get; 168 ran->state.dirac.wavelength = sz ? wavelengths[0] : -1; 169 } else { 170 ran->type = WL_PIECEWISE; 171 ran->get = &ran_piecewise_get; 172 res = ssp_ranst_piecewise_linear_create 173 (ran->allocator, &ran->state.piecewise.spectrum); 174 if(res != RES_OK) goto error; 175 res = ssp_ranst_piecewise_linear_setup 176 (ran->state.piecewise.spectrum, wavelengths, intensities, sz); 177 if(res != RES_OK) goto error; 178 } 179 180 exit: 181 return res; 182 error: 183 if(ran->state.piecewise.spectrum) { 184 SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum)); 185 ran->state.piecewise.spectrum = NULL; 186 } 187 goto exit; 188 } 189