@web-font-path: "roboto-debian.css";
v2.2.0 (RP2040)
Loading...
Searching...
No Matches
float.h
Go to the documentation of this file.
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_FLOAT_H
#define _PICO_FLOAT_H
#include <math.h>
#include <float.h>
#include "pico.h"
#include "pico/bootrom/sf_table.h"
#ifdef __cplusplus
extern "C" {
#endif
// PICO_CONFIG: PICO_FLOAT_IN_RAM, Force placement of SDK provided single-precision floating point into RAM, type=bool, default=0, group=pico_float
#if !defined(__riscv) || PICO_COMBINED_DOCS
#if PICO_COMBINED_DOCS || !LIB_PICO_FLOAT_COMPILER
float int2float(int32_t i);
float uint2float(uint32_t i);
float int642float(int64_t i);
float uint642float(uint64_t i);
float fix2float(int32_t m, int e);
float ufix2float(uint32_t m, int e);
float fix642float(int64_t m, int e);
float ufix642float(uint64_t m, int e);
// These methods round towards 0, which IS the C way
int32_t float2int_z(float f);
int64_t float2int64_z(float f);
int32_t float2uint_z(float f);
int64_t float2uint64_z(float f);
int32_t float2fix_z(float f, int e);
uint32_t float2ufix_z(float f, int e);
int64_t float2fix64_z(float f, int e);
uint64_t float2ufix64_z(float f, int e);
// These methods round towards -Infinity - which IS NOT the C way for negative numbers;
// as such the naming is not ideal, however is kept for backwards compatibility
int32_t float2int(float f);
uint32_t float2uint(float f);
int64_t float2int64(float f);
uint64_t float2uint64(float f);
int32_t float2fix(float f, int e);
uint32_t float2ufix(float f, int e);
int64_t float2fix64(float f, int e);
uint64_t float2ufix64(float f, int e);
#if LIB_PICO_FLOAT_PICO_VFP
// a bit of a hack to inline VFP fixed point conversion when exponent is constant and in range 1-32
#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))
#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))
#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))
#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))
#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))
#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))
#define _fix2float_inline(m, e) ({ \
int32_t _m = m; \
float f; \
pico_default_asm( \
"vmov %0, %1\n" \
"vcvt.f32.s32 %0, %0, %2\n" \
: "=t" (f) \
: "r" (_m), "i" (e) \
); \
f; \
})
#define _ufix2float_inline(m, e) ({ \
uint32_t _m = m; \
float f; \
pico_default_asm( \
"vmov %0, %1\n" \
"vcvt.f32.u32 %0, %0, %2\n" \
: "=t" (f) \
: "r" (_m), "i" (e) \
); \
f; \
})
#define _float2fix_z_inline(f, e) ({ \
int32_t _m; \
float _f = (f); \
pico_default_asm( \
"vcvt.s32.f32 %0, %0, %2\n" \
"vmov %1, %0\n" \
: "+t" (_f), "=r" (_m) \
: "i" (e) \
); \
_m; \
})
#define _float2ufix_z_inline(f, e) ({ \
uint32_t _m; \
float _f = (f); \
pico_default_asm( \
"vcvt.u32.f32 %0, %0, %2\n" \
"vmov %1, %0\n" \
: "+t" (_f), "=r" (_m) \
: "i" (e) \
); \
_m; \
})
#define _float2fix_z_inline(f, e) ({ \
int32_t _m; \
float _f = (f); \
pico_default_asm( \
"vcvt.s32.f32 %0, %0, %2\n" \
"vmov %1, %0\n" \
: "+t" (_f), "=r" (_m) \
: "i" (e) \
); \
_m; \
})
#define _float2fix_inline(f, e) ({ \
union { float _f; int32_t _i; } _u; \
_u._f = (f); \
uint rc, tmp; \
pico_default_asm( \
"vcvt.s32.f32 %0, %0, %4\n" \
"vmov %2, %0\n" \
"lsls %1, #1\n" \
"bls 2f\n" /* positive or zero or -zero are ok with the result we have */ \
"lsrs %3, %1, #24\n" \
"subs %3, #0x7f - %c4\n" \
"bcc 1f\n" /* 0 < abs(f) < 1 ^ e, so need to round down */ \
/* mask off all but fractional bits */ \
"lsls %1, %3\n" \
"lsls %1, #8\n" \
"beq 2f\n" /* integers can round towards zero */ \
"1:\n" \
/* need to subtract 1 from the result to round towards -infinity... */ \
/* this will never cause an overflow, because to get here we must have had a non integer/infinite value which */ \
/* therefore cannot have been equal to INT64_MIN when rounded towards zero */ \
"subs %2, #1\n" \
"2:\n" \
: "+t" (_u._f), "+r" (_u._i), "=r" (rc), "=r" (tmp) \
: "i" (e) \
); \
rc; \
})
#define _float2ufix_inline(f, e) _float2ufix_z_inline((f), (e))
#endif
#if LIB_PICO_FLOAT_PICO_VFP
// may as well provide inline macros for VFP
#define int2float(i) ((float)(int32_t)(i))
#define uint2float(i) ((float)(uint32_t)(i))
#define float2int_z(f) ((int32_t)(f))
#define float2uint_z(f) ((uint32_t)(f))
#endif
#endif
float exp10f(float x);
void sincosf(float x, float *sinx, float *cosx);
float powintf(float x, int y);
#if !PICO_RP2040 || PICO_COMBINED_DOCS
float fdiv_fast(float n, float d);
float sqrtf_fast(float f);
#endif
#endif
#if defined(__riscv) || LIB_PICO_FLOAT_COMPILER
// when using the compiler or RISC-V, we provide as many functions as we trivially can - these will be efficient
// when using hard-float on Arm
static inline float int2float(int32_t i) { return (float)i; }
static inline float uint2float(uint32_t i) { return (float)i; }
static inline float int642float(int64_t i) { return (float)i; }
static inline float uint642float(uint64_t i) { return (float)i; }
static inline int32_t float2int_z(float f) { return (int32_t)f; }
static inline int64_t float2int64_z(float f) { return (int64_t)f; }
static inline int32_t float2uint_z(float f) { return (uint32_t)f; }
static inline int64_t float2uint64_z(float f) { return (uint64_t)f; }
#endif
#ifdef __cplusplus
}
#endif
#endif
float.h
pico.h