Plaquette
 
Loading...
Searching...
No Matches
pq_fixed.h
1/*
2 * pq_fixed.h
3 *
4 * Utility functions for fixed-point arithmetic.
5 *
6 * (c) 2022 Sofian Audry :: info(@)sofianaudry(.)com
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21#ifndef PQ_FIXED_H_
22#define PQ_FIXED_H_
23
24#include "pq_globals.h"
25#include "pq_constrain.h"
26
27#include <stdint.h>
28
29namespace pq {
30
31// Fixed-point types.
32typedef uint32_t q0_32u_t;
33typedef uint16_t q0_16u_t;
34typedef uint8_t q0_8u_t;
35
36// Fixed-point constants.
37constexpr q0_32u_t FIXED_32_MAX = static_cast<q0_32u_t>(0xFFFFFFFF);
38constexpr q0_32u_t HALF_FIXED_32_MAX = static_cast<q0_32u_t>(0x80000000);
39constexpr float INV_FIXED_32_MAX = 1.0f / FIXED_32_MAX;
40
41constexpr q0_16u_t FIXED_16_MAX = static_cast<q0_16u_t>(0xFFFF);
42constexpr q0_16u_t HALF_FIXED_16_MAX = static_cast<q0_16u_t>(0x8000);
43constexpr float INV_FIXED_16_MAX = 1.0f / FIXED_16_MAX;
44
45constexpr q0_8u_t FIXED_8_MAX = static_cast<q0_8u_t>(0xFF);
46constexpr q0_8u_t HALF_FIXED_8_MAX = static_cast<q0_8u_t>(0x80);
47constexpr float INV_FIXED_8_MAX = 1.0f / FIXED_8_MAX;
48
55template <typename I>
56inline I floatToFixed(float value, I high) {
57#if defined(PQ_IEEE_754_SUPPORTED)
58 uint32_t ui;
59 memcpy(&ui, &value, sizeof ui); // safe bit copy
60
61 // Negative -> clamp to 0.0f
62 if (ui & 0x80000000u) return static_cast<I>(0);
63
64 // Closed upper bound: x > 1.0f -> 1.0f
65 if (ui >= 0x3F800000u) return high;
66
67 return static_cast<I>(value + value * high); // x * (toHigh + 1)
68#else
69 return (value <= 0.0f) ? 0 : (value >= 1.0f) ? high : static_cast<I>(value + value * high);
70#endif
71}
72
79template <typename I>
80inline float fixedToFloat(I value, I high) {
81 return constrain01(value / static_cast<float>(high));
82}
83
90template <typename I>
91inline float fixedToFloatInv(I value, float invHigh) {
92 return constrain01(value * invHigh);
93}
94
96inline float fixed32ToFloat(q0_32u_t x) { return fixedToFloatInv(x, INV_FIXED_32_MAX); }
97
99inline q0_32u_t floatToFixed32(float x) { return floatToFixed(x, FIXED_32_MAX); }
100
102inline float fixed16ToFloat(q0_16u_t x) { return fixedToFloatInv(x, INV_FIXED_16_MAX); }
103
105inline q0_16u_t floatToFixed16(float x) { return floatToFixed(x, FIXED_16_MAX); }
106
108inline float fixed8ToFloat(q0_8u_t x) { return fixedToFloatInv(x, INV_FIXED_8_MAX); }
109
111inline q0_8u_t floatToFixed8(float x) { return floatToFixed(x, FIXED_8_MAX); }
112
113}
114
115#endif