Skip to content

Commit

Permalink
sw/math: Add exp, sqrt, log and ceil functions
Browse files Browse the repository at this point in the history
  • Loading branch information
colluca committed Nov 8, 2023
1 parent e387f06 commit 81fe099
Show file tree
Hide file tree
Showing 29 changed files with 1,122 additions and 1 deletion.
29 changes: 28 additions & 1 deletion Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,40 @@ vendor_package:
- "Makefile"
- ".gitignore"
- "README"
- "src/math/tanh.c"
- "src/math/ceil.c"
- "src/math/ceilf.c"
- "src/math/ceill.c"
- "src/math/expm1.c"
- "src/math/expf.c"
- "src/math/exp2f_data.c"
- "src/math/exp2f_data.h"
- "src/math/log2.c"
- "src/math/log2_data.c"
- "src/math/log2_data.h"
- "src/math/log2f.c"
- "src/math/log2f_data.c"
- "src/math/log2f_data.h"
- "src/math/__math_divzero.c"
- "src/math/__math_invalid.c"
- "src/math/__math_invalidf.c"
- "src/math/__math_invalidl.c"
- "src/math/__math_oflow.c"
- "src/math/__math_oflowf.c"
- "src/math/__math_uflow.c"
- "src/math/__math_uflowf.c"
- "src/math/__math_xflow.c"
- "src/math/__math_xflowf.c"
- "src/math/sqrt.c"
- "src/math/sqrtf.c"
- "src/math/sqrt_data.c"
- "src/math/sqrt_data.h"
- "src/math/tanh.c"
- "src/internal/libm.h"
- "src/include/features.h"
- "include/endian.h"
- "include/math.h"
- "include/features.h"
- "include/float.h"
- "include/alltypes.h.in"
- "arch/riscv64/bits/alltypes.h.in"
- "arch/riscv64/bits/float.h"
Expand Down
52 changes: 52 additions & 0 deletions sw/math/include/float.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef _FLOAT_H
#define _FLOAT_H

#ifdef __cplusplus
extern "C" {
#endif

int __flt_rounds(void);
#define FLT_ROUNDS (__flt_rounds())

#define FLT_RADIX 2

#define FLT_TRUE_MIN 1.40129846432481707092e-45F
#define FLT_MIN 1.17549435082228750797e-38F
#define FLT_MAX 3.40282346638528859812e+38F
#define FLT_EPSILON 1.1920928955078125e-07F

#define FLT_MANT_DIG 24
#define FLT_MIN_EXP (-125)
#define FLT_MAX_EXP 128
#define FLT_HAS_SUBNORM 1

#define FLT_DIG 6
#define FLT_DECIMAL_DIG 9
#define FLT_MIN_10_EXP (-37)
#define FLT_MAX_10_EXP 38

#define DBL_TRUE_MIN 4.94065645841246544177e-324
#define DBL_MIN 2.22507385850720138309e-308
#define DBL_MAX 1.79769313486231570815e+308
#define DBL_EPSILON 2.22044604925031308085e-16

#define DBL_MANT_DIG 53
#define DBL_MIN_EXP (-1021)
#define DBL_MAX_EXP 1024
#define DBL_HAS_SUBNORM 1

#define DBL_DIG 15
#define DBL_DECIMAL_DIG 17
#define DBL_MIN_10_EXP (-307)
#define DBL_MAX_10_EXP 308

#define LDBL_HAS_SUBNORM 1
#define LDBL_DECIMAL_DIG DECIMAL_DIG

#include <bits/float.h>

#ifdef __cplusplus
}
#endif

#endif
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_divzero.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

double __math_divzero(uint32_t sign)
{
return fp_barrier(sign ? -1.0 : 1.0) / 0.0;
}
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_invalid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

double __math_invalid(double x)
{
return (x - x) / (x - x);
}
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_invalidf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

float __math_invalidf(float x)
{
return (x - x) / (x - x);
}
9 changes: 9 additions & 0 deletions sw/math/src/math/__math_invalidl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <float.h>
#include "libm.h"

#if LDBL_MANT_DIG != DBL_MANT_DIG
long double __math_invalidl(long double x)
{
return (x - x) / (x - x);
}
#endif
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_oflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

double __math_oflow(uint32_t sign)
{
return __math_xflow(sign, 0x1p769);
}
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_oflowf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

float __math_oflowf(uint32_t sign)
{
return __math_xflowf(sign, 0x1p97f);
}
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_uflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

double __math_uflow(uint32_t sign)
{
return __math_xflow(sign, 0x1p-767);
}
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_uflowf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

float __math_uflowf(uint32_t sign)
{
return __math_xflowf(sign, 0x1p-95f);
}
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_xflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

double __math_xflow(uint32_t sign, double y)
{
return eval_as_double(fp_barrier(sign ? -y : y) * y);
}
6 changes: 6 additions & 0 deletions sw/math/src/math/__math_xflowf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "libm.h"

float __math_xflowf(uint32_t sign, float y)
{
return eval_as_float(fp_barrierf(sign ? -y : y) * y);
}
31 changes: 31 additions & 0 deletions sw/math/src/math/ceil.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "libm.h"

#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2
#define EPS LDBL_EPSILON
#endif
static const double_t toint = 1/EPS;

double ceil(double x)
{
union {double f; uint64_t i;} u = {x};
int e = u.i >> 52 & 0x7ff;
double_t y;

if (e >= 0x3ff+52 || x == 0)
return x;
/* y = int(x) - x, where int(x) is an integer neighbor of x */
if (u.i >> 63)
y = x - toint + toint - x;
else
y = x + toint - toint - x;
/* special case because of non-nearest rounding modes */
if (e <= 0x3ff-1) {
FORCE_EVAL(y);
return u.i >> 63 ? -0.0 : 1;
}
if (y < 0)
return x + y + 1;
return x + y;
}
27 changes: 27 additions & 0 deletions sw/math/src/math/ceilf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "libm.h"

float ceilf(float x)
{
union {float f; uint32_t i;} u = {x};
int e = (int)(u.i >> 23 & 0xff) - 0x7f;
uint32_t m;

if (e >= 23)
return x;
if (e >= 0) {
m = 0x007fffff >> e;
if ((u.i & m) == 0)
return x;
FORCE_EVAL(x + 0x1p120f);
if (u.i >> 31 == 0)
u.i += m;
u.i &= ~m;
} else {
FORCE_EVAL(x + 0x1p120f);
if (u.i >> 31)
u.f = -0.0;
else if (u.i << 1)
u.f = 1.0;
}
return u.f;
}
34 changes: 34 additions & 0 deletions sw/math/src/math/ceill.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "libm.h"

#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
long double ceill(long double x)
{
return ceil(x);
}
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384

static const long double toint = 1/LDBL_EPSILON;

long double ceill(long double x)
{
union ldshape u = {x};
int e = u.i.se & 0x7fff;
long double y;

if (e >= 0x3fff+LDBL_MANT_DIG-1 || x == 0)
return x;
/* y = int(x) - x, where int(x) is an integer neighbor of x */
if (u.i.se >> 15)
y = x - toint + toint - x;
else
y = x + toint - toint - x;
/* special case because of non-nearest rounding modes */
if (e <= 0x3fff-1) {
FORCE_EVAL(y);
return u.i.se >> 15 ? -0.0 : 1;
}
if (y < 0)
return x + y + 1;
return x + y;
}
#endif
35 changes: 35 additions & 0 deletions sw/math/src/math/exp2f_data.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Shared data between expf, exp2f and powf.
*
* Copyright (c) 2017-2018, Arm Limited.
* SPDX-License-Identifier: MIT
*/

#include "exp2f_data.h"

#define N (1 << EXP2F_TABLE_BITS)

const struct exp2f_data __exp2f_data = {
/* tab[i] = uint(2^(i/N)) - (i << 52-BITS)
used for computing 2^(k/N) for an int |k| < 150 N as
double(tab[k%N] + (k << 52-BITS)) */
.tab = {
0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51,
0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1,
0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d,
0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429, 0x3feea47eb03a5585,
0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13,
0x3feeace5422aa0db, 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d,
0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069,
0x3fef5818dcfba487, 0x3fef7c97337b9b5f, 0x3fefa4afa2a490da, 0x3fefd0765b6e4540,
},
.shift_scaled = 0x1.8p+52 / N,
.poly = {
0x1.c6af84b912394p-5, 0x1.ebfce50fac4f3p-3, 0x1.62e42ff0c52d6p-1,
},
.shift = 0x1.8p+52,
.invln2_scaled = 0x1.71547652b82fep+0 * N,
.poly_scaled = {
0x1.c6af84b912394p-5/N/N/N, 0x1.ebfce50fac4f3p-3/N/N, 0x1.62e42ff0c52d6p-1/N,
},
};
23 changes: 23 additions & 0 deletions sw/math/src/math/exp2f_data.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2017-2018, Arm Limited.
* SPDX-License-Identifier: MIT
*/
#ifndef _EXP2F_DATA_H
#define _EXP2F_DATA_H

#include <features.h>
#include <stdint.h>

/* Shared between expf, exp2f and powf. */
#define EXP2F_TABLE_BITS 5
#define EXP2F_POLY_ORDER 3
extern hidden const struct exp2f_data {
uint64_t tab[1 << EXP2F_TABLE_BITS];
double shift_scaled;
double poly[EXP2F_POLY_ORDER];
double shift;
double invln2_scaled;
double poly_scaled[EXP2F_POLY_ORDER];
} __exp2f_data;

#endif
Loading

0 comments on commit 81fe099

Please sign in to comment.