diff --git a/src/real.cpp b/src/real.cpp index 54faff18..1888b37c 100644 --- a/src/real.cpp +++ b/src/real.cpp @@ -770,6 +770,38 @@ real cosh(real const &x) return (exp(x) + exp(-x)) >> 1; } +real frexp(real const &x, int *exp) +{ + if (!x) + { + *exp = 0; + return x; + } + + real ret = x; + int exponent = (ret.m_signexp & 0x7fffffffu) - (1 << 30) + 1; + *exp = exponent + 1; + ret.m_signexp -= exponent + 1; + return ret; +} + +real ldexp(real const &x, int exp) +{ + real ret = x; + if (ret) + ret.m_signexp += exp; + return ret; +} + +real modf(real const &x, real *iptr) +{ + real absx = fabs(x); + real tmp = floor(absx); + + *iptr = copysign(tmp, x); + return copysign(absx - tmp, x); +} + real copysign(real const &x, real const &y) { real ret = x; @@ -1063,6 +1095,32 @@ real atan(real const &x) return ret; } +real atan2(real const &y, real const &x) +{ + if (!y) + { + if ((x.m_signexp >> 31) == 0) + return y; + if (y.m_signexp >> 31) + return -real::R_PI; + return real::R_PI; + } + + if (!x) + { + if (y.m_signexp >> 31) + return -real::R_PI; + return real::R_PI; + } + + /* FIXME: handle the Inf and NaN cases */ + real z = y / x; + real ret = atan(z); + if (x < real::R_0) + ret += (y > real::R_0) ? real::R_PI : -real::R_PI; + return ret; +} + void real::hexprint() const { printf("%08x", m_signexp); diff --git a/src/real.h b/src/real.h index 290cefc4..9340660d 100644 --- a/src/real.h +++ b/src/real.h @@ -69,7 +69,7 @@ public: friend real asin(real const &x); friend real acos(real const &x); friend real atan(real const &x); - /* FIXME: atan2 */ + friend real atan2(real const &y, real const &x); /* Hyperbolic functions */ friend real sinh(real const &x); @@ -82,7 +82,9 @@ public: friend real log(real const &x); friend real log2(real const &x); friend real log10(real const &x); - /* FIXME: frexp ldexp modf */ + friend real frexp(real const &x, int *exp); + friend real ldexp(real const &x, int exp); + friend real modf(real const &x, real *iptr); /* Power functions */ friend real re(real const &x);