libc

/* $Id$ */
/* Copyright (c) 2008-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libc */
/* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* XXX in part from dietlibc */
#include "sys/types.h"
#include "stdlib.h"
#include "string.h"
#include "errno.h"
#include "math.h"
#include "arch.h"
/* constants */
#define B0 + 1.0l/ 6/ 1/ 2
#define B1 - 1.0l/ 30/ 3/ 4
#define B2 + 1.0l/ 42/ 5/ 6
#define B3 - 1.0l/ 30/ 7/ 8
#define B4 + 5.0l/ 66/ 9/10
#define B5 - 691.0l/2730/11/12
#define B6 + 7.0l/ 6/13/14
#define B7 - 3617.0l/ 510/15/16
#define B8 + 43867.0l/ 798/17/18
#define B9 - 174611.0l/ 330/19/20
#define B10 + 854513.0l/ 138/21/22
#define B11 - 236364091.0l/2730/23/24
#define B12 + 8553103.0l/ 6/25/26
#define M_C 0.5772156649015328
/* variables */
static const double _coeff[] = { B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10 };
static int _signgam;
/* macros */
#define EXPL(x) ((((short *)(void *)&x)[4] & 0x7FFF) >> 0)
#define EXPD(x) ((((short *)(void *)&x)[3] & 0x7FF0) >> 4)
#define EXPF(x) ((((short *)(void *)&x)[1] & 0x7F80) >> 7)
#define SQUARE(x) (long) (My - (x) * (x) )
/* prototypes */
/* private */
static double _logfact(long double x);
static double _poly(double x, size_t n, const double * c);
static long double _P(int My, double * x);
static long double _Q(int My, double * x);
static long double _jn(int n, double * x);
static long double _yn(int n, double * x);
/* functions */
/* private */
static double _logfact(long double x)
{
static unsigned char list [] = { 6, 4, 3, 3, 2, 2 };
long double z = 2. * M_PI * x;
register int e = EXPL (x);
return (log(x) - 1) * x + 0.5 * log(z) + _poly(1. / (x * x),
e < 0x4003 ? 10 : (e > 0x4008 ? 1 : list[e - 0x4003]),
_coeff) / x;
}
static double _poly(double x, size_t n, const double * c)
{
long double ret;
size_t i;
i = n;
c += n;
ret = 0;
do
ret = ret * x + *c--;
while(i--);
return ret;
}
static long double _P(int My, double * x)
{
long double Sum = 0.;
long double Fact = 1.;
long double z182 = -0.015625 / (x[0] * x[0]);
register int i;
for ( i = 1; ; i += 2 ) {
Fact *= SQUARE(i+i-1) * SQUARE(i+i+1) * z182 / (i*(i+1));
if ( EXPL (Fact) < 0x3FFF-53 )
break;
Sum += Fact;
}
return 1. + Sum;
}
static long double _Q(int My, double * x)
{
long double Fact = (My-1) / x[0] * 0.125;
long double Sum = Fact;
long double z182 = -0.015625 / (x[0]*x[0]);
register int i;
for ( i = 2; ; i += 2 ) {
Fact *= SQUARE(i+i-1) * SQUARE(i+i+1) * z182 / (i*(i+1));
if ( EXPL (Fact) < 0x3FFF-53 )
break;
Sum += Fact;
}
return Sum;
}
static long double _jn(int n, double * x)
{
long double Sum;
long double Fact;
long double y;
register int i;
double xx;
long double Xi;
int My;
if ( n < 0 )
return n & 1 ? _jn(-n, x) : -_jn(-n, x);
if ((x[0] >= 17.7+0.0144*(n*n))) {
Xi = x[0] - M_PI * (n*0.5 + 0.25);
My = n*n << 2;
return sqrt(M_2_PI / x[0]) * (_P(My, x) * cos(Xi) - _Q(My,x) * sin(Xi));
}
xx = x[0] * 0.5;
Sum = 0.;
Fact = 1.;
y = -xx * xx;
for ( i = 1; i <= n; i++ )
Fact *= xx/i;
for ( i = 1; ; i++ ) {
Sum += Fact;
Fact *= y / (i*(n+i));
if ( EXPL (Sum) - EXPL(Fact) > 53 || !EXPL(Fact) )
break;
}
return Sum;
}
static long double _yn ( int n, double* x )
{
long double Sum1;
long double Sum2;
long double Fact1;
long double Fact2;
long double F1;
long double F2;
long double y;
register int i;
double xx;
long double Xi;
unsigned int My;
if ( EXPD (x[0]) == 0 )
return -1./0.; /* ignore the gcc warning, this is intentional */
if ( (x[0] >= (n>=32 ? 25.8 : (n<8 ? 17.4+0.1*n : 16.2+0.3*n))) ) {
Xi = x[0] - M_PI * (n*0.5+0.25);
My = n*n << 2;
return sqrt(M_2_PI / x[0]) * (_P(My,x) * sin(Xi) + _Q(My,x) * cos(Xi));
}
Sum1 = Sum2 = F1 = F2 = 0;
Fact1 = 1. / (xx = x[0] * 0.5 );
Fact2 = 1.;
y = xx*xx;
for ( i = 1; i < n; i++ )
Fact1 *= (n-i) / xx;
for ( i = 1; i <= n; i++ ) {
Sum1 += Fact1;
if ( i == n )
break;
Fact1 *= y/(i*(n-i));
}
for (i=1; i<=n; i++) {
Fact2 *= xx / i;
F1 += 1. / i;
}
for ( i = 1; ; i++ ) {
Sum2 += Fact2 * (F1+F2);
Fact2 *= -y / (i*(n+i));
if ( EXPL (Sum2) - EXPL (Fact2) > 53 || !EXPL (Fact2) )
break;
F1 += 1. / (n+i);
F2 += 1. / i;
}
return M_1_PI * (2. * (M_C + log(xx)) * _jn (n, x) - Sum1 - Sum2);
}
/* public */
/* acos */
#ifndef ARCH_acos
double acos(double x)
{
return acosl(x);
}
#endif
/* acosf */
#ifndef ARCH_acosf
float acosf(float x)
{
return acos(x);
}
#endif
/* acosh */
#ifndef ARCH_acosh
double acosh(double x)
{
return acoshl(x);
}
#endif
/* acoshf */
#ifndef ARCH_acoshf
float acoshf(float x)
{
return acosh(x);
}
#endif
/* acoshl */
#ifndef ARCH_acoshl
# warning Unsupported platform: acoshl() is not implemented
long double acoshl(long double x)
{
if(x < 1.0)
{
errno = EDOM;
return nanl(NULL);
}
/* FIXME implement */
return 0.0;
}
#endif
/* acosl */
#ifndef ARCH_acosl
# warning Unsupported platform: acosl() is not implemented
long double acosl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* asin */
#ifndef ARCH_asin
double asin(double x)
{
return asinl(x);
}
#endif
/* asinf */
#ifndef ARCH_asinf
float asinf(float x)
{
return asin(x);
}
#endif
/* asinh */
#ifndef ARCH_asinh
double asinh(double x)
{
return asinhl(x);
}
#endif
/* asinhf */
#ifndef ARCH_asinhf
float asinhf(float x)
{
return asinh(x);
}
#endif
/* asinhl */
#ifndef ARCH_asinhl
# warning Unsupported platform: asinhl() is not implemented
long double asinhl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* asinl */
#ifndef ARCH_asinl
# warning Unsupported platform: asinl() is not implemented
long double asinl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* atan */
#ifndef ARCH_atan
double atan(double x)
{
return atanl(x);
}
#endif
/* atan2 */
#ifndef ARCH_atan2
double atan2(double x, double y)
{
return atan2l(x, y);
}
#endif
/* atan2f */
#ifndef ARCH_atan2f
float atan2f(float x, float y)
{
return atan2(x, y);
}
#endif
/* atan2l */
#ifndef ARCH_atan2l
long double atan2l(long double x, long double y)
{
/* FIXME implement */
return 0.0;
}
#endif
/* atanf */
#ifndef ARCH_atanf
float atanf(float x)
{
return atan(x);
}
#endif
/* atanh */
#ifndef ARCH_atanh
double atanh(double x)
{
return atanhl(x);
}
#endif
/* atanhf */
#ifndef ARCH_atanhf
float atanhf(float x)
{
return atanh(x);
}
#endif
/* atanhl */
#ifndef ARCH_atanhl
# warning Unsupported platform: atanhl() is not implemented
long double atanhl(long double x)
{
if(abs(x) >= 1.0)
{
errno = EDOM;
return nanl(NULL);
}
/* FIXME implement */
return 0.0;
}
#endif
/* atanl */
#ifndef ARCH_atanl
# warning Unsupported platform: atanl() is not implemented
long double atanl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* cbrt */
#ifndef ARCH_cbrt
double cbrt(double x)
{
return cbrtl(x);
}
#endif
/* cbrtf */
#ifndef ARCH_cbrtf
float cbrtf(float x)
{
return cbrt(x);
}
#endif
/* cbrtl */
#ifndef ARCH_cbrtl
# warning Unsupported platform: cbrtl() is not implemented
long double cbrtl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* ceil */
#ifndef ARCH_ceil
double ceil(double x)
{
return ceill(x);
}
#endif
/* ceilf */
#ifndef ARCH_ceilf
float ceilf(float x)
{
return ceil(x);
}
#endif
/* ceill */
#ifndef ARCH_ceill
long double ceill(long double x)
{
long double y;
y = roundl(x);
return (y >= x) ? y : y + 1.0;
}
#endif
#if 0
double copysign(double, double);
float copysignf(float, float);
long double copysignl(long double, long double);
#endif
/* cos */
#ifndef ARCH_cos
double cos(double x)
{
return cosl(x);
}
#endif
/* cosf */
#ifndef ARCH_cosf
float cosf(float x)
{
return cos(x);
}
#endif
/* cosh */
#ifndef ARCH_cosh
double cosh(double x)
{
return (exp(x) + exp(-x)) / 2;
}
#endif
/* coshf */
#ifndef ARCH_coshf
float coshf(float x)
{
return (expf(x) + expf(-x)) / 2;
}
#endif
/* coshl */
#ifndef ARCH_coshl
long double coshl(long double x)
{
return (expl(x) + expl(-x)) / 2;
}
#endif
/* cosl */
#ifndef ARCH_cosl
# warning Unsupported platform: cosl() is not implemented
long double cosl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
#if 0
double erf(double);
double erfc(double);
float erfcf(float);
long double erfcl(long double);
float erff(float);
long double erfl(long double);
#endif
/* exp */
#ifndef ARCH_exp
double exp(double x)
{
return expl(x);
}
#endif
/* exp2 */
#ifndef ARCH_exp2
double exp2(double x)
{
return exp2l(x);
}
#endif
/* exp2f */
#ifndef ARCH_exp2f
float exp2f(float x)
{
return exp2(x);
}
#endif
/* exp2l */
#ifndef ARCH_exp2l
# warning Unsupported platform: exp2l() is not implemented
long double exp2l(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* expf */
#ifndef ARCH_expf
float expf(float x)
{
return exp(x);
}
#endif
/* expl */
#ifndef ARCH_expl
# warning Unsupported platform: expl() is not implemented
long double expl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* expm1 */
#ifndef ARCH_expm1
double expm1(double x)
{
return expm1l(x);
}
#endif
/* expm1f */
#ifndef ARCH_expm1f
float expm1f(float x)
{
return expm1(x);
}
#endif
/* expm1l */
#ifndef ARCH_expm1l
# warning Unsupported platform: expm1l() is not implemented
long double expm1l(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* fabs */
#ifndef ARCH_fabs
double fabs(double x)
{
return (x >= 0.0) ? x : -x;
}
#endif
/* fabsf */
#ifndef ARCH_fabsf
float fabsf(float x)
{
return (x >= 0.0) ? x : -x;
}
#endif
/* fabsl */
#ifndef ARCH_fabsl
long double fabsl(long double x)
{
return (x >= 0.0) ? x : -x;
}
#endif
/* fdim */
#ifndef ARCH_fdim
double fdim(double x, double y)
{
return fdiml(x, y);
}
#endif
/* fdimf */
#ifndef ARCH_fdimf
float fdimf(float x, float y)
{
return fdim(x, y);
}
#endif
/* fdiml */
#ifndef ARCH_fdiml
# warning Unsupported platform: fdiml() is not implemented
long double fdiml(long double x, long double y)
{
(void) x;
(void) y;
/* FIXME implement */
return 0.0;
}
#endif
/* floor */
#ifndef ARCH_floor
double floor(double x)
{
return floorl(x);
}
#endif
/* floorf */
#ifndef ARCH_floorf
float floorf(float x)
{
return floor(x);
}
#endif
#ifndef ARCH_floorl
long double floorl(long double x)
{
long double y;
y = roundl(x);
return (y <= x) ? y : y - 1.0;
}
#endif
#if 0
double fma(double, double, double);
float fmaf(float, float, float);
long double fmal(long double, long double, long double);
#endif
/* fmax */
#ifndef ARCH_fmax
double fmax(double x, double y)
{
if(isnan(x))
return y;
if(isnan(y))
return x;
return (x >= y) ? x : y;
}
#endif
/* fmaxf */
#ifndef ARCH_fmaxf
float fmaxf(float x, float y)
{
if(isnan(x))
return y;
if(isnan(y))
return x;
return (x >= y) ? x : y;
}
#endif
/* fmaxl */
#ifndef ARCH_fmaxl
long double fmaxl(long double x, long double y)
{
if(isnan(x))
return y;
if(isnan(y))
return x;
return (x >= y) ? x : y;
}
#endif
/* fmin */
#ifndef ARCH_fmin
double fmin(double x, double y)
{
if(isnan(x))
return y;
if(isnan(y))
return x;
return (x <= y) ? x : y;
}
#endif
/* fminf */
#ifndef ARCH_fminf
float fminf(float x, float y)
{
if(isnan(x))
return y;
if(isnan(y))
return x;
return (x <= y) ? x : y;
}
#endif
/* fminl */
#ifndef ARCH_fminl
long double fminl(long double x, long double y)
{
if(isnan(x))
return y;
if(isnan(y))
return x;
return (x <= y) ? x : y;
}
#endif
/* fmod */
#ifndef ARCH_fmod
double fmod(double x, double y)
{
return fmodl(x, y);
}
#endif
/* fmod */
#ifndef ARCH_fmodf
float fmodf(float x, float y)
{
return fmod(x, y);
}
#endif
/* fmodl */
#ifndef ARCH_fmodl
long double fmodl(long double x, long double y)
{
long double z;
z = floor(x / y);
return x - (y * z);
}
#endif
/* frexp */
#ifndef ARCH_frexp
double frexp(double x, int * y)
{
return frexpl(x, y);
}
#endif
/* frexpf */
#ifndef ARCH_frexpf
float frexpf(float x, int * y)
{
return frexp(x, y);
}
#endif
/* frexpl */
#ifndef ARCH_frexpl
# warning Unsupported platform: frexpl() is not implemented
long double frexpl(long double x, int * y)
{
(void) x;
(void) y;
/* FIXME implement */
return 0.0;
}
#endif
/* hypot */
#ifndef ARCH_hypot
double hypot(double x, double y)
{
return hypotl(x, y);
}
#endif
/* hypotf */
#ifndef ARCH_hypotf
float hypotf(float x, float y)
{
return hypot(x, y);
}
#endif
/* hypotl */
#ifndef ARCH_hypotl
long double hypotl(long double x, long double y)
{
/* XXX may overflow */
return sqrt((x * x) + (y * y));
}
#endif
#if 0
int ilogb(double);
int ilogbf(float);
int ilogbl(long double);
#endif
/* isinf */
int __isinf(double x)
{
return x == strtold("INF", NULL);
}
/* isnan */
int __isnan(double x)
{
return x == nanl(NULL);
}
/* j0 */
double j0(double x)
{
return _jn(0, &x);
}
/* j1 */
double j1(double x)
{
return _jn(1, &x);
}
/* jn */
double jn(int n, double x)
{
return _jn(n, &x);
}
/* ldexp */
#ifndef ARCH_ldexp
double ldexp(double x, int y)
{
return ldexpl(x, y);
}
#endif
/* ldexpf */
#ifndef ARCH_ldexpf
float ldexpf(float x, int y)
{
return ldexp(x, y);
}
#endif
/* ldexpl */
#ifndef ARCH_ldexpl
# warning Unsupported platform: ldexpl() is not implemented
long double ldexpl(long double x, int y)
{
(void) x;
(void) y;
/* FIXME implement */
return 0.0;
}
#endif
/* lgamma */
#ifndef ARCH_lgamma
double lgamma(double x)
{
register int k = floor (x);
long double w;
long double y;
long double z;
_signgam = 0;
if ( k >= 7 )
return _logfact (x-1);
if ( k == x )
switch (k) {
case 1 :
case 2 : return 0.000000000000000000000000000l;
case 3 : return 0.693147180559945309432805516l;
case 4 : return 1.791759469228055000858148560l;
case 5 : return 3.178053830347945619723759592l;
case 6 : return 4.787491742782045994244981560l;
default: return 1./0.; /* ignore the gcc warning, this is intentional */
}
z = _logfact (y = x - k + 7.0 - 1);
w = 1;
for ( k = 7 - k; k--; )
w *= y, y -= 1.;
_signgam = k >= 0 ? 0 : k & 1;
return z - log (w);
}
#endif
/* lgammaf */
#ifndef ARCH_lgammaf
float lgammaf(float x)
{
return lgamma(x);
}
#endif
/* lgammal */
#ifndef ARCH_lgammal
# warning Unsupported platform: lgammal() is not implemented
long double lgammal(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
#if 0
long long llrint(double);
long long llrintf(float);
long long llrintl(long double);
long long llround(double);
long long llroundf(float);
long long llroundl(long double);
#endif
/* log */
#ifndef ARCH_log
double log(double x)
{
return logl(x);
}
#endif
/* log10 */
#ifndef ARCH_log10
double log10(double x)
{
return log10l(x);
}
#endif
/* log1p */
#ifndef ARCH_log1p
double log1p(double x)
{
return log1pl(x);
}
#endif
/* log1pf */
#ifndef ARCH_log1pf
float log1pf(float x)
{
return log1p(x);
}
#endif
/* log1pl */
#ifndef ARCH_log1pl
# warning Unsupported platform: log1pl() is not implemented
long double log1pl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* log2 */
#ifndef ARCH_log2
double log2(double x)
{
return log2l(x);
}
#endif
/* log2f */
#ifndef ARCH_log2f
float log2f(float x)
{
return log2(x);
}
#endif
/* log2l */
#ifndef ARCH_log2l
# warning Unsupported platform: log2l() is not implemented
long double log2l(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* logb */
#ifndef ARCH_logb
double logb(double x)
{
return logbl(x);
}
#endif
/* logbf */
#ifndef ARCH_logbf
float logbf(float x)
{
return logb(x);
}
#endif
/* logbl */
#ifndef ARCH_logbl
# warning Unsupported platform: logbl() is not implemented
long double logbl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* log10f */
#ifndef ARCH_log10f
float log10f(float x)
{
return log10(x);
}
#endif
/* log10l */
#ifndef ARCH_log10l
# warning Unsupported platform: log10l() is not implemented
long double log10l(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* logf */
#ifndef ARCH_logf
float logf(float x)
{
return log(x);
}
#endif
/* logl */
#ifndef ARCH_logl
# warning Unsupported platform: logl() is not implemented
long double logl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
#if 0
long lrint(double);
long lrintf(float);
long lrintl(long double);
long lround(double);
long lroundf(float);
long lroundl(long double);
#endif
/* modf */
#ifndef ARCH_modf
double modf(double x, double * iptr)
{
double ret = fmod(x, 1.0);
*iptr = x - ret;
return ret;
}
#endif
/* modff */
#ifndef ARCH_modff
float modff(float x, float * iptr)
{
float ret = fmodf(x, 1.0);
*iptr = x - ret;
return ret;
}
#endif
/* modfl */
#ifndef ARCH_modfl
long double modfl(long double x, long double * iptr)
{
long double ret = fmodl(x, 1.0);
*iptr = x - ret;
return ret;
}
#endif
/* nan */
double nan(const char * tagp)
{
if(tagp == NULL || strlen(tagp) == 0)
return strtod("NAN", NULL);
/* FIXME implement */
return 0.0;
}
/* nanf */
float nanf(const char * tagp)
{
if(tagp == NULL || strlen(tagp) == 0)
return strtof("NAN", NULL);
/* FIXME implement */
return 0.0;
}
/* nanl */
long double nanl(const char * tagp)
{
if(tagp == NULL || strlen(tagp) == 0)
return strtold("NAN", NULL);
/* FIXME implement */
return 0.0;
}
#if 0
double nearbyint(double);
float nearbyintf(float);
long double nearbyintl(long double);
double nextafter(double, double);
float nextafterf(float, float);
long double nextafterl(long double, long double);
double nexttoward(double, long double);
float nexttowardf(float, long double);
long double nexttowardl(long double, long double);
#endif
/* pow */
#ifndef ARCH_pow
double pow(double x, double y)
{
return powl(x, y);
}
#endif
/* powf */
#ifndef ARCH_powf
float powf(float x, float y)
{
return pow(x, y);
}
#endif
/* powl */
#ifndef ARCH_powl
long double powl(long double x, long double y)
{
long double ret;
if(x == 1.0 || y == 0.0)
return 1.0;
if(isnan(x))
return x;
else if(isnan(y))
return y;
if(x < 0.0 || roundl(y) != y)
{
/* XXX really report the error */
errno = EDOM;
return 0.0;
}
if(x == 0.0 && y > 0.0)
return 0.0;
/* XXX there are more corner cases with infinity */
for(ret = 1.0; y >= 1.0; y -= 1.0)
/* FIXME detect overflows and underflows */
ret = ret * x;
return ret;
}
#endif
/* remainder */
#ifndef ARCH_remainder
double remainder(double x, double y)
{
return remainderl(x, y);
}
#endif
/* remainderf */
#ifndef ARCH_remainderf
float remainderf(float x, float y)
{
return remainder(x, y);
}
#endif
/* remainderl */
#ifndef ARCH_remainderl
long double remainderl(long double x, long double y)
{
return x - floor(x / y);
}
#endif
#if 0
double remquo(double, double, int *);
float remquof(float, float, int *);
long double remquol(long double, long double, int *);
#endif
/* rint */
#ifndef ARCH_rint
double rint(double x)
{
return floor(x + 0.5);
}
#endif
/* rintf */
#ifndef ARCH_rintf
float rintf(float x)
{
return floorf(x + 0.5);
}
#endif
/* rintl */
#ifndef ARCH_rintl
long double rintl(long double x)
{
return floorl(x + 0.5);
}
#endif
/* round */
#ifndef ARCH_round
double round(double x)
{
return roundl(x);
}
#endif
/* roundf */
#ifndef ARCH_roundf
float roundf(float x)
{
return round(x);
}
#endif
/* roundl */
#ifndef ARCH_roundl
# warning Unsupported platform: roundl() is not implemented
long double roundl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
#if 0
double scalb(double, double);
double scalbln(double, long);
float scalblnf(float, long);
long double scalblnl(long double, long);
double scalbn(double, int);
float scalbnf(float, int);
long double scalbnl(long double, int);
#endif
/* sin */
#ifndef ARCH_sin
double sin(double x)
{
return sinl(x);
}
#endif
/* sinf */
#ifndef ARCH_sinf
float sinf(float x)
{
return sin(x);
}
#endif
/* sinh */
#ifndef ARCH_sinh
double sinh(double x)
{
return (exp(x) - exp(-x)) / 2;
}
#endif
/* sinhf */
#ifndef ARCH_sinhf
float sinhf(float x)
{
return (expf(x) - expf(-x)) / 2;
}
#endif
/* sinhl */
#ifndef ARCH_sinhl
long double sinhl(long double x)
{
return (expl(x) - expl(-x)) / 2;
}
#endif
/* sinl */
#ifndef ARCH_sinl
# warning Unsupported platform: sinl() is not implemented
long double sinl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* sqrt */
#ifndef ARCH_sqrt
double sqrt(double x)
{
return sqrtl(x);
}
#endif
/* sqrtf */
#ifndef ARCH_sqrtf
float sqrtf(float x)
{
return sqrt(x);
}
#endif
/* sqrtl */
#ifndef ARCH_sqrtl
# warning Unsupported platform: sqrtl() is not implemented
long double sqrtl(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* tan */
#ifndef ARCH_tan
double tan(double x)
{
return sin(x) / cos(x);
}
#endif
/* tanf */
#ifndef ARCH_tanf
float tanf(float x)
{
return sinf(x) / cosf(x);
}
#endif
/* tanh */
#ifndef ARCH_tanh
double tanh(double x)
{
return sinh(x) / cosh(x);
}
#endif
/* tanhf */
#ifndef ARCH_tanhf
float tanhf(float x)
{
return sinhf(x) / coshf(x);
}
#endif
/* tanhl */
#ifndef ARCH_tanhl
long double tanhl(long double x)
{
return sinhl(x) / coshl(x);
}
#endif
/* tanl */
#ifndef ARCH_tanl
long double tanl(long double x)
{
return sinl(x) / cosl(x);
}
#endif
/* tgamma */
#ifndef ARCH_tgamma
double tgamma(double x)
{
return tgammal(x);
}
#endif
/* tgammaf */
#ifndef ARCH_tgammaf
float tgammaf(float x)
{
return tgamma(x);
}
#endif
/* tgammal */
#ifndef ARCH_tgammal
# warning Unsupported platform: tgammal() is not implemented
long double tgammal(long double x)
{
(void) x;
/* FIXME implement */
return 0.0;
}
#endif
/* trunc */
#ifndef ARCH_trunc
double trunc(double x)
{
return rint(x);
}
#endif
/* truncf */
#ifndef ARCH_truncf
float truncf(float x)
{
return rintf(x);
}
#endif
/* truncl */
#ifndef ARCH_truncl
long double truncl(long double x)
{
return rintl(x);
}
#endif
/* y0 */
double y0(double x)
{
return _yn(0, &x);
}
/* y1 */
double y1(double x)
{
return _yn(1, &x);
}
/* yn */
double yn(int n, double x)
{
return _yn(n, &x);
}