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