shtr.c (5734B)
1 /* Copyright (C) 2022, 2025, 2026 |Méso|Star> (contact@meso-star.com) 2 * Copyright (C) 2025, 2026 Université de Lorraine 3 * Copyright (C) 2022 Centre National de la Recherche Scientifique 4 * Copyright (C) 2022 Université Paul Sabatier 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19 #include "shtr.h" 20 #include "shtr_c.h" 21 22 /******************************************************************************* 23 * Helper functions 24 ******************************************************************************/ 25 static INLINE res_T 26 check_shtr_create_args(const struct shtr_create_args* args) 27 { 28 return args ? RES_OK : RES_BAD_ARG; 29 } 30 31 static void 32 release_shtr(ref_T* ref) 33 { 34 struct shtr* shtr = CONTAINER_OF(ref, struct shtr, ref); 35 ASSERT(ref); 36 if(shtr->logger == &shtr->logger__) logger_release(&shtr->logger__); 37 MEM_RM(shtr->allocator, shtr); 38 } 39 40 /******************************************************************************* 41 * Local functions 42 ******************************************************************************/ 43 int64_t 44 float2fix 45 (const double fp, 46 const int ipl, /* Length (in bits) of the integer part */ 47 const int fpl) /* Length (in bits) of the fractional part */ 48 { 49 union { double flt; int64_t i64; } fpart; /* Fractional part */ 50 int64_t ipart = 0; /* Integer part */ 51 double fp_abs = 0; /* Absolute value of fp */ 52 int sign = 0; /* 1 if fp is negative, and 0 otherwise */ 53 54 ASSERT(ipl + fpl <= 64 && fpl < 51); /* Pre-conditions */ 55 56 sign = fp < 0; 57 fp_abs = fabs(fp); 58 ipart = (int64_t)fp_abs & (BIT_I64(ipl)-1); 59 60 /* The IEEE-754 encoding of a double precision floating point number `f' 61 * whose binary representation is `F' is defined as: 62 * f = (-1)^S * 2^(E-1023) 63 * * (1 + For(i in [0..51]) { M & BIT(51-i) ? 2^i : 0 }) 64 * with S = F / 2^63; E = F / 2^52 and M = F & (2^52 - 1). 65 * 66 * By adding 1 to the fractional part of the floating point number submitted 67 * as input, its exponent becomes zero (i.e., E = 1023) and its mantissa is 68 * then the binary representation of the fractional part as expected by the 69 * fixed format. In other words, the (fpl-1-i)^th bit of the mantissa then 70 * corresponds to the power of 2 expected in fixed representation. */ 71 fpart.flt = 1.0 + (fp_abs - (double)ipart); 72 fpart.i64 &= BIT_I64(52)-1; 73 74 fpart.i64 >>= 52 - fpl; /* Quantification of the fractional part */ 75 76 return (((sign << ipl) | ipart) << fpl) | fpart.i64; 77 } 78 79 double 80 fix2float 81 (const int64_t fix, 82 const int ipl, /* Length (in bits) of the integer part */ 83 const int fpl) /* Length (in bits) of the fractional part */ 84 { 85 union { double flt; int64_t i64; } fpart; /* Fractional part */ 86 double ipart = 0; /* Integer part */ 87 double sign = 0; /* -1 if fix is negative, and 1 otherwise */ 88 89 ASSERT(ipl + fpl <= 64 && fpl < 51); /* Pre-conditions */ 90 91 sign = (fix & BIT_I64(ipl + fpl)) ? -1.0 : +1.0; 92 ipart = (double)((fix >> fpl) & (BIT_I64(ipl)-1)); 93 94 /* The IEEE-754 encoding of a double precision floating point number `f' 95 * whose binary representation is `F' is defined as: 96 * f = (-1)^S * 2^(E-1023) 97 * * (1 + For(i in [0..51]) { M & BIT(51-i) ? 2^i : 0 }) 98 * with S = F / 2^63; E = F / 2^52 and M = F & (2^52 - 1). 99 * 100 * Setting a floating-point number to 1 sets its exponent to zero (i.e., E = 101 * 1023). Thus, the mantissa bits and the fractional part of a fixed-point 102 * representation are identical. All you need to do is subtract 1 from the 103 * floating-point representation to retrieve the floating-point encoding of 104 * the fractional part */ 105 fpart.flt = 1.0; 106 fpart.i64 |= (fix & (BIT(fpl) - 1)) << (52 - fpl); 107 fpart.flt -= 1.0; 108 109 return sign * (ipart + fpart.flt); 110 } 111 112 /******************************************************************************* 113 * Exported functions 114 ******************************************************************************/ 115 res_T 116 shtr_create 117 (const struct shtr_create_args* args, 118 struct shtr** out_shtr) 119 { 120 struct mem_allocator* allocator = NULL; 121 struct shtr* shtr = NULL; 122 res_T res = RES_OK; 123 124 if(!out_shtr) { res = RES_BAD_ARG; goto error; } 125 res = check_shtr_create_args(args); 126 if(res != RES_OK) goto error; 127 128 allocator = args->allocator ? args->allocator : &mem_default_allocator; 129 shtr = MEM_CALLOC(allocator, 1, sizeof(*shtr)); 130 if(!shtr) { 131 #define ERR_STR "Could not allocate the Star-HITRAN data structure.\n" 132 if(args->logger) { 133 logger_print(args->logger, LOG_ERROR, ERR_STR); 134 } else { 135 fprintf(stderr, MSG_ERROR_PREFIX ERR_STR); 136 } 137 #undef ERR_STR 138 res = RES_MEM_ERR; 139 goto error; 140 } 141 ref_init(&shtr->ref); 142 shtr->allocator = allocator; 143 shtr->verbose = args->verbose; 144 shtr->logger = args->logger ? args->logger : LOGGER_DEFAULT; 145 146 exit: 147 if(out_shtr) *out_shtr = shtr; 148 return res; 149 error: 150 if(shtr) { SHTR(ref_put(shtr)); shtr = NULL; } 151 goto exit; 152 } 153 154 res_T 155 shtr_ref_get(struct shtr* shtr) 156 { 157 if(!shtr) return RES_BAD_ARG; 158 ref_get(&shtr->ref); 159 return RES_OK; 160 } 161 162 res_T 163 shtr_ref_put(struct shtr* shtr) 164 { 165 if(!shtr) return RES_BAD_ARG; 166 ref_put(&shtr->ref, release_shtr); 167 return RES_OK; 168 }