Fix some floatl issues, add init version flmath

This commit is contained in:
Lamdonn 2025-03-12 23:48:18 +08:00
parent 085cfede8a
commit 226ad1461c
8 changed files with 1275 additions and 136 deletions

333
source/07_math/flmath.c Normal file
View File

@ -0,0 +1,333 @@
/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file flmath.c
* \unit flmath
* \brief This is a simple large float number math calculate module for C language
* \author Lamdonn
* \version v1.0.1
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#include "flmath.h"
// Number of terms in the Taylor series for trigonometric functions
static const int trig_terms = 15 * sizeof(floatl) / 8;
// Number of terms in the Taylor series for the exponential function
static const int exp_terms = 15 * sizeof(floatl) / 8;
// Number of terms in the Taylor series for the natural logarithm function
static const int ln_terms = 15 * sizeof(floatl) / 8;
/**
* \brief Calculates the factorial of an integer.
* \param n: The integer for which the factorial is to be calculated.
* \return A 'floatl' number representing the factorial of 'n'.
*/
static floatl floatl_int_fact(int n)
{
floatl result = FLOATL_CONST_1;
for (int i = 1; i <= n; i++)
{
result = floatl_mul(result, floatl(i));
}
return result;
}
/**
* \brief Calculates the power of a 'floatl' number with an integer exponent.
* \param base: The base 'floatl' number.
* \param exponent: The integer exponent.
* \return A 'floatl' number representing 'base' raised to the power of 'exponent'.
*/
static floatl floatl_int_power(floatl base, int exponent)
{
floatl result = FLOATL_CONST_1;
for (int i = 0; i < exponent; i++)
{
result = floatl_mul(result, base);
}
return result;
}
/**
* \brief Calculates the sine of a 'floatl' number using the Taylor series expansion.
* \param x: The 'floatl' number for which the sine is to be calculated.
* \return A 'floatl' number representing the sine of 'x'.
*/
floatl floatl_sin(floatl x)
{
floatl result = FLOATL_CONST_0;
// Normalize x to the range [-π, π]
while (floatl_gt(x, FLOATL_PI))
{
x = floatl_sub(x, FLOATL_PI);
x = floatl_sub(x, FLOATL_PI);
}
while (floatl_lt(x, floatl_neg(FLOATL_PI)))
{
x = floatl_add(x, FLOATL_PI);
x = floatl_add(x, FLOATL_PI);
}
for (int n = 0; n < trig_terms; n++)
{
floatl term = floatl_int_power(floatl_neg(FLOATL_CONST_1), n);
term = floatl_mul(term, floatl_int_power(x, 2 * n + 1));
term = floatl_div(term, floatl_int_fact(2 * n + 1));
result = floatl_add(result, term);
}
return result;
}
/**
* \brief Calculates the cosine of a 'floatl' number using the sine function.
* \param x: The 'floatl' number for which the cosine is to be calculated.
* \return A 'floatl' number representing the cosine of 'x'.
*/
floatl floatl_cos(floatl x)
{
x = floatl_add(x, floatl_mul(floatl(0.5), FLOATL_PI));
return floatl_sin(x);
}
/**
* \brief Calculates the secant of a 'floatl' number.
* \param x: The 'floatl' number for which the secant is to be calculated.
* \return A 'floatl' number representing the secant of 'x'.
*/
floatl floatl_sec(floatl x)
{
return floatl_div(FLOATL_CONST_1, floatl_cos(x));
}
/**
* \brief Calculates the cosecant of a 'floatl' number.
* \param x: The 'floatl' number for which the cosecant is to be calculated.
* \return A 'floatl' number representing the cosecant of 'x'.
*/
floatl floatl_csc(floatl x)
{
return floatl_div(FLOATL_CONST_1, floatl_sin(x));
}
/**
* \brief Calculates the tangent of a 'floatl' number.
* \param x: The 'floatl' number for which the tangent is to be calculated.
* \return A 'floatl' number representing the tangent of 'x'. Returns infinity or negative infinity
* if the cosine of 'x' is zero.
*/
floatl floatl_tan(floatl x)
{
floatl s = floatl_sin(x);
floatl c = floatl_cos(x);
if (floatl_eq(c, FLOATL_CONST_0))
{
return (floatl_gt(s, FLOATL_CONST_0)) ? FLOATL_INF : floatl_neg(FLOATL_INF);
}
return floatl_div(s, c);
}
/**
* \brief Calculates the cotangent of a 'floatl' number.
* \param x: The 'floatl' number for which the cotangent is to be calculated.
* \return A 'floatl' number representing the cotangent of 'x'.
*/
floatl floatl_cot(floatl x)
{
x = floatl_sub(floatl_mul(floatl(0.5), FLOATL_PI), x);
return floatl_tan(x);
}
/**
* \brief Calculates the exponential function of a 'floatl' number using the Taylor series expansion.
* \param x: The 'floatl' number for which the exponential is to be calculated.
* \return A 'floatl' number representing e raised to the power of 'x'.
*/
floatl floatl_exp(floatl x)
{
floatl result = FLOATL_CONST_0;
for (int n = 0; n < exp_terms; n++)
{
floatl term = floatl_int_power(x, n);
term = floatl_div(term, floatl_int_fact(n));
result = floatl_add(result, term);
}
return result;
}
/**
* \brief Calculates the natural logarithm of a 'floatl' number using the Taylor series expansion.
* \param x: The 'floatl' number for which the natural logarithm is to be calculated.
* \return A 'floatl' number representing the natural logarithm of 'x'. Returns -1 if 'x' is less than or equal to 0.
*/
floatl floatl_ln(floatl x)
{
if (floatl_le(x, FLOATL_CONST_0)) return floatl_neg(FLOATL_CONST_1);
floatl result = FLOATL_CONST_0;
// Transform x to the range (0, 2]
floatl y = floatl_sub(x, FLOATL_CONST_1);
y = floatl_div(y, floatl_add(x, FLOATL_CONST_1));
for (int n = 0; n < ln_terms; n++)
{
floatl term = floatl_int_power(y, 2 * n + 1);
term = floatl_div(term, floatl(2 * n + 1));
result = floatl_add(result, term);
}
result = floatl_mul(result, floatl(2.0));
return result;
}
/**
* \brief Calculates the logarithm of a 'floatl' number with a given base.
* \param x: The base 'floatl' number.
* \param y: The 'floatl' number for which the logarithm is to be calculated.
* \return A 'floatl' number representing the logarithm of 'y' with base 'x'. Returns negative infinity
* if 'x' is zero or 'y' is less than or equal to 0.
*/
floatl floatl_log(floatl x, floatl y)
{
if ((floatl_eq(x, FLOATL_CONST_0)) || (floatl_le(y, FLOATL_CONST_0))) return floatl_neg(FLOATL_INF);
return floatl_div(floatl_ln(y), floatl_ln(x));
}
/**
* \brief Calculates the logarithm of a 'floatl' number with base 2.
* \param x: The 'floatl' number for which the logarithm is to be calculated.
* \return A 'floatl' number representing the logarithm of 'x' with base 2. Returns negative infinity
* if 'x' is zero.
*/
floatl floatl_log2(floatl x)
{
if (floatl_eq(x, FLOATL_CONST_0)) return floatl_neg(FLOATL_INF);
return floatl_div(floatl_ln(x), floatl_ln(floatl(2.0)));
}
/**
* \brief Calculates the logarithm of a 'floatl' number with base 10.
* \param x: The 'floatl' number for which the logarithm is to be calculated.
* \return A 'floatl' number representing the logarithm of 'x' with base 10. Returns negative infinity
* if 'x' is zero.
*/
floatl floatl_log10(floatl x)
{
if (floatl_eq(x, FLOATL_CONST_0)) return floatl_neg(FLOATL_INF);
return floatl_div(floatl_ln(x), floatl_ln(floatl(10.0)));
}
/**
* \brief Calculates the sigmoid function of a 'floatl' number.
* \param x: The 'floatl' number for which the sigmoid is to be calculated.
* \return A 'floatl' number representing the sigmoid of 'x'.
*/
floatl floatl_sigmoid(floatl x)
{
return floatl_div(FLOATL_CONST_1, floatl_add(FLOATL_CONST_1, floatl_exp(floatl_neg(x))));
}
/**
* \brief Calculates the derivative of the sigmoid function of a 'floatl' number.
* \param x: The 'floatl' number for which the derivative of the sigmoid is to be calculated.
* \return A 'floatl' number representing the derivative of the sigmoid of 'x'.
*/
floatl floatl_dsigmoid(floatl x)
{
floatl s = floatl_sigmoid(x);
return floatl_mul(s, floatl_sub(FLOATL_CONST_1, s));
}
/**
* \brief Calculates the hyperbolic sine of a 'floatl' number.
* \param x: The 'floatl' number for which the hyperbolic sine is to be calculated.
* \return A 'floatl' number representing the hyperbolic sine of 'x'.
*/
floatl floatl_sinh(floatl x)
{
floatl a = floatl_exp(x);
return floatl_div(floatl_sub(a, floatl_div(FLOATL_CONST_1, a)), floatl(2.0));
}
/**
* \brief Calculates the hyperbolic cosine of a 'floatl' number.
* \param x: The 'floatl' number for which the hyperbolic cosine is to be calculated.
* \return A 'floatl' number representing the hyperbolic cosine of 'x'.
*/
floatl floatl_cosh(floatl x)
{
floatl a = floatl_exp(x);
return floatl_div(floatl_add(a, floatl_div(FLOATL_CONST_1, a)), floatl(2.0));
}
/**
* \brief Calculates the hyperbolic tangent of a 'floatl' number.
* \param x: The 'floatl' number for which the hyperbolic tangent is to be calculated.
* \return A 'floatl' number representing the hyperbolic tangent of 'x'.
*/
floatl floatl_tanh(floatl x)
{
floatl a = floatl_exp(x);
floatl b = floatl_div(FLOATL_CONST_1, a);
return floatl_div(floatl_sub(a, b), floatl_add(a, b));
}
/**
* \brief Calculates the hyperbolic cotangent of a 'floatl' number.
* \param x: The 'floatl' number for which the hyperbolic cotangent is to be calculated.
* \return A 'floatl' number representing the hyperbolic cotangent of 'x'.
*/
floatl floatl_coth(floatl x)
{
floatl a = floatl_exp(x);
floatl b = floatl_div(FLOATL_CONST_1, a);
return floatl_div(floatl_add(a, b), floatl_sub(a, b));
}
/**
* \brief Calculates the hyperbolic secant of a 'floatl' number.
* \param x: The 'floatl' number for which the hyperbolic secant is to be calculated.
* \return A 'floatl' number representing the hyperbolic secant of 'x'.
*/
floatl floatl_sech(floatl x)
{
floatl a = floatl_exp(x);
return floatl_div(floatl(2.0), floatl_add(a, floatl_div(FLOATL_CONST_1, a)));
}
/**
* \brief Calculates the hyperbolic cosecant of a 'floatl' number.
* \param x: The 'floatl' number for which the hyperbolic cosecant is to be calculated.
* \return A 'floatl' number representing the hyperbolic cosecant of 'x'.
*/
floatl floatl_csch(floatl x)
{
floatl a = floatl_exp(x);
return floatl_div(floatl(2.0), floatl_sub(a, floatl_div(FLOATL_CONST_1, a)));
}
/**
* \brief Calculates the square root of a 'floatl' number using the Newton - Raphson method.
* \param x: The 'floatl' number for which the square root is to be calculated.
* \return A 'floatl' number representing the square root of 'x'. Returns -1 if 'x' is less than 0.
*/
floatl floatl_sqrt(floatl x)
{
if (floatl_lt(x, FLOATL_CONST_0)) return floatl_neg(FLOATL_CONST_1);
floatl a = x; // Initial guess
floatl epsilon = floatl(1e-7); // Precision
while (floatl_gt(floatl_sub(floatl_mul(a, a), x), epsilon))
{
a = floatl_add(a, floatl_div(x, a));
a = floatl_div(a, floatl(2.0));
}
return a;
}
/**
* \brief Calculates the power of a 'floatl' number with another 'floatl' exponent.
* \param x: The base 'floatl' number.
* \param y: The exponent 'floatl' number.
* \return A 'floatl' number representing 'x' raised to the power of 'y'.
*/
floatl floatl_pow(floatl x, floatl y)
{
return floatl_exp(floatl_mul(y, floatl_ln(x)));
}

48
source/07_math/flmath.h Normal file
View File

@ -0,0 +1,48 @@
/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file flmath.h
* \unit flmath
* \brief This is a simple large float number math calculate module for C language
* \author Lamdonn
* \version v1.0.1
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#ifndef __flmath_H
#define __flmath_H
#include "floatl.h"
/* Version infomation */
#define FLMATH_V_MAJOR 1
#define FLMATH_V_MINOR 0
#define FLMATH_V_PATCH 0
floatl floatl_sin(floatl x);
floatl floatl_cos(floatl x);
floatl floatl_sec(floatl x);
floatl floatl_csc(floatl x);
floatl floatl_tan(floatl x);
floatl floatl_exp(floatl x);
floatl floatl_ln(floatl x);
floatl floatl_log(floatl x, floatl y);
floatl floatl_log2(floatl x);
floatl floatl_log10(floatl x);
floatl floatl_sigmoid(floatl x);
floatl floatl_dsigmoid(floatl x);
floatl floatl_sinh(floatl x);
floatl floatl_cosh(floatl x);
floatl floatl_tanh(floatl x);
floatl floatl_coth(floatl x);
floatl floatl_sech(floatl x);
floatl floatl_csch(floatl x);
floatl floatl_sqrt(floatl x);
floatl floatl_pow(floatl x, floatl y);
#endif

View File

@ -2029,6 +2029,167 @@ floatl floatl_neg(floatl a)
return a;
}
/**
* \brief Computes the ceiling of a 'floatl' number.
* \param[in] a: The 'floatl' number for which the ceiling value is to be computed.
* \return A 'floatl' number representing the ceiling of the input number.
*
* This function calculates the ceiling of a 'floatl' number. The ceiling of a number is the smallest
* integer that is greater than or equal to the given number.
*/
floatl floatl_ceil(floatl a)
{
// Calculate the actual exponent value by subtracting the mid - point of the exponent range
int32_t exponent = a.exponent - __FLOATL_EXP_MID_VALUE__;
// If the exponent is negative, the number lies between - 1 and 1
if (exponent < 0)
{
// If the number is greater than 0, the ceiling is 1
if (floatl_gt(a, FLOATL_CONST_0))
{
return FLOATL_CONST_1;
}
// If the number is equal to 0, the ceiling is 0
else if (floatl_eq(a, FLOATL_CONST_0))
{
return FLOATL_CONST_0;
}
// If the number is less than 0, the ceiling is 0 (in the context of floating - point representation)
else
{
return floatl_neg(FLOATL_CONST_0);
}
}
// Calculate the number of bits to shift to isolate the integer part
int32_t shift = __FLOATL_MANT_BITS__ - exponent;
// If the shift is less than or equal to 0, the number is already an integer
if (shift <= 0) return a;
// Create a floatl number with the least significant bit set to 1
floatl int1 = FLOATL_CONST_0;
int1.u32[0] = 1;
// Create a mask to isolate the fractional part
floatl mask = floatl_int_sub(floatl_int_shl(int1, shift), int1);
// Clear the fractional part of the number
floatl result = floatl_int_and(a, floatl_int_not(mask));
// If the result is less than the original number, increment the result
if (floatl_lt(result, a))
{
result = floatl_add(result, FLOATL_CONST_1);
}
return result;
}
/**
* \brief Computes the floor of a 'floatl' number.
* \param[in] a: The 'floatl' number for which the floor value is to be computed.
* \return A 'floatl' number representing the floor of the input number.
*
* This function calculates the floor of a 'floatl' number. The floor of a number is the largest
* integer that is less than or equal to the given number.
*/
floatl floatl_floor(floatl a)
{
// Calculate the actual exponent value by subtracting the mid - point of the exponent range
int32_t exponent = a.exponent - __FLOATL_EXP_MID_VALUE__;
// If the exponent is negative, the number lies between - 1 and 1
if (exponent < 0)
{
// If the number is greater than or equal to 0, the floor is 0
if (floatl_ge(a, FLOATL_CONST_0))
{
return FLOATL_CONST_0;
}
// If the number is less than 0, the floor is - 1
else
{
return floatl_neg(FLOATL_CONST_1);
}
}
// Calculate the number of bits to shift to isolate the integer part
int32_t shift = __FLOATL_MANT_BITS__ - exponent;
// If the shift is less than or equal to 0, the number is already an integer
if (shift <= 0) return a;
// Create a floatl number with the least significant bit set to 1
floatl int1 = FLOATL_CONST_0;
int1.u32[0] = 1;
// Create a mask to isolate the fractional part
floatl mask = floatl_int_sub(floatl_int_shl(int1, shift), int1);
// Clear the fractional part of the number
floatl result = floatl_int_and(a, floatl_int_not(mask));
// If the result is greater than the original number, decrement the result
if (floatl_gt(result, a))
{
result = floatl_sub(result, FLOATL_CONST_1);
}
return result;
}
/**
* \brief Rounds a 'floatl' number to the nearest integer.
* \param[in] a: The 'floatl' number to be rounded.
* \return A 'floatl' number representing the rounded value of the input number.
*
* This function rounds a 'floatl' number to the nearest integer. If the fractional part
* is 0.5 or greater, the number is rounded up; otherwise, it is rounded down.
*/
floatl floatl_round(floatl a)
{
// Calculate the actual exponent value by subtracting the mid - point of the exponent range
int32_t exponent = a.exponent - __FLOATL_EXP_MID_VALUE__;
// If the exponent is negative, the number lies between - 1 and 1
if (exponent < 0)
{
if (floatl_gt(a, FLOATL_CONST_0))
{
// If the number is greater than 0, round up if it is greater than or equal to 0.5
return (floatl_ge(a, floatl(0.5))) ? FLOATL_CONST_1 : FLOATL_CONST_0;
}
else
{
// If the number is less than 0, round down if it is less than or equal to - 0.5
return (floatl_le(a, floatl(-0.5))) ? floatl_neg(FLOATL_CONST_1) : floatl_neg(FLOATL_CONST_0);
}
}
// Calculate the number of bits to shift to isolate the integer part
int32_t shift = __FLOATL_MANT_BITS__ - exponent;
// If the shift is less than or equal to 0, the number is already an integer
if (shift <= 0) return a;
// Create a floatl number with the least significant bit set to 1
floatl int1 = FLOATL_CONST_0;
int1.u32[0] = 1;
// Create a mask to isolate the fractional part
floatl mask = floatl_int_sub(floatl_int_shl(int1, shift), int1);
// Clear the fractional part of the number to get the integer part
floatl result = floatl_int_and(a, floatl_int_not(mask));
// Extract the fractional part of the number
floatl fractional = floatl_int_and(a, mask);
// Check if the fractional part is greater than or equal to 0.5
if (floatl_int_ucmp(fractional, floatl_int_shl(int1, shift - 1)) >= 0)
{
// If so, round up the result
result = floatl_add(result, FLOATL_CONST_1);
}
return result;
}
/**
* \brief Perform a right shift operation on a 'floatl' value while preserving the sticky bit.
* \param[in] mant: The 'floatl' value to be shifted.

View File

@ -32,7 +32,15 @@
*/
#define FLOATL_INF __FLOATL_INF__
#define FLOATL_INF_N floatl_neg(__FLOATL_INF__)
#define FLOATL_NAN __FLOATL_NAN__
#define FLOATL_PI __FLOATL_CONST_PI__
#define FLOATL_E __FLOATL_CONST_E__
#define FLOATL_MIN __FLOATL_MIN__
#define FLOATL_MAX __FLOATL_MAX__
#define FLOATL_EPSILON __FLOATL_EPSILON__
#define FLOATL_CONST_PI __FLOATL_CONST_PI__
#define FLOATL_CONST_E __FLOATL_CONST_E__
#define FLOATL_CONST_0 __FLOATL_CONST_0__
#define FLOATL_CONST_1 __FLOATL_CONST_1__
#define FLOATL_CONST_10 __FLOATL_CONST_1e1__
@ -55,6 +63,14 @@
#define FLOATL_CONST_1e14 __FLOATL_CONST_1e14__
#define FLOATL_CONST_1e15 __FLOATL_CONST_1e15__
#define FLOATL_MANT_DIG __FLOATL_MANT_DIG__
#define FLOATL_MIN_EXP __FLOATL_MIN_EXP__
#define FLOATL_MAX_EXP __FLOATL_MAX_EXP__
#define FLOATL_DIG __FLOATL_DIG__
#define FLOATL_DECIMAL_DIG __FLOATL_DECIMAL_DIG__
#define FLOATL_MIN_10_EXP __FLOATL_MIN_10_EXP__
#define FLOATL_MAX_10_EXP __FLOATL_MAX_10_EXP__
/**
* \brief A structure to represent a long bits integer.
*
@ -122,9 +138,15 @@ int floatl_isnormal(floatl a);
// Value modification functions
// floatl_abs: Computes the absolute value of a floatl number
// floatl_neg: Computes the negation of a floatl number, equivalent to the unary '-' operator
// floatl_ceil: Computes the ceiling value of a floatl number
// floatl_floor: Computes the floor value of a floatl number
// floatl_round: Computes the round value of a floatl number
floatl floatl_abs(floatl a);
floatl floatl_neg(floatl a);
floatl floatl_ceil(floatl a);
floatl floatl_floor(floatl a);
floatl floatl_round(floatl a);
// Conversion functions
// floatl_from: Converts a string to a floatl number

File diff suppressed because one or more lines are too long

View File

@ -38,6 +38,7 @@ TEST_LIST += dList
TEST_LIST += cQueue
TEST_LIST += intl
TEST_LIST += floatl
TEST_LIST += flmath
TEST_LIST += ramt
TEST_LIST += romt
# TEST_LIST += cpul

190
test/test_flmath.c Normal file
View File

@ -0,0 +1,190 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <float.h>
#if defined(TEST_TARGET_flmath)
#include <varch/command.h>
#include <varch/unitt.h>
#include <varch/flmath.h>
#else
#include "init.h"
#include "command.h"
#include "unitt.h"
#include "kern.h"
#include "flmath.h"
#endif
static char buffer[1024] = {0};
/************************************************************************************/
/************************************* Unit Test ************************************/
/************************************************************************************/
// #define EXIT_TEST
extern uint64_t unitt_clock(void);
static int u_test_0(void)
{
for (int i = 0; i < 1000; i++)
{
}
return UNITT_E_OK;
}
static void unitt_task(void)
{
static UNITT_TCASE rand_tests[] = {
UNITT_TCASE(u_test_0),
};
static UNITT suites[] = {
{ "flmath suite", rand_tests, sizeof(rand_tests) / sizeof(rand_tests[0]) , unitt_clock },
};
UNITT_EXE(suites);
}
/************************************************************************************/
/************************************* Base Test ************************************/
/************************************************************************************/
static void test_base(void)
{
floatl p = floatl_mul(FLOATL_PI, floatl(1.0 / 2.0));
floatl sin = floatl_sin(p);
printf("sin %s\r\n", floatl_show(sin, buffer, sizeof(buffer), "%f"));
floatl cos = floatl_cos(p);
printf("cos %s\r\n", floatl_show(cos, buffer, sizeof(buffer), "%f"));
floatl tan = floatl_tan(p);
printf("tan %s\r\n", floatl_show(tan, buffer, sizeof(buffer), "%f"));
floatl exp = floatl_exp(floatl(0.0));
printf("exp %s\r\n", floatl_show(exp, buffer, sizeof(buffer), "%f"));
floatl log = floatl_ln(floatl(1.0));
printf("log %s\r\n", floatl_show(log, buffer, sizeof(buffer), "%f"));
floatl sqrt = floatl_sqrt(floatl(3.0));
printf("sqrt %s\r\n", floatl_show(sqrt, buffer, sizeof(buffer), "%f"));
floatl pow = floatl_pow(floatl(2.0), floatl(3.0));
printf("pow %s\r\n", floatl_show(pow, buffer, sizeof(buffer), "%f"));
}
/************************************************************************************/
/************************************* Command ************************************/
/************************************************************************************/
static void usage(void)
{
printf(
"Usage: floatl [opt] [arg] ...\n"
"\n"
"options:\n"
" -e <execute> Specifies the function to execute, the default is the <base> test\n"
" <base> Test base function\n"
" <ut> Unit test\n"
" <define> Test define function\n"
" <cal> Calculate string math expression\n"
" <gen> Generate the floatl configuration file code segment, need specify -f -b\n"
" <print> Print an floatl number\n"
" <error> Function that tests for floatl errors\n"
" -l <format> Format string, 10d, 08x, ...\n"
" -o <op function> Operate function, add, sub, mul, div, ...\n"
" -n <floatl> floatl number expression\n"
" -f <filename> File name, temporarily store configuration code segment\n"
" -b <bits> Maximum number of configured bits\n"
" -h Print help\n"
" -v Print version\n"
" -u [<period>] Unit test period, unit ms, the default is 1000ms\n"
"\n"
);
}
static int test(int argc, char *argv[])
{
char *execute = NULL;
int ut_period = 1000;
/* reset getopt */
command_opt_init();
while (1)
{
int opt = command_getopt(argc, argv, "e:hvu::");
if (opt == -1) break;
switch (opt)
{
case 'u' :
if (command_optarg) ut_period = atoi(command_optarg);
break;
case 'e' :
execute = command_optarg;
break;
case 'v' :
printf("floatl version %d.%d.%d\r\n", FLMATH_V_MAJOR, FLMATH_V_MINOR, FLMATH_V_PATCH);
return 0;
case '?':
printf("Unknown option `%c`\r\n", command_optopt);
return -1;
case 'h' :
default:
usage();
return 0;
}
}
if (execute)
{
if (!strcmp(execute, "base"))
{
test_base();
}
else if (!strcmp(execute, "ut"))
{
srand((uint32_t)time(NULL));
#if defined(TEST_TARGET_flmath)
while (1)
{
unitt_task();
usleep(1000 * ut_period);
}
#else
printf("create task %d\r\n", task_create(ut_period, unitt_task));
#endif
}
}
else
{
test_base();
}
return 0;
}
/************************************************************************************/
/************************************ Test entry ************************************/
/************************************************************************************/
#if defined(TEST_TARGET_flmath)
int main(int argc, char *argv[])
{
return test(argc, argv);
}
#else
void test_flmath(void)
{
command_export("flmath", test);
}
init_export_app(test_flmath);
#endif

View File

@ -243,6 +243,115 @@ static double double_from_uint64(uint64_t value)
return v.double_;
}
// 将 double 的二进制表示转换为 uint64_t
typedef unsigned long long uint64_t;
typedef long long int64_t;
uint64_t double_to_bits(double x) {
return *((uint64_t*)&x);
}
double bits_to_double(uint64_t bits) {
return *((double*)&bits);
}
// double_ceil 实现
double double_ceil(double x) {
uint64_t bits = double_to_bits(x);
int64_t exponent = ((bits >> 52) & 0x7FF) - 1023;
if (exponent < 0) {
// 如果指数为负,说明 x 在 (-1, 1) 之间
if (x > 0) {
return 1.0;
} else if (x == 0.0) {
return 0.0;
} else {
return -0.0;
}
}
int shift = 52 - exponent;
if (shift <= 0) {
// 如果 x 已经是整数,直接返回 x
return x;
}
uint64_t mask = (1ULL << shift) - 1;
uint64_t truncated = bits & ~mask;
double result = bits_to_double(truncated);
if (result < x) {
result += 1.0;
}
return result;
}
// double_floor 实现
double double_floor(double x) {
uint64_t bits = double_to_bits(x);
int64_t exponent = ((bits >> 52) & 0x7FF) - 1023;
if (exponent < 0) {
// 如果指数为负,说明 x 在 (-1, 1) 之间
if (x >= 0) {
return 0.0;
} else {
return -1.0;
}
}
int shift = 52 - exponent;
if (shift <= 0) {
// 如果 x 已经是整数,直接返回 x
return x;
}
uint64_t mask = (1ULL << shift) - 1;
uint64_t truncated = bits & ~mask;
double result = bits_to_double(truncated);
if (result > x) {
result -= 1.0;
}
return result;
}
// double_round 实现
double double_round(double x) {
uint64_t bits = double_to_bits(x);
int64_t exponent = ((bits >> 52) & 0x7FF) - 1023;
if (exponent < 0) {
// 如果指数为负,说明 x 在 (-1, 1) 之间
if (x > 0) {
return (x >= 0.5) ? 1.0 : 0.0;
} else {
return (x <= -0.5) ? -1.0 : -0.0;
}
}
int shift = 52 - exponent;
if (shift <= 0) {
// 如果 x 已经是整数,直接返回 x
return x;
}
uint64_t mask = (1ULL << shift) - 1;
uint64_t truncated = bits & ~mask;
double result = bits_to_double(truncated);
uint64_t fractional = bits & mask;
if (fractional >= (1ULL << (shift - 1))) {
result += 1.0;
}
return result;
}
static const char* float_show_raw(float x)
{
float_u a = {.float_ = x};
@ -754,19 +863,27 @@ typedef struct
{
uint32_t buffer[256];
uint32_t FLOATL_BIT_PARTS; // bits
uint32_t FLOATL_U32_PARTS; // FLOATL_BIT_PARTS / 32 ---- FLOATL_BIT_PARTS >> 5
uint32_t FLOATL_U16_PARTS; // FLOATL_BIT_PARTS / 16 ---- FLOATL_BIT_PARTS >> 4
uint32_t FLOATL_EXP_BITS; // floatl_cfg_gen_exp(FLOATL_BIT_PARTS)
uint32_t FLOATL_MANT_BITS; // FLOATL_BIT_PARTS - FLOATL_EXP_BITS - 1
uint32_t FLOATL_MANT_PARTS; // FLOATL_MANT_BITS / 32 ---- FLOATL_MANT_BITS >> 5
uint32_t FLOATL_MANT_HIGH_BITS; // FLOATL_MANT_BITS % 32 ---- FLOATL_MANT_BITS & 0x1F
uint32_t FLOATL_EXP_MID_VALUE; // 2^(FLOATL_EXP_BITS-1) - 1
uint32_t FLOATL_EXP_WHL_VALUE; // 2^(FLOATL_EXP_BITS) - 1
uint32_t FLOATL_BIT_PARTS__; // bits
uint32_t FLOATL_U32_PARTS__; // FLOATL_BIT_PARTS__ / 32 ---- FLOATL_BIT_PARTS__ >> 5
uint32_t FLOATL_U16_PARTS__; // FLOATL_BIT_PARTS__ / 16 ---- FLOATL_BIT_PARTS__ >> 4
uint32_t FLOATL_EXP_BITS__; // floatl_cfg_gen_exp(FLOATL_BIT_PARTS__)
uint32_t FLOATL_MANT_BITS__; // FLOATL_BIT_PARTS__ - FLOATL_EXP_BITS__ - 1
uint32_t FLOATL_MANT_PARTS__; // FLOATL_MANT_BITS__ / 32 ---- FLOATL_MANT_BITS__ >> 5
uint32_t FLOATL_MANT_HIGH_BITS__; // FLOATL_MANT_BITS__ % 32 ---- FLOATL_MANT_BITS__ & 0x1F
uint32_t FLOATL_EXP_MID_VALUE__; // 2^(FLOATL_EXP_BITS__-1) - 1
uint32_t FLOATL_EXP_WHL_VALUE__; // 2^(FLOATL_EXP_BITS__) - 1
uint32_t FLOATL2_BIT_PARTS; // FLOATL_BIT_PARTS * 2
uint32_t FLOATL2_U32_PARTS; // FLOATL2_BIT_PARTS / 32 ---- FLOATL2_BIT_PARTS >> 5
uint32_t FLOATL2_U16_PARTS; // FLOATL2_BIT_PARTS / 16 ---- FLOATL2_BIT_PARTS >> 4
uint32_t FLOATL2_BIT_PARTS__; // FLOATL_BIT_PARTS__ * 2
uint32_t FLOATL2_U32_PARTS__; // FLOATL2_BIT_PARTS__ / 32 ---- FLOATL2_BIT_PARTS__ >> 5
uint32_t FLOATL2_U16_PARTS__; // FLOATL2_BIT_PARTS__ / 16 ---- FLOATL2_BIT_PARTS__ >> 4
uint32_t FLOATL_MANT_DIG__; // FLOATL_MANT_BITS__ + 1
int32_t FLOATL_MIN_EXP__; // - FLOATL_EXP_MID_VALUE__ + 2
uint32_t FLOATL_MAX_EXP__; // FLOATL_EXP_MID_VALUE__ + 1
uint32_t FLOATL_DIG__; // floor(log10(2) * FLOATL_MANT_DIG__)
uint32_t FLOATL_DECIMAL_DIG__; // ceil(log10(2) * FLOATL_MANT_DIG__) + 1
int32_t FLOATL_MIN_10_EXP__; // ceil(log10(2) * (1 - FLOATL_EXP_MID_VALUE__))
uint32_t FLOATL_MAX_10_EXP__; // - FLOATL_MIN_10_EXP__ + 1
} FLINFO;
typedef struct
@ -830,7 +947,7 @@ void floatl_cfg_const_out(FILE* file, FLINFO *info)
if (!file || !info) return;
fprintf(file, "(floatl){.u32={");
for (int i = 0; i < info->FLOATL_U32_PARTS; i++)
for (int i = 0; i < info->FLOATL_U32_PARTS__; i++)
{
uint32_t value = info->buffer[i];
if (value == 0) fprintf(file, "0,");
@ -844,28 +961,35 @@ int floatl_cfg_info_init(FLINFO *info, unsigned int bits)
{
if ((bits & (bits - 1)) != 0) return 0;
info->FLOATL_BIT_PARTS = bits;
info->FLOATL_U32_PARTS = info->FLOATL_BIT_PARTS >> (5);
info->FLOATL_U16_PARTS = info->FLOATL_BIT_PARTS >> (4);
info->FLOATL_EXP_BITS = floatl_cfg_gen_exp(info->FLOATL_BIT_PARTS);
info->FLOATL_MANT_BITS = info->FLOATL_BIT_PARTS - info->FLOATL_EXP_BITS - 1;
info->FLOATL_MANT_PARTS = info->FLOATL_MANT_BITS >> 5;
info->FLOATL_MANT_HIGH_BITS = info->FLOATL_MANT_BITS & 0x1F;
info->FLOATL_EXP_MID_VALUE = (uint32_t)pow(2, info->FLOATL_EXP_BITS - 1) - 1;
info->FLOATL_EXP_WHL_VALUE = (uint32_t)pow(2, info->FLOATL_EXP_BITS) - 1;
info->FLOATL2_BIT_PARTS = info->FLOATL_BIT_PARTS * 2;
info->FLOATL2_U32_PARTS = info->FLOATL2_BIT_PARTS >> (5);
info->FLOATL2_U16_PARTS = info->FLOATL2_BIT_PARTS >> (4);
info->FLOATL_BIT_PARTS__ = bits;
info->FLOATL_U32_PARTS__ = info->FLOATL_BIT_PARTS__ >> (5);
info->FLOATL_U16_PARTS__ = info->FLOATL_BIT_PARTS__ >> (4);
info->FLOATL_EXP_BITS__ = floatl_cfg_gen_exp(info->FLOATL_BIT_PARTS__);
info->FLOATL_MANT_BITS__ = info->FLOATL_BIT_PARTS__ - info->FLOATL_EXP_BITS__ - 1;
info->FLOATL_MANT_PARTS__ = info->FLOATL_MANT_BITS__ >> 5;
info->FLOATL_MANT_HIGH_BITS__ = info->FLOATL_MANT_BITS__ & 0x1F;
info->FLOATL_EXP_MID_VALUE__ = (uint32_t)pow(2, info->FLOATL_EXP_BITS__ - 1) - 1;
info->FLOATL_EXP_WHL_VALUE__ = (uint32_t)pow(2, info->FLOATL_EXP_BITS__) - 1;
info->FLOATL2_BIT_PARTS__ = info->FLOATL_BIT_PARTS__ * 2;
info->FLOATL2_U32_PARTS__ = info->FLOATL2_BIT_PARTS__ >> (5);
info->FLOATL2_U16_PARTS__ = info->FLOATL2_BIT_PARTS__ >> (4);
info->FLOATL_MANT_DIG__ = info->FLOATL_MANT_BITS__ + 1;
info->FLOATL_MIN_EXP__ = - info->FLOATL_EXP_MID_VALUE__ + 2;
info->FLOATL_MAX_EXP__ = info->FLOATL_EXP_MID_VALUE__ + 1;
info->FLOATL_DIG__ = floor(log10(2) * info->FLOATL_MANT_DIG__);
info->FLOATL_DECIMAL_DIG__ = ceil(log10(2) * info->FLOATL_MANT_DIG__) + 1;
info->FLOATL_MIN_10_EXP__ = ceil(log10(2) * (int32_t)(1 - info->FLOATL_EXP_MID_VALUE__));
info->FLOATL_MAX_10_EXP__ = - info->FLOATL_MIN_10_EXP__ + 1;
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
return 1;
}
FLINFO *floatl_cfg_set_sign(FLINFO *info, int sign)
{
if (sign) info->buffer[info->FLOATL_U32_PARTS - 1] |= (1 << 31);
else info->buffer[info->FLOATL_U32_PARTS - 1] &= ~(1 << 31);
if (sign) info->buffer[info->FLOATL_U32_PARTS__ - 1] |= (1 << 31);
else info->buffer[info->FLOATL_U32_PARTS__ - 1] &= ~(1 << 31);
return info;
}
@ -873,25 +997,25 @@ FLINFO *floatl_cfg_set_exp_real(FLINFO *info, uint32_t t)
{
uint32_t temp = 1;
temp <<= info->FLOATL_EXP_BITS;
temp <<= info->FLOATL_EXP_BITS__;
temp -= 1;
t &= temp;
t <<= (32 - info->FLOATL_EXP_BITS - 1);
t <<= (32 - info->FLOATL_EXP_BITS__ - 1);
temp <<= (32 - info->FLOATL_EXP_BITS - 1);
temp <<= (32 - info->FLOATL_EXP_BITS__ - 1);
info->buffer[info->FLOATL_U32_PARTS - 1] &= (~temp); // clear
info->buffer[info->FLOATL_U32_PARTS__ - 1] &= (~temp); // clear
info->buffer[info->FLOATL_U32_PARTS - 1] |= t;
info->buffer[info->FLOATL_U32_PARTS__ - 1] |= t;
return info;
}
FLINFO *floatl_cfg_set_exp(FLINFO *info, int32_t e)
{
return floatl_cfg_set_exp_real(info, e + info->FLOATL_EXP_MID_VALUE);
return floatl_cfg_set_exp_real(info, e + info->FLOATL_EXP_MID_VALUE__);
}
FLINFO *floatl_cfg_set_mant(FLINFO *info, char *bin)
@ -900,7 +1024,7 @@ FLINFO *floatl_cfg_set_mant(FLINFO *info, char *bin)
while (*s)
{
int index = info->FLOATL_MANT_BITS - (s - bin) - 1;
int index = info->FLOATL_MANT_BITS__ - (s - bin) - 1;
if (index < 0) break;
if (index >= 0 && *s == '1')
{
@ -917,24 +1041,24 @@ FLINFO *floatl_cfg_set_mant(FLINFO *info, char *bin)
FLINFO *floatl_cfg_int_zero(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
return info;
}
FLINFO *floatl_cfg_const_0(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
return info;
}
FLINFO *floatl_cfg_const_1(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 0xFFFFFFFF);
info->buffer[info->FLOATL_U32_PARTS - 1] &= 0xBFFFFFFF;
info->buffer[info->FLOATL_U32_PARTS__ - 1] &= 0xBFFFFFFF;
return info;
}
@ -943,7 +1067,7 @@ FLINFO *floatl_cfg_const_1eX(FLINFO *info, uint32_t e)
{
if (e >= sizeof(fle_list) / sizeof(fle_list[0])) return NULL;
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp(info, fle_list[e].exp);
floatl_cfg_set_mant(info, fle_list[e].mantBin);
@ -951,9 +1075,29 @@ FLINFO *floatl_cfg_const_1eX(FLINFO *info, uint32_t e)
return info;
}
FLINFO *floatl_cfg_const_pi(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp(info, 1);
floatl_cfg_set_mant(info, FLOATL_CFG_MANT_PI);
return info;
}
FLINFO *floatl_cfg_const_e(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp(info, 1);
floatl_cfg_set_mant(info, FLOATL_CFG_MANT_E);
return info;
}
FLINFO *floatl_cfg_inf(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 0xFFFFFFFF);
@ -962,26 +1106,26 @@ FLINFO *floatl_cfg_inf(FLINFO *info)
FLINFO *floatl_cfg_nan(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 0xFFFFFFFF);
info->buffer[info->FLOATL_U32_PARTS - 1] |= 0x80000000;
info->buffer[info->FLOATL_U32_PARTS__ - 1] |= 0x80000000;
return info;
}
FLINFO *floatl_cfg_all_sign(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
info->buffer[info->FLOATL_U32_PARTS - 1] |= 0x80000000;
info->buffer[info->FLOATL_U32_PARTS__ - 1] |= 0x80000000;
return info;
}
FLINFO *floatl_cfg_all_exp(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 0xFFFFFFFF);
@ -990,26 +1134,26 @@ FLINFO *floatl_cfg_all_exp(FLINFO *info)
FLINFO *floatl_cfg_all_mant(FLINFO *info)
{
memset(info->buffer, -1, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, -1, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 0);
info->buffer[info->FLOATL_U32_PARTS - 1] &= (~0x80000000);
info->buffer[info->FLOATL_U32_PARTS__ - 1] &= (~0x80000000);
return info;
}
FLINFO *floatl_cfg_all_exp_mant(FLINFO *info)
{
memset(info->buffer, -1, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, -1, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
info->buffer[info->FLOATL_U32_PARTS - 1] &= (~0x80000000);
info->buffer[info->FLOATL_U32_PARTS__ - 1] &= (~0x80000000);
return info;
}
FLINFO *floatl_cfg_hide_mant_bit(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 1);
@ -1018,7 +1162,7 @@ FLINFO *floatl_cfg_hide_mant_bit(FLINFO *info)
FLINFO *floatl_cfg_mant_plus_max(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 8);
@ -1027,10 +1171,38 @@ FLINFO *floatl_cfg_mant_plus_max(FLINFO *info)
FLINFO *floatl_cfg_mant_whole(FLINFO *info)
{
memset(info->buffer, -1, info->FLOATL_U32_PARTS * sizeof(uint32_t));
memset(info->buffer, -1, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 1);
info->buffer[info->FLOATL_U32_PARTS - 1] &= (~0x80000000);
info->buffer[info->FLOATL_U32_PARTS__ - 1] &= (~0x80000000);
return info;
}
FLINFO *floatl_cfg_min(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_exp_real(info, 1);
return info;
}
FLINFO *floatl_cfg_max(FLINFO *info)
{
memset(info->buffer, -1, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
floatl_cfg_set_sign(info, 0);
floatl_cfg_set_exp_real(info, 0xFFFFFFFE);
return info;
}
FLINFO *floatl_cfg_epsilon(FLINFO *info)
{
memset(info->buffer, 0, info->FLOATL_U32_PARTS__ * sizeof(uint32_t));
info->buffer[0] |= 1;
return info;
}
@ -1058,6 +1230,13 @@ void floatl_cfg_generate(uint32_t bits, const char *filename)
return;
}
/* Enable PI and E mant configurations */
if (!FLOATL_CFG_MANT_PI || !FLOATL_CFG_MANT_E)
{
fprintf(stdout, "[ERROR] Enable `FLOATL_CFG_MANT_PI` and `FLOATL_CFG_MANT_E` in `floatl_cfg.h` file"NEWLINE);
return;
}
/* Limiting the minimum bit */
if (bits < MINBITS)
{
@ -1098,19 +1277,27 @@ void floatl_cfg_generate(uint32_t bits, const char *filename)
FLINFO info;
floatl_cfg_info_init(&info, tb);
fprintf(output, "#define __FLOATL_BIT_PARTS__ %u"NEWLINE, info.FLOATL_BIT_PARTS );
fprintf(output, "#define __FLOATL_U32_PARTS__ %u"NEWLINE, info.FLOATL_U32_PARTS );
fprintf(output, "#define __FLOATL_U16_PARTS__ %u"NEWLINE, info.FLOATL_U16_PARTS );
fprintf(output, "#define __FLOATL_EXP_BITS__ %u"NEWLINE, info.FLOATL_EXP_BITS );
fprintf(output, "#define __FLOATL_MANT_BITS__ %u"NEWLINE, info.FLOATL_MANT_BITS );
fprintf(output, "#define __FLOATL_MANT_PARTS__ %u"NEWLINE, info.FLOATL_MANT_PARTS );
fprintf(output, "#define __FLOATL_MANT_HIGH_BITS__ %u"NEWLINE, info.FLOATL_MANT_HIGH_BITS );
fprintf(output, "#define __FLOATL_EXP_MID_VALUE__ %u"NEWLINE, info.FLOATL_EXP_MID_VALUE );
fprintf(output, "#define __FLOATL_EXP_WHL_VALUE__ %u"NEWLINE, info.FLOATL_EXP_WHL_VALUE );
fprintf(output, "#define __FLOATL_BIT_PARTS__ %u"NEWLINE, info.FLOATL_BIT_PARTS__ );
fprintf(output, "#define __FLOATL_U32_PARTS__ %u"NEWLINE, info.FLOATL_U32_PARTS__ );
fprintf(output, "#define __FLOATL_U16_PARTS__ %u"NEWLINE, info.FLOATL_U16_PARTS__ );
fprintf(output, "#define __FLOATL_EXP_BITS__ %u"NEWLINE, info.FLOATL_EXP_BITS__ );
fprintf(output, "#define __FLOATL_MANT_BITS__ %u"NEWLINE, info.FLOATL_MANT_BITS__ );
fprintf(output, "#define __FLOATL_MANT_PARTS__ %u"NEWLINE, info.FLOATL_MANT_PARTS__ );
fprintf(output, "#define __FLOATL_MANT_HIGH_BITS__ %u"NEWLINE, info.FLOATL_MANT_HIGH_BITS__ );
fprintf(output, "#define __FLOATL_EXP_MID_VALUE__ %u"NEWLINE, info.FLOATL_EXP_MID_VALUE__ );
fprintf(output, "#define __FLOATL_EXP_WHL_VALUE__ %u"NEWLINE, info.FLOATL_EXP_WHL_VALUE__ );
fprintf(output, "#define __FLOATL2_BIT_PARTS__ %u"NEWLINE, info.FLOATL2_BIT_PARTS );
fprintf(output, "#define __FLOATL2_U32_PARTS__ %u"NEWLINE, info.FLOATL2_U32_PARTS );
fprintf(output, "#define __FLOATL2_U16_PARTS__ %u"NEWLINE, info.FLOATL2_U16_PARTS );
fprintf(output, "#define __FLOATL2_BIT_PARTS__ %u"NEWLINE, info.FLOATL2_BIT_PARTS__ );
fprintf(output, "#define __FLOATL2_U32_PARTS__ %u"NEWLINE, info.FLOATL2_U32_PARTS__ );
fprintf(output, "#define __FLOATL2_U16_PARTS__ %u"NEWLINE, info.FLOATL2_U16_PARTS__ );
fprintf(output, "#define __FLOATL_MANT_DIG__ %u"NEWLINE, info.FLOATL_MANT_DIG__ );
fprintf(output, "#define __FLOATL_MIN_EXP__ %d"NEWLINE, info.FLOATL_MIN_EXP__ );
fprintf(output, "#define __FLOATL_MAX_EXP__ %u"NEWLINE, info.FLOATL_MAX_EXP__ );
fprintf(output, "#define __FLOATL_DIG__ %u"NEWLINE, info.FLOATL_DIG__ );
fprintf(output, "#define __FLOATL_DECIMAL_DIG__ %u"NEWLINE, info.FLOATL_DECIMAL_DIG__ );
fprintf(output, "#define __FLOATL_MIN_10_EXP__ %d"NEWLINE, info.FLOATL_MIN_10_EXP__ );
fprintf(output, "#define __FLOATL_MAX_10_EXP__ %u"NEWLINE, info.FLOATL_MAX_10_EXP__ );
fprintf(output, "#define __FLOATL_CONST_0__ "); floatl_cfg_const_out(output, floatl_cfg_const_0(&info) );
fprintf(output, "#define __FLOATL_CONST_1__ "); floatl_cfg_const_out(output, floatl_cfg_const_1(&info) );
@ -1130,6 +1317,8 @@ void floatl_cfg_generate(uint32_t bits, const char *filename)
fprintf(output, "#define __FLOATL_CONST_1e13__ "); floatl_cfg_const_out(output, floatl_cfg_const_1eX(&info,13) );
fprintf(output, "#define __FLOATL_CONST_1e14__ "); floatl_cfg_const_out(output, floatl_cfg_const_1eX(&info,14) );
fprintf(output, "#define __FLOATL_CONST_1e15__ "); floatl_cfg_const_out(output, floatl_cfg_const_1eX(&info,15) );
fprintf(output, "#define __FLOATL_CONST_PI__ "); floatl_cfg_const_out(output, floatl_cfg_const_pi(&info) );
fprintf(output, "#define __FLOATL_CONST_E__ "); floatl_cfg_const_out(output, floatl_cfg_const_e(&info) );
fprintf(output, "#define __FLOATL_INT_ZERO__ "); floatl_cfg_const_out(output, floatl_cfg_int_zero(&info) );
fprintf(output, "#define __FLOATL_INF__ "); floatl_cfg_const_out(output, floatl_cfg_inf(&info) );
fprintf(output, "#define __FLOATL_NAN__ "); floatl_cfg_const_out(output, floatl_cfg_nan(&info) );
@ -1140,6 +1329,9 @@ void floatl_cfg_generate(uint32_t bits, const char *filename)
fprintf(output, "#define __FLOATL_HIDE_MANT_BIT__ "); floatl_cfg_const_out(output, floatl_cfg_hide_mant_bit(&info) );
fprintf(output, "#define __FLOATL_MANT_PLUS_MAX__ "); floatl_cfg_const_out(output, floatl_cfg_mant_plus_max(&info) );
fprintf(output, "#define __FLOATL_MANT_WHL__ "); floatl_cfg_const_out(output, floatl_cfg_mant_whole(&info) );
fprintf(output, "#define __FLOATL_MIN__ "); floatl_cfg_const_out(output, floatl_cfg_min(&info) );
fprintf(output, "#define __FLOATL_MAX__ "); floatl_cfg_const_out(output, floatl_cfg_max(&info) );
fprintf(output, "#define __FLOATL_EPSILON__ "); floatl_cfg_const_out(output, floatl_cfg_epsilon(&info) );
}
fprintf(output, "#endif"NEWLINE);
@ -1158,8 +1350,6 @@ void floatl_cfg_generate(uint32_t bits, const char *filename)
{
printf("[INFO] The configuration has been generated, copy it to the `floatl_cfg.h` range specified\r\n");
}
return 0;
}
/*----------------------------------------------------------------------------------*/
@ -1360,6 +1550,18 @@ static void test_base(void)
// double_show_raw(y);
// printf("y %f e %d\r\n", y, e);
#endif
double v = -3.14;
printf("ceil %f\r\n", ceil(v));
printf("floor %f\r\n", floor(v));
printf("round %f\r\n", round(v));
printf("double_ceil %f\r\n", double_ceil(v));
printf("double_floor %f\r\n", double_floor(v));
printf("double_round %f\r\n", double_round(v));
printf("floatl_ceil %s\r\n", floatl_show(floatl_ceil(floatl(v)), buffer, sizeof(buffer), "%f"));
printf("floatl_floor %s\r\n", floatl_show(floatl_floor(floatl(v)), buffer, sizeof(buffer), "%f"));
printf("floatl_round %s\r\n", floatl_show(floatl_round(floatl(v)), buffer, sizeof(buffer), "%f"));
}
/************************************************************************************/