#ifndef HODU_CPU_KERNELS_MATH_UTILS_H
#define HODU_CPU_KERNELS_MATH_UTILS_H
#include "constants.h"
#include <math.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
static inline int64_t ipow_i64(int64_t base, int64_t exp) {
if (exp < 0)
return 0;
int64_t result = 1;
while (exp > 0) {
if (exp & 1)
result *= base;
base *= base;
exp >>= 1;
}
return result;
}
static inline uint64_t ipow_u64(uint64_t base, uint64_t exp) {
uint64_t result = 1;
while (exp > 0) {
if (exp & 1)
result *= base;
base *= base;
exp >>= 1;
}
return result;
}
static inline float powf_opt(float base, float exponent) {
if (exponent == 0.0f)
return 1.0f;
if (base == 0.0f)
return (exponent > 0.0f) ? 0.0f : INFINITY;
if (base == 1.0f)
return 1.0f;
if (exponent == 1.0f)
return base;
if (floorf(exponent) == exponent) {
if (exponent >= 0.0f && exponent < 32.0f) {
int iexp = (int)exponent;
float result = 1.0f;
while (iexp > 0) {
if (iexp & 1)
result *= base;
base *= base;
iexp >>= 1;
}
return result;
} else if (exponent < 0.0f && exponent > -32.0f) {
return 1.0f / powf_opt(base, -exponent);
}
}
if (base < 0.0f)
return NAN;
return powf(base, exponent);
}
static inline double pow_opt(double base, double exponent) {
if (exponent == 0.0)
return 1.0;
if (base == 0.0)
return (exponent > 0.0) ? 0.0 : INFINITY;
if (base == 1.0)
return 1.0;
if (exponent == 1.0)
return base;
if (floor(exponent) == exponent) {
if (exponent >= 0.0 && exponent < 32.0) {
int iexp = (int)exponent;
double result = 1.0;
while (iexp > 0) {
if (iexp & 1)
result *= base;
base *= base;
iexp >>= 1;
}
return result;
} else if (exponent < 0.0 && exponent > -32.0) {
return 1.0 / pow_opt(base, -exponent);
}
}
if (base < 0.0)
return NAN;
return pow(base, exponent);
}
static inline float tanf_opt(float x) {
x = fmodf(x, 2.0f * (float)M_PI);
if (x > (float)M_PI)
x -= 2.0f * (float)M_PI;
else if (x < -(float)M_PI)
x += 2.0f * (float)M_PI;
float halfPi = (float)M_PI / 2.0f;
float eps = 1e-6f;
if (fabsf(fabsf(x) - halfPi) < eps) {
return x > 0 ? 1e6f : -1e6f;
}
return sinf(x) / cosf(x);
}
static inline double tan_opt(double x) {
x = fmod(x, 2.0 * M_PI);
if (x > M_PI)
x -= 2.0 * M_PI;
else if (x < -M_PI)
x += 2.0 * M_PI;
double halfPi = M_PI / 2.0;
double eps = 1e-14;
if (fabs(fabs(x) - halfPi) < eps) {
return x > 0 ? 1e14 : -1e14;
}
return sin(x) / cos(x);
}
static inline float exp10f_opt(float x) { return expf(x * (float)M_LN10); }
static inline double exp10_opt(double x) { return exp(x * M_LN10); }
static inline float gelu_helper_f32(float x) {
return 0.5f * x * (1.0f + tanhf(0.7978845608f * (x + 0.044715f * x * x * x)));
}
static inline double gelu_helper_f64(double x) {
return 0.5 * x * (1.0 + tanh(0.7978845608 * (x + 0.044715 * x * x * x)));
}
static inline float softplus_helper_f32(float x) { return logf(1.0f + expf(x)); }
static inline double softplus_helper_f64(double x) { return log(1.0 + exp(x)); }
static inline float silu_helper_f32(float x) { return x / (1.0f + expf(-x)); }
static inline double silu_helper_f64(double x) { return x / (1.0 + exp(-x)); }
static inline float mish_helper_f32(float x) { return x * tanhf(softplus_helper_f32(x)); }
static inline double mish_helper_f64(double x) { return x * tanh(softplus_helper_f64(x)); }
#ifdef __cplusplus
}
#endif
#endif