@web-font-path: "roboto-debian.css";
Loading...
Searching...
No Matches
float.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _PICO_FLOAT_H
8#define _PICO_FLOAT_H
9
10#include <math.h>
11#include <float.h>
12#include "pico.h"
13#include "pico/bootrom/sf_table.h"
14
15#ifdef __cplusplus
16extern "C" {
17#endif
18
152
153// PICO_CONFIG: PICO_FLOAT_IN_RAM, Force placement of SDK provided single-precision floating point into RAM, type=bool, default=0, group=pico_float
154#if !defined(__riscv) || PICO_COMBINED_DOCS
155
156#if PICO_COMBINED_DOCS || !LIB_PICO_FLOAT_COMPILER
157float int2float(int32_t i);
158float uint2float(uint32_t i);
159float int642float(int64_t i);
160float uint642float(uint64_t i);
161float fix2float(int32_t m, int e);
162float ufix2float(uint32_t m, int e);
163float fix642float(int64_t m, int e);
164float ufix642float(uint64_t m, int e);
165
166// These methods round towards 0, which IS the C way
167int32_t float2int_z(float f);
168int64_t float2int64_z(float f);
169int32_t float2uint_z(float f);
170int64_t float2uint64_z(float f);
171int32_t float2fix_z(float f, int e);
172uint32_t float2ufix_z(float f, int e);
173int64_t float2fix64_z(float f, int e);
174uint64_t float2ufix64_z(float f, int e);
175
176// These methods round towards -Infinity - which IS NOT the C way for negative numbers;
177// as such the naming is not ideal, however is kept for backwards compatibility
178int32_t float2int(float f);
179uint32_t float2uint(float f);
180int64_t float2int64(float f);
181uint64_t float2uint64(float f);
182int32_t float2fix(float f, int e);
183uint32_t float2ufix(float f, int e);
184int64_t float2fix64(float f, int e);
185uint64_t float2ufix64(float f, int e);
186
187#if LIB_PICO_FLOAT_PICO_VFP
188// a bit of a hack to inline VFP fixed point conversion when exponent is constant and in range 1-32
189#define fix2float(m, e) __builtin_choose_expr(__builtin_constant_p(e), (e) >= 1 && (e) <= 32 ? _fix2float_inline(m, e) : fix2 ## float(m, e), fix2 ## float(m, e))
190#define ufix2float(m, e) __builtin_choose_expr(__builtin_constant_p(e), (e) >= 1 && (e) <= 32 ? _ufix2float_inline(m, e) : ufix2 ## float(m, e), ufix2 ## float(m, e))
191#define float2fix_z(f, e) __builtin_choose_expr(__builtin_constant_p(e), (e) >= 1 && (e) <= 32 ? _float2fix_z_inline(f, e) : float2 ## fix_z(f, e), float2 ## fix_z(f, e))
192#define float2ufix_z(f, e) __builtin_choose_expr(__builtin_constant_p(e), (e) >= 1 && (e) <= 32 ? _float2ufix_z_inline(f, e) : float2 ## ufix_z(f, e), float2 ## ufix_z(f, e))
193#define float2fix(f, e) __builtin_choose_expr(__builtin_constant_p(e), (e) >= 1 && (e) <= 32 ? _float2fix_inline(f, e) : float2 ## fix(f, e), float2 ## fix(f, e))
194#define float2ufix(f, e) __builtin_choose_expr(__builtin_constant_p(e), (e) >= 1 && (e) <= 32 ? _float2ufix_inline(f, e) : float2 ## ufix(f, e), float2 ## ufix(f, e))
195
196#define _fix2float_inline(m, e) ({ \
197 int32_t _m = m; \
198 float f; \
199 pico_default_asm( \
200 "vmov %0, %1\n" \
201 "vcvt.f32.s32 %0, %0, %2\n" \
202 : "=t" (f) \
203 : "r" (_m), "i" (e) \
204 ); \
205 f; \
206})
207#define _ufix2float_inline(m, e) ({ \
208 uint32_t _m = m; \
209 float f; \
210 pico_default_asm( \
211 "vmov %0, %1\n" \
212 "vcvt.f32.u32 %0, %0, %2\n" \
213 : "=t" (f) \
214 : "r" (_m), "i" (e) \
215 ); \
216 f; \
217})
218#define _float2fix_z_inline(f, e) ({ \
219 int32_t _m; \
220 float _f = (f); \
221 pico_default_asm( \
222 "vcvt.s32.f32 %0, %0, %2\n" \
223 "vmov %1, %0\n" \
224 : "+t" (_f), "=r" (_m) \
225 : "i" (e) \
226 ); \
227 _m; \
228})
229#define _float2ufix_z_inline(f, e) ({ \
230 uint32_t _m; \
231 float _f = (f); \
232 pico_default_asm( \
233 "vcvt.u32.f32 %0, %0, %2\n" \
234 "vmov %1, %0\n" \
235 : "+t" (_f), "=r" (_m) \
236 : "i" (e) \
237 ); \
238 _m; \
239})
240#define _float2fix_z_inline(f, e) ({ \
241 int32_t _m; \
242 float _f = (f); \
243 pico_default_asm( \
244 "vcvt.s32.f32 %0, %0, %2\n" \
245 "vmov %1, %0\n" \
246 : "+t" (_f), "=r" (_m) \
247 : "i" (e) \
248 ); \
249 _m; \
250})
251#define _float2fix_inline(f, e) ({ \
252 union { float _f; int32_t _i; } _u; \
253 _u._f = (f); \
254 uint rc, tmp; \
255 pico_default_asm( \
256 "vcvt.s32.f32 %0, %0, %4\n" \
257 "vmov %2, %0\n" \
258 "lsls %1, #1\n" \
259 "bls 2f\n" /* positive or zero or -zero are ok with the result we have */ \
260 "lsrs %3, %1, #24\n" \
261 "subs %3, #0x7f - %c4\n" \
262 "bcc 1f\n" /* 0 < abs(f) < 1 ^ e, so need to round down */ \
263 /* mask off all but fractional bits */ \
264 "lsls %1, %3\n" \
265 "lsls %1, #8\n" \
266 "beq 2f\n" /* integers can round towards zero */ \
267 "1:\n" \
268 /* need to subtract 1 from the result to round towards -infinity... */ \
269 /* this will never cause an overflow, because to get here we must have had a non integer/infinite value which */ \
270 /* therefore cannot have been equal to INT64_MIN when rounded towards zero */ \
271 "subs %2, #1\n" \
272 "2:\n" \
273 : "+t" (_u._f), "+r" (_u._i), "=r" (rc), "=r" (tmp) \
274 : "i" (e) \
275 ); \
276 rc; \
277})
278#define _float2ufix_inline(f, e) _float2ufix_z_inline((f), (e))
279#endif
280
281#if LIB_PICO_FLOAT_PICO_VFP
282// may as well provide inline macros for VFP
283#define int2float(i) ((float)(int32_t)(i))
284#define uint2float(i) ((float)(uint32_t)(i))
285#define float2int_z(f) ((int32_t)(f))
286#define float2uint_z(f) ((uint32_t)(f))
287#endif
288
289#endif
290
291float exp10f(float x);
292void sincosf(float x, float *sinx, float *cosx);
293float powintf(float x, int y);
294
295#if !PICO_RP2040 || PICO_COMBINED_DOCS
296float fdiv_fast(float n, float d);
297float sqrtf_fast(float f);
298#endif
299
300#endif
301
302#if defined(__riscv) || LIB_PICO_FLOAT_COMPILER
303// when using the compiler or RISC-V, we provide as many functions as we trivially can - these will be efficient
304// when using hard-float on Arm
305static inline float int2float(int32_t i) { return (float)i; }
306static inline float uint2float(uint32_t i) { return (float)i; }
307static inline float int642float(int64_t i) { return (float)i; }
308static inline float uint642float(uint64_t i) { return (float)i; }
309
310static inline int32_t float2int_z(float f) { return (int32_t)f; }
311static inline int64_t float2int64_z(float f) { return (int64_t)f; }
312static inline int32_t float2uint_z(float f) { return (uint32_t)f; }
313static inline int64_t float2uint64_z(float f) { return (uint64_t)f; }
314#endif
315
316#ifdef __cplusplus
317}
318#endif
319
320#endif