summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatryk Duda <pdk@semihalf.com>2022-01-28 12:19:57 +0100
committerCommit Bot <commit-bot@chromium.org>2022-02-01 22:35:46 +0000
commit17e3a7568331291accdb8364846fa8d7619b6bec (patch)
treef86ba581f03543db4eb807f439686460aeeb8a53
parenta1d1af858da7621fb1cd840afc33d935d07af5f2 (diff)
downloadchrome-ec-17e3a7568331291accdb8364846fa8d7619b6bec.tar.gz
math: Introduce isnan and isinf functions
This patch adds functions responsible for checking if floating point operation result is NaN or infinity. Minute-ia specific functions were removed, because generic version should be used. To test added functions, 'fp' unit test was extended. BUG=b:215606535 BRANCH=none TEST=make buildall TEST=make runhosttests Signed-off-by: Patryk Duda <pdk@semihalf.com> Change-Id: I68f46e91491b4a221beccde4275fd27a5424a048 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3423529 Reviewed-by: Bobby Casey <bobbycasey@google.com> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
-rw-r--r--builtin/math.h11
-rw-r--r--core/minute-ia/include/fpu.h48
-rw-r--r--test/fp.c71
3 files changed, 75 insertions, 55 deletions
diff --git a/builtin/math.h b/builtin/math.h
index 30a8849bd6..9292ac8b34 100644
--- a/builtin/math.h
+++ b/builtin/math.h
@@ -6,6 +6,17 @@
#ifndef __CROS_EC_MATH_H__
#define __CROS_EC_MATH_H__
+#include <stdbool.h>
#include "fpu.h"
+static inline bool isnan(float a)
+{
+ return __builtin_isnan(a);
+}
+
+static inline bool isinf(float a)
+{
+ return __builtin_isinf(a);
+}
+
#endif /* __CROS_EC_MATH_H__ */
diff --git a/core/minute-ia/include/fpu.h b/core/minute-ia/include/fpu.h
index fb4865932e..553807352a 100644
--- a/core/minute-ia/include/fpu.h
+++ b/core/minute-ia/include/fpu.h
@@ -189,53 +189,5 @@ static inline float acosf(float v)
return atan2f(sqrtf(1.0 - v * v), v);
}
-#define COND_FP_NAN 0x0100
-#define COND_FP_SIGNBIT 0x0200
-#define COND_FP_NORMAL 0x0400
-#define COND_FP_ZERO 0x4000
-#define COND_FP_INFINITE (COND_FP_NAN | COND_FP_NORMAL)
-
-/* Check if V is NaN (not-a-number). */
-static inline int __isnanf(float v)
-{
- uint16_t stat;
-
- asm volatile(
- "fxam\n"
- "fnstsw %0\n"
- : "=r" (stat)
- : "v" (v));
-
- return (stat & (COND_FP_NAN | COND_FP_NORMAL | COND_FP_ZERO))
- == COND_FP_NAN;
-}
-
-/**
- * Check if V is infinite.
- *
- * @return 0 if V is finite or NaN.
- * @return +1 if V is +infinite.
- * @return -1 if V is -infinite.
- */
-static inline int __isinff(float v)
-{
- uint16_t stat;
-
- asm volatile(
- "fxam\n"
- "fnstsw %0\n"
- : "=r" (stat)
- : "v" (v));
-
- if ((stat & (COND_FP_NAN | COND_FP_NORMAL | COND_FP_ZERO)) ==
- COND_FP_INFINITE) {
- /* Infinite number, check sign */
- return stat & COND_FP_SIGNBIT ? -1 : 1;
- }
-
- /* Finite or NaN */
- return 0;
-}
-
#endif /* CONFIG_FPU */
#endif /* __CROS_EC_FPU_H */
diff --git a/test/fp.c b/test/fp.c
index 0324da6c8d..2d9aa1ed5e 100644
--- a/test/fp.c
+++ b/test/fp.c
@@ -5,12 +5,13 @@
/*
* Explicitly include common.h to populate predefined macros in test_config.h
- * early. e.g. CONFIG_FPU, which is needed in math_util.h
+ * early. e.g. CONFIG_FPU, which is needed in math_util.h.
*/
#include "common.h"
#include "mat33.h"
#include "mat44.h"
+#include "math.h"
#include "math_util.h"
#include "test_util.h"
#include "vec3.h"
@@ -69,7 +70,7 @@ static int test_fpv3_dot(void)
int i;
floatv3_t a = {1.8f, 2.12f, 4.12f};
floatv3_t b = {3.1f, 4.3f, 5.8f};
- /* Golden result g = dot(a, b) */
+ /* Golden result g = dot(a, b). */
float g = 38.592f;
fpv3_t fpa, fpb;
volatile fp_t result;
@@ -91,7 +92,7 @@ static int test_fpv3_norm_squared(void)
const int N = 3;
int i;
floatv3_t a = {3.0f, 4.0f, 5.0f};
- /* Golden result g = norm_squared(a) */
+ /* Golden result g = norm_squared(a). */
float g = 50.0f;
fpv3_t fpa;
@@ -108,7 +109,7 @@ static int test_fpv3_norm(void)
{
const int N = 3;
floatv3_t a = {3.1f, 4.2f, 5.3f};
- /* Golden result g = norm(a) */
+ /* Golden result g = norm(a). */
float g = 7.439086f;
int i;
fpv3_t fpa;
@@ -131,9 +132,9 @@ static int test_int_sqrtf(void)
TEST_ASSERT(int_sqrtf(1111088889) == 33333);
TEST_ASSERT(int_sqrtf(123456789) == 11111);
TEST_ASSERT(int_sqrtf(1000000000000000005) == 1000000000);
- /* Return zero for imaginary numbers */
+ /* Return zero for imaginary numbers. */
TEST_ASSERT(int_sqrtf(-100) == 0);
- /* Return INT32_MAX for input greater than INT32_MAX ^ 2 */
+ /* Return INT32_MAX for input greater than INT32_MAX ^ 2. */
TEST_ASSERT(int_sqrtf(INT64_MAX) == INT32_MAX);
#endif
@@ -192,7 +193,7 @@ static int test_mat33_fp_scalar_mul(void)
{1.1f, 2.2f, 3.3f},
{0.38f, 13.2f, 88.3f}
};
- /* Golden result g = scalar_mul(a, scale) */
+ /* Golden result g = scalar_mul(a, scale). */
mat33_float_t g = {{3.11f, 6.22f, 9.33f},
{3.421f, 6.842f, 10.263f},
{1.18179988861083984375f, 41.051998138427734375f,
@@ -320,6 +321,60 @@ static int test_mat44_fp_solve(void)
return EC_SUCCESS;
}
+test_static int test_isnan(void)
+{
+ float zero = 0.0f;
+ float smallest = 1.40130e-45f;
+ float highest = 3.40282e38f;
+
+ /* 0.0/0.0 results in NaN. */
+ TEST_ASSERT(isnan(zero / zero));
+ TEST_ASSERT(isnan(-zero / zero));
+ TEST_ASSERT(isnan(zero / -zero));
+ TEST_ASSERT(isnan(-zero / -zero));
+
+ /*
+ * Make sure the smallest number (which is also denormalized) won't be
+ * recognized as NaN.
+ */
+ TEST_ASSERT(!isnan(smallest));
+
+ /* Make sure highest number won't be recognized as NaN. */
+ TEST_ASSERT(!isnan(highest));
+
+ /* Make sure that 0.0 is not recognized as NaN. */
+ TEST_ASSERT(!isnan(zero));
+ TEST_ASSERT(!isnan(-zero));
+
+ return EC_SUCCESS;
+}
+
+test_static int test_isinf(void)
+{
+ float one = 1.0f;
+ float zero = 0.0f;
+ float smallest = 1.40130e-45f;
+ float highest = 3.40282e38f;
+
+ TEST_ASSERT(isinf(one / zero));
+ TEST_ASSERT(isinf(-one / zero));
+
+ /*
+ * Make sure the smallest number (which is also denormalized) won't be
+ * recognized as infinity.
+ */
+ TEST_ASSERT(!isinf(smallest));
+
+ /* Make sure highest number won't be recognized as infinity. */
+ TEST_ASSERT(!isinf(highest));
+
+ /* Make sure that 0.0 is not recognized as infinity. */
+ TEST_ASSERT(!isinf(zero));
+ TEST_ASSERT(!isinf(-zero));
+
+ return EC_SUCCESS;
+}
+
void run_test(int argc, char **argv)
{
test_reset();
@@ -335,6 +390,8 @@ void run_test(int argc, char **argv)
RUN_TEST(test_mat33_fp_get_eigenbasis);
RUN_TEST(test_mat44_fp_decompose_lup);
RUN_TEST(test_mat44_fp_solve);
+ RUN_TEST(test_isnan);
+ RUN_TEST(test_isinf);
test_print_result();
}