Program Listing for File math.h

Return to documentation for file (rcsw/stdio/math.h)

#pragma once

/*******************************************************************************
 * Includes
 ******************************************************************************/
#include <float.h>

#include "rcsw/al/types.h"
#include "rcsw/common/common.h"

/*******************************************************************************
 * Constant Definitions
 ******************************************************************************/

#if FLT_RADIX != 2
#error "Non-binary-radix floating-point types are unsupported."
#endif

/*******************************************************************************
 * Configuration
 ******************************************************************************/
#if DBL_MANT_DIG == 24

#define DOUBLE_SIZE_IN_BITS 32
typedef uint32_t double_uint_t;
#define DOUBLE_EXPONENT_MASK 0xFFU
#define DOUBLE_BASE_EXPONENT 127
#define DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10 -38
#define DOUBLE_MAX_SUBNORMAL_POWER_OF_10 1e-38

#elif DBL_MANT_DIG == 53

#define DOUBLE_SIZE_IN_BITS 64
typedef uint64_t double_uint_t;
#define DOUBLE_EXPONENT_MASK 0x7FFU
#define DOUBLE_BASE_EXPONENT 1023
#define DOUBLE_MAX_SUBNORMAL_EXPONENT_OF_10 -308
#define DOUBLE_MAX_SUBNORMAL_POWER_OF_10 1e-308

#else
#error "Unsupported double type configuration"
#endif
#define DOUBLE_STORED_MANTISSA_BITS (DBL_MANT_DIG - 1)

typedef union {
  double_uint_t U;
  double        F;
} double_with_bit_access;


/*******************************************************************************
 * API Functions
 ******************************************************************************/
BEGIN_C_DECLS

// This is unnecessary in C99, since compound initializers can be used,
// but:
// 1. Some compilers are finicky about this;
// 2. Some people may want to convert this to C89;
// 3. If you try to use it as C++, only C++20 supports compound literals
static inline double_with_bit_access get_bit_access(double x) {
  double_with_bit_access dwba;
  dwba.F = x;
  return dwba;
}

static inline int stdio_sign_bit(double x)
{
  // The sign is stored in the highest bit
  return (int) (get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1));
}

static inline int stdio_exp2(double_with_bit_access x)
{
  // The exponent in an IEEE-754 floating-point number occupies a contiguous
  // sequence of bits (e.g. 52..62 for 64-bit doubles), but with a non-trivial representation: An
  // unsigned offset from some negative value (with the extremal offset values reserved for
  // special use).
  return (int)((x.U >> DOUBLE_STORED_MANTISSA_BITS ) & DOUBLE_EXPONENT_MASK) - DOUBLE_BASE_EXPONENT;
}

RCSW_WARNING_DISABLE_PUSH()
RCSW_WARNING_DISABLE_FLOAT_EQUAL()
static inline bool_t stdio_isnan(double value) { return value != value; }
RCSW_WARNING_DISABLE_POP()

static inline bool_t stdio_isinf(double value) { return value < -DBL_MAX || value > DBL_MAX; }

// A floor function - but one which only works for numbers whose
// floor value is representable by an int.
int stdio_floor(double x) RCSW_CONST;

RCSW_API double stdio_log10(double positive_number) RCSW_CONST;

RCSW_API double stdio_pow10(int floored_exp10) RCSW_CONST;

END_C_DECLS