aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/fixpt.h
blob: d3163df0fbc4d4b54d4d9a738afe4ecdc7106d46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#ifndef FIXEDPOINT_H_
#define FIXEDPOINT_H_

#include "util.h"


#ifndef FIXPT_SIZE
  /* Q10.5 */
# define FIXPT_SIZE		24
# define FIXPT_SHIFT		6
#endif

#ifndef FIXPTFLOAT_SIZE
# define FIXPTFLOAT_SIZE	32
#endif


#if FIXPT_SIZE == 8
# define FIXPTBIG_SIZE	16
typedef int8_t fixpt_t;
typedef int16_t fixpt_big_t;
#elif FIXPT_SIZE == 16
# define FIXPTBIG_SIZE	24
typedef int16_t fixpt_t;
typedef int24_t fixpt_big_t;
#elif FIXPT_SIZE == 24
# define FIXPTBIG_SIZE	32
typedef int24_t fixpt_t;
typedef int32_t fixpt_big_t;
#elif FIXPT_SIZE == 32
# define FIXPTBIG_SIZE	64
typedef int32_t fixpt_t;
typedef int64_t fixpt_big_t;
#else
# error "Invalid FIXPT_SIZE"
#endif

#define FIXPT_MAX	((fixpt_t)((1ULL << (FIXPT_SIZE - 1U)) - 1U))
#define FIXPT_MIN	((fixpt_t)(-FIXPT_MAX))
#define FIXPTBIG_MAX	((fixpt_t)((1ULL << (FIXPTBIG_SIZE - 1U)) - 1U))
#define FIXPTBIG_MIN	((fixpt_t)(-FIXPTBIG_MAX))


#if FIXPTFLOAT_SIZE == 32
typedef float fixptfloat_t;
#elif FIXPTFLOAT_SIZE == 64
typedef double fixptfloat_t;
#else
# error "Invalid FIXPTFLOAT_SIZE"
#endif


fixpt_big_t fixpt_inflate(fixpt_t a);

fixpt_t fixpt_deflate(fixpt_big_t a);

#define FLOAT_TO_FIXPT_BIG(f)	((fixpt_big_t)(						\
		((f) < 0.0) ?								\
			(fixpt_big_t)(((f) * (fixptfloat_t)(1L << FIXPT_SHIFT)) - 0.5)	\
		:									\
			(fixpt_big_t)(((f) * (fixptfloat_t)(1L << FIXPT_SHIFT)) + 0.5)	\
	))

#define FLOAT_TO_FIXPT(f)	((fixpt_t)FLOAT_TO_FIXPT_BIG(f))

static alwaysinline fixpt_big_t float_to_fixpt_big(fixptfloat_t f)
{
	return (fixpt_big_t)FLOAT_TO_FIXPT_BIG(f);
}

static alwaysinline fixpt_t float_to_fixpt(fixptfloat_t f)
{
	return fixpt_deflate(float_to_fixpt_big(f));
}

static alwaysinline fixptfloat_t fixpt_big_to_float(fixpt_big_t p)
{
	return (fixptfloat_t)p / (fixptfloat_t)(1L << FIXPT_SHIFT);
}

static alwaysinline fixptfloat_t fixpt_to_float(fixpt_t p)
{
	return fixpt_big_to_float(fixpt_inflate(p));
}

#define INT_TO_FIXPT_BIG(i)	((fixpt_big_t)((int32_t)(i) << FIXPT_SHIFT))
#define INT_TO_FIXPT(i)		((fixpt_t)INT_TO_FIXPT_BIG(i))

fixpt_big_t _do_int32_to_fixpt_big(int32_t i);
#define int_to_fixpt_big(i)	choose_expr(is_constant(i),		\
					    INT_TO_FIXPT_BIG(i),	\
					    _do_int32_to_fixpt_big(i))

fixpt_t _do_int32_to_fixpt(int32_t i);
#define int_to_fixpt(i)		choose_expr(is_constant(i),		\
					    INT_TO_FIXPT(i),		\
					    _do_int32_to_fixpt(i))

int32_t fixpt_big_to_int(fixpt_big_t p);

int32_t fixpt_to_int(fixpt_t p);

/* Get the integer part of a fixpt_t.
 */
int32_t fixpt_get_int_part(fixpt_t p);

/* Get the decimal fractional part of a fixpt_t.
 */
uint32_t fixpt_get_dec_fract(fixpt_t p, uint8_t nr_digits);

/* Calculate: a + b
 */
fixpt_big_t fixpt_big_add(fixpt_big_t a, fixpt_big_t b);

/* Calculate: a - b
 */
fixpt_big_t fixpt_big_sub(fixpt_big_t a, fixpt_big_t b);

/* Calculate: a * b
 */
fixpt_big_t fixpt_big_mul(fixpt_big_t a, fixpt_big_t b);

/* Calculate: a / b
 */
fixpt_big_t fixpt_big_div(fixpt_big_t a, fixpt_big_t b);

/* Calculate: (a * b) / c
 */
fixpt_big_t fixpt_big_mul_div(fixpt_big_t a, fixpt_big_t b, fixpt_big_t c);

/* Calculate: a + b
 */
fixpt_t fixpt_add(fixpt_t a, fixpt_t b);

/* Calculate: a - b
 */
fixpt_t fixpt_sub(fixpt_t a, fixpt_t b);

/* Calculate: a * b
 */
fixpt_t fixpt_mul(fixpt_t a, fixpt_t b);

/* Calculate: a / b
 */
fixpt_t fixpt_div(fixpt_t a, fixpt_t b);

/* Calculate: (a * b) / c
 */
fixpt_t fixpt_mul_div(fixpt_t a, fixpt_t b, fixpt_t c);

/* Calculate: -a
 */
fixpt_t fixpt_neg(fixpt_t a);

/* Calculate: Absolute value of a
 */
fixpt_t fixpt_abs(fixpt_t a);

/* Calculate: a + b, limited to lo_lim, hi_lim
 */
fixpt_t fixpt_add_limited(fixpt_t a, fixpt_t b,
			  fixpt_t lo_lim, fixpt_t hi_lim);

/* Limit a to lo_lim, hi_lim */
fixpt_t fixpt_clamp(fixpt_t a,
		    fixpt_t lo_lim, fixpt_t hi_lim);

#endif /* FIXEDPOINT_H_ */
bues.ch cgit interface