Newer
Older
rtlibc / inc / math.h
/* Copyright (C) Thornwave Labs Inc - All Rights Reserved
 * Unauthorized copying of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 * Written by Razvan Turiac <razvan.turiac@thornwave.com>
 */

#ifndef _RTLIBC_MATH_H
#define _RTLIBC_MATH_H


#include <stdint.h>


#define FLT_MAX		3.4028234664e+38
#define FLT_MIN		1.1754943508e-38
#define DBL_MAX 	1.7976931348623158e+308
#define DBL_MIN 	2.2250738585072014e-308


#define M_E				2.718281828459045235360287471352662498L //e
#define M_LOG2E			1.442695040888963407359924681001892137L //log_2 e
#define M_LOG10E		0.434294481903251827651128918916605082L //log_10 e
#define M_LN2			0.693147180559945309417232121458176568L //log_e 2
#define M_LN10			2.302585092994045684017991454684364208L //log_e 10
#define M_PI			3.141592653589793238462643383279502884L //pi
#define M_PI_2			1.570796326794896619231321691639751442L //pi/2
#define M_PI_4			0.785398163397448309615660845819875721L //pi/4
#define M_1_PI			0.318309886183790671537767526745028724L //1/pi
#define M_2_PI			0.636619772367581343075535053490057448L //2/pi
#define M_2_SQRTPI		1.128379167095512573896158903121545172L //2/sqrt(pi)
#define M_SQRT2			1.414213562373095048801688724209698079L //sqrt(2)
#define M_SQRT1_2		0.707106781186547524400844362104849039L //1/sqrt(2)


#define INFINITY	(__builtin_inff())
#define NAN			nan("")



#ifdef __cplusplus
extern "C"
{
#endif


static inline int32_t isinf(float x)
{
	if (x > FLT_MAX)
		return 1;
	else if (x < FLT_MIN)
		return -1;
	else
		return 0;
}


static inline bool isnan(float x)
{
	return x != x;
}


static inline float nan(const char* arg)
{
	return __builtin_nanf(arg);
}


static inline float round(float x)
{
#ifdef ARM_MATH_CM7
	float rv;
	__asm volatile ("vrinta.f32 %0, %1" : "=w" (rv) : "w" (x));
	return rv;
#else
	return (int32_t)(x + 0.5L);
#endif
}



static inline float floor(float x)
{
#ifdef ARM_MATH_CM7
	float rv;
	__asm volatile ("vrintm.f32 %0, %1" : "=w" (rv) : "w" (x));
	return rv;
#else
	return (x >= 0) ? (int32_t)x : (int32_t)x - 1;
#endif
}


static inline float trunc(float x)
{
#ifdef ARM_MATH_CM7
	float rv;
	__asm volatile ("vrintz.f32 %0, %1" : "=w" (rv) : "w" (x));
	return rv;
#else
	return (int32_t)x;
#endif
}


static inline float ceil(float x)
{
#ifdef ARM_MATH_CM7
	float rv;
	__asm volatile ("vrintp.f32 %0, %1" : "=w" (rv) : "w" (x));
	return rv;
#else
	return (x >= 0) ? 	
	(((x - (int32_t)x) > 0) ? (int32_t)(x + 1) : (int32_t)x) : 
	(((x - (int32_t)x) < 0) ? (int32_t)(x - 1) : (int32_t)x);
#endif
}


static inline float sqrt(float x)
{
#if defined ARM_MATH_CM7 || defined ARM_MATH_CM4
	if (x >= 0)
	{
		float rv;
		__asm volatile ("vsqrt.f32 %0, %1" : "=w" (rv) : "w" (x));
		return rv;
	}
	else
	{
		return 0;
	}
#else

	return 0;			//TODO not implemented
#endif
}


static inline float sqrtf(float x)
{
	return sqrt(x);
}


static inline float fmod(float x, float y)
{
	return x - floor(x / y) * y;
}


static inline float frac(float x)
{
	return x - trunc(x);
}



static inline float fabs(float x)
{
#if defined(ARM_MATH_CM7) || defined(ARM_MATH_CM4)
	float rv;
	__asm volatile ("vabs.f32 %0, %1" : "=w" (rv) : "w" (x));
	return rv;
#else
	return (x >= 0) ? x : -x;
#endif
}


static inline float fmax(float a, float b)
{
#ifdef ARM_MATH_CM7
	float v;
	__asm volatile ("vmaxnm.f32 %0, %1, %2" : "=w" (v) : "w" (a), "w" (b));         //max instruction
	return v;
#else
	return (a > b) ? a : b;
#endif
}


static inline float fmin(float a, float b)
{
#ifdef ARM_MATH_CM7
	float v;
	__asm volatile ("vminnm.f32 %0, %1, %2" : "=w" (v) : "w" (a), "w" (b));         //min instruction
	return v;
#else
	return (a < b) ? a : b;
#endif
}


static inline float fsat(float x, float min, float max)
{
	return fmin(fmax(min, x), max);
}


static inline int32_t smin(int32_t a, int32_t b)
{
	return (a < b) ? a : b;
}

static inline int32_t smax(int32_t a, int32_t b)
{
	return (a > b) ? a : b;
}

static inline int32_t ssat(int32_t x, int32_t min, int32_t max)
{
	if (x < min)
		return min;
	else if (x > max)
		return max;
	else
		return x;
}



static inline uint32_t umin(uint32_t a, uint32_t b)
{
	return (a < b) ? a : b;
}

static inline uint32_t umax(uint32_t a, uint32_t b)
{
	return (a > b) ? a : b;
}

static inline uint32_t usat(uint32_t x, uint32_t min, uint32_t max)
{
	if (x < min)
		return min;
	else if (x > max)
		return max;
	else
		return x;
}


static inline int32_t round_closest_signed(int32_t n, int32_t d)
{
	return (((n < 0) ^ (d < 0)) ? ((n - d / 2) / d) : ((n + d / 2) / d)) * d;
}


static inline uint32_t round_closest_unsigned(uint32_t n, uint32_t d)
{
	return ((n + d / 2) / d) * d;
}


float sin(float x);
float cos(float x);
float tan(float x);
float cotan(float x);


float expf(float x);
double exp(double x);

float log(float x);
float powf(float b, float x);


uint64_t gcd(uint64_t a, uint64_t b);

static inline uint64_t lcm(uint32_t a, uint64_t b)
{
	return (a * b) / gcd(a, b);
}


#ifdef __cplusplus
}
#endif


#endif