star-hitran

Load line-by-line data from the HITRAN database
git clone git://git.meso-star.fr/star-hitran.git
Log | Files | Refs | README | LICENSE

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 }