LCOV - code coverage report
Current view: top level - src - scientific.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 36 36 100.0 %
Date: 2026-07-14 21:28:07 Functions: 2 2 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 14 14 100.0 %

           Branch data     Line data    Source code
       1                 :            : // Copyright 2019-2026 David Robillard <d@drobilla.net>
       2                 :            : // SPDX-License-Identifier: ISC
       3                 :            : 
       4                 :            : #include "scientific.h"
       5                 :            : #include "big_decimal.h"
       6                 :            : #include "int_math.h"
       7                 :            : #include "result.h"
       8                 :            : #include "write_utils.h"
       9                 :            : 
      10                 :            : #include <exess/exess.h>
      11                 :            : 
      12                 :            : #include <stdlib.h>
      13                 :            : #include <string.h>
      14                 :            : 
      15                 :            : typedef struct {
      16                 :            :   size_t      length;
      17                 :            :   const char* string;
      18                 :            : } SpecialCase;
      19                 :            : 
      20                 :            : static const SpecialCase special_cases[] = {{3U, "NaN"},
      21                 :            :                                             {4U, "-INF"},
      22                 :            :                                             {3U, "INF"},
      23                 :            :                                             {6U, "-0.0E0"},
      24                 :            :                                             {5U, "0.0E0"}};
      25                 :            : 
      26                 :            : EXESS_CONST_FUNC static size_t
      27                 :      27526 : scientific_string_length(const BigDecimal value, const unsigned n_expt_digits)
      28                 :            : {
      29         [ +  + ]:      27526 :   if (value.kind < EXESS_NEGATIVE) {
      30                 :       1094 :     return special_cases[value.kind].length;
      31                 :            :   }
      32                 :            : 
      33                 :      26432 :   return (value.n_digits + n_expt_digits +
      34                 :      26432 :           !!(value.kind == EXESS_NEGATIVE) + // Sign
      35                 :      26432 :           1U +                               // Decimal point
      36                 :      26432 :           !!(value.n_digits <= 1) +          // Added '0' after point
      37                 :      26432 :           1U +                               // 'E'
      38                 :      26432 :           !!(value.expt < 1));               // Exponent sign
      39                 :            : }
      40                 :            : 
      41                 :            : EXESS_NONBLOCKING ExessResult
      42                 :      27526 : write_scientific(const BigDecimal  value,
      43                 :            :                  const char* const digits,
      44                 :            :                  const size_t      buf_size,
      45                 :            :                  char* const       buf)
      46                 :            : {
      47                 :      27526 :   const int      expt          = value.expt - 1;
      48                 :      27526 :   unsigned       abs_expt      = (unsigned)abs(expt);
      49                 :      27526 :   const unsigned n_expt_digits = (unsigned)exess_num_digits(abs_expt);
      50                 :      27526 :   const size_t   length        = scientific_string_length(value, n_expt_digits);
      51         [ +  + ]:      27526 :   if (length >= buf_size) {
      52                 :        300 :     return RESULT(EXESS_NO_SPACE, length);
      53                 :            :   }
      54                 :            : 
      55         [ +  + ]:      27226 :   if (value.kind < EXESS_NEGATIVE) {
      56                 :        991 :     return write_special(special_cases[value.kind].length,
      57                 :        991 :                          special_cases[value.kind].string,
      58                 :            :                          buf_size,
      59                 :            :                          buf);
      60                 :            :   }
      61                 :            : 
      62                 :      26235 :   size_t i = 0;
      63         [ +  + ]:      26235 :   if (value.kind == EXESS_NEGATIVE) {
      64                 :          8 :     buf[i++] = '-';
      65                 :            :   }
      66                 :            : 
      67                 :            :   // Write mantissa, with decimal point after the first (normal form)
      68                 :      26235 :   buf[i++] = digits[0];
      69                 :      26235 :   buf[i++] = '.';
      70         [ +  + ]:      26235 :   if (value.n_digits > 1) {
      71                 :      26207 :     memcpy(buf + i, digits + 1, value.n_digits - 1U);
      72                 :      26207 :     i += value.n_digits - 1U;
      73                 :            :   } else {
      74                 :         28 :     buf[i++] = '0';
      75                 :            :   }
      76                 :            : 
      77                 :            :   // Write exponent
      78                 :            : 
      79                 :      26235 :   buf[i++] = 'E';
      80         [ +  + ]:      26235 :   if (expt < 0) {
      81                 :      12034 :     buf[i++] = '-';
      82                 :            :   }
      83                 :            : 
      84                 :      26235 :   char* s = buf + i + n_expt_digits;
      85                 :            : 
      86                 :      26235 :   *s-- = '\0';
      87                 :            :   do {
      88                 :      54364 :     *s-- = (char)('0' + (abs_expt % 10));
      89         [ +  + ]:      54364 :   } while ((abs_expt /= 10) > 0);
      90                 :            : 
      91                 :      26235 :   return RESULT(EXESS_SUCCESS, i + n_expt_digits);
      92                 :            : }

Generated by: LCOV version 1.16