121 lines
4.8 KiB
C

/**
* @file FR_Defs.h - type definitions used in Fixed-Radix math lib
*
* @copy Copyright (C) <2001-2026> <M. A. Chatterjee>
* @author M A Chatterjee <deftio [at] deftio [dot] com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#ifndef __FR_Platform_Defs_H__
#define __FR_Platform_Defs_H__
/*
* Fixed-width integer typedefs.
*
* Prefer C99 <stdint.h> when available (gcc, clang, MSVC, IAR, Keil, sdcc,
* MSP430-gcc, AVR-gcc, RISC-V, ARM toolchains). For bare-metal toolchains
* or pre-C99 compilers that lack <stdint.h>, define FR_NO_STDINT before
* including this header and the types are provided via sizeof()-based
* fallback definitions that cover the common 8/16/32/64-bit layouts.
*/
#ifndef FR_NO_STDINT
#include <stdint.h>
#else
/* ---- fallback: no <stdint.h> ------------------------------------ */
/* Works on any toolchain where char=8, short=16, int/long=32 bits,
* which covers virtually all embedded targets (AVR, MSP430, ARM,
* 68HC11, 68k, PPC, RISC-V, Xtensa, x86). Adjust if your platform
* differs.
*/
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
#if defined(__AVR__) || defined(__MSP430__) || defined(__m68hc1x__)
/* On these targets int is 16-bit; use long for 32-bit */
typedef unsigned long uint32_t;
typedef signed long int32_t;
#else
typedef unsigned int uint32_t;
typedef signed int int32_t;
#endif
/* 64-bit: available on most 32-bit+ GCC targets via long long */
typedef unsigned long long uint64_t;
typedef signed long long int64_t;
#endif /* FR_NO_STDINT */
/*
* Arduino's USBAPI.h typedefs u8 and u16 as unsigned char / unsigned short.
* On AVR, uint8_t/uint16_t resolve to unsigned int types, which are the same
* width but different C++ types — causing a redefinition error. Skip those
* two typedefs when building in an Arduino environment; the Arduino-provided
* types are the same width and work identically.
*
* The guard checks __cplusplus too because Arduino.h (which pulls in
* USBAPI.h) is only auto-included in .ino/.cpp translation units.
* Plain-C files (.c) compiled by the Arduino build system need our
* typedefs even though the ARDUINO macro is defined for them.
*/
#if defined(ARDUINO) && defined(__cplusplus)
/* Arduino C++ TU — USBAPI.h already provides u8 and u16 */
#else
typedef uint8_t u8;
typedef uint16_t u16;
#endif
typedef int8_t s8;
typedef int16_t s16;
typedef uint32_t u32;
typedef int32_t s32;
typedef uint64_t u64;
typedef int64_t s64;
typedef short FR_bool;
#define FR_SWAP_BYTES(x) (((x >> 8) & 0xff) | ((x << 8) & 0xff00))
/*=======================================================
* Sentinel values for math errors.
*
* Functions that can hit a domain error (sqrt of negative, log of <=0, etc.)
* return one of these sentinels rather than raising an error code. Callers
* that care can check `result == FR_DOMAIN_ERROR` before using the value.
*
* FR_OVERFLOW_POS and FR_OVERFLOW_NEG are the saturating-overflow values
* returned by FR_FixMulSat / FR_FixAddSat etc. They are deliberately the
* extremes of s32 so that they compare correctly under signed comparison.
*
* Note: FR_DOMAIN_ERROR equals INT32_MIN (the same value as FR_OVERFLOW_NEG
* would naturally be), so a single check `result <= FR_OVERFLOW_NEG` cannot
* distinguish "saturating-negative-overflow" from "domain error". In
* practice the two never occur in the same call: saturating ops never go
* to a domain-error state, and domain-error ops never saturate. The names
* exist to make caller intent self-documenting.
*/
#define FR_DOMAIN_ERROR ((s32)0x80000000) /* INT32_MIN: e.g. sqrt(<0) */
#define FR_OVERFLOW_POS ((s32)0x7fffffff) /* INT32_MAX: e.g. FR_FixMulSat + */
#define FR_OVERFLOW_NEG ((s32)0x80000000) /* INT32_MIN: e.g. FR_FixMulSat - */
#define FR_FALSE (0)
#define FR_TRUE (!FR_FALSE)
#endif /* __FR_Platform_Defs_H__ */