123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115 |
- /* Implementation of various C99 functions
- Copyright (C) 2004-2015 Free Software Foundation, Inc.
- This file is part of the GNU Fortran 95 runtime library (libgfortran).
- Libgfortran is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
- Libgfortran is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #define C99_PROTOS_H WE_DONT_WANT_PROTOS_NOW
- #include "libgfortran.h"
- /* On a C99 system "I" (with I*I = -1) should be defined in complex.h;
- if not, we define a fallback version here. */
- #ifndef I
- # if defined(_Imaginary_I)
- # define I _Imaginary_I
- # elif defined(_Complex_I)
- # define I _Complex_I
- # else
- # define I (1.0fi)
- # endif
- #endif
- /* Macros to get real and imaginary parts of a complex, and set
- a complex value. */
- #define REALPART(z) (__real__(z))
- #define IMAGPART(z) (__imag__(z))
- #define COMPLEX_ASSIGN(z_, r_, i_) {__real__(z_) = (r_); __imag__(z_) = (i_);}
- /* Prototypes are included to silence -Wstrict-prototypes
- -Wmissing-prototypes. */
- /* Wrappers for systems without the various C99 single precision Bessel
- functions. */
- #if defined(HAVE_J0) && ! defined(HAVE_J0F)
- #define HAVE_J0F 1
- float j0f (float);
- float
- j0f (float x)
- {
- return (float) j0 ((double) x);
- }
- #endif
- #if defined(HAVE_J1) && !defined(HAVE_J1F)
- #define HAVE_J1F 1
- float j1f (float);
- float j1f (float x)
- {
- return (float) j1 ((double) x);
- }
- #endif
- #if defined(HAVE_JN) && !defined(HAVE_JNF)
- #define HAVE_JNF 1
- float jnf (int, float);
- float
- jnf (int n, float x)
- {
- return (float) jn (n, (double) x);
- }
- #endif
- #if defined(HAVE_Y0) && !defined(HAVE_Y0F)
- #define HAVE_Y0F 1
- float y0f (float);
- float
- y0f (float x)
- {
- return (float) y0 ((double) x);
- }
- #endif
- #if defined(HAVE_Y1) && !defined(HAVE_Y1F)
- #define HAVE_Y1F 1
- float y1f (float);
- float
- y1f (float x)
- {
- return (float) y1 ((double) x);
- }
- #endif
- #if defined(HAVE_YN) && !defined(HAVE_YNF)
- #define HAVE_YNF 1
- float ynf (int, float);
- float
- ynf (int n, float x)
- {
- return (float) yn (n, (double) x);
- }
- #endif
- /* Wrappers for systems without the C99 erff() and erfcf() functions. */
- #if defined(HAVE_ERF) && !defined(HAVE_ERFF)
- #define HAVE_ERFF 1
- float erff (float);
- float
- erff (float x)
- {
- return (float) erf ((double) x);
- }
- #endif
- #if defined(HAVE_ERFC) && !defined(HAVE_ERFCF)
- #define HAVE_ERFCF 1
- float erfcf (float);
- float
- erfcf (float x)
- {
- return (float) erfc ((double) x);
- }
- #endif
- #ifndef HAVE_ACOSF
- #define HAVE_ACOSF 1
- float acosf (float x);
- float
- acosf (float x)
- {
- return (float) acos (x);
- }
- #endif
- #if HAVE_ACOSH && !HAVE_ACOSHF
- float acoshf (float x);
- float
- acoshf (float x)
- {
- return (float) acosh ((double) x);
- }
- #endif
- #ifndef HAVE_ASINF
- #define HAVE_ASINF 1
- float asinf (float x);
- float
- asinf (float x)
- {
- return (float) asin (x);
- }
- #endif
- #if HAVE_ASINH && !HAVE_ASINHF
- float asinhf (float x);
- float
- asinhf (float x)
- {
- return (float) asinh ((double) x);
- }
- #endif
- #ifndef HAVE_ATAN2F
- #define HAVE_ATAN2F 1
- float atan2f (float y, float x);
- float
- atan2f (float y, float x)
- {
- return (float) atan2 (y, x);
- }
- #endif
- #ifndef HAVE_ATANF
- #define HAVE_ATANF 1
- float atanf (float x);
- float
- atanf (float x)
- {
- return (float) atan (x);
- }
- #endif
- #if HAVE_ATANH && !HAVE_ATANHF
- float atanhf (float x);
- float
- atanhf (float x)
- {
- return (float) atanh ((double) x);
- }
- #endif
- #ifndef HAVE_CEILF
- #define HAVE_CEILF 1
- float ceilf (float x);
- float
- ceilf (float x)
- {
- return (float) ceil (x);
- }
- #endif
- #ifndef HAVE_COPYSIGNF
- #define HAVE_COPYSIGNF 1
- float copysignf (float x, float y);
- float
- copysignf (float x, float y)
- {
- return (float) copysign (x, y);
- }
- #endif
- #ifndef HAVE_COSF
- #define HAVE_COSF 1
- float cosf (float x);
- float
- cosf (float x)
- {
- return (float) cos (x);
- }
- #endif
- #ifndef HAVE_COSHF
- #define HAVE_COSHF 1
- float coshf (float x);
- float
- coshf (float x)
- {
- return (float) cosh (x);
- }
- #endif
- #ifndef HAVE_EXPF
- #define HAVE_EXPF 1
- float expf (float x);
- float
- expf (float x)
- {
- return (float) exp (x);
- }
- #endif
- #ifndef HAVE_FABSF
- #define HAVE_FABSF 1
- float fabsf (float x);
- float
- fabsf (float x)
- {
- return (float) fabs (x);
- }
- #endif
- #ifndef HAVE_FLOORF
- #define HAVE_FLOORF 1
- float floorf (float x);
- float
- floorf (float x)
- {
- return (float) floor (x);
- }
- #endif
- #ifndef HAVE_FMODF
- #define HAVE_FMODF 1
- float fmodf (float x, float y);
- float
- fmodf (float x, float y)
- {
- return (float) fmod (x, y);
- }
- #endif
- #ifndef HAVE_FREXPF
- #define HAVE_FREXPF 1
- float frexpf (float x, int *exp);
- float
- frexpf (float x, int *exp)
- {
- return (float) frexp (x, exp);
- }
- #endif
- #ifndef HAVE_HYPOTF
- #define HAVE_HYPOTF 1
- float hypotf (float x, float y);
- float
- hypotf (float x, float y)
- {
- return (float) hypot (x, y);
- }
- #endif
- #ifndef HAVE_LOGF
- #define HAVE_LOGF 1
- float logf (float x);
- float
- logf (float x)
- {
- return (float) log (x);
- }
- #endif
- #ifndef HAVE_LOG10F
- #define HAVE_LOG10F 1
- float log10f (float x);
- float
- log10f (float x)
- {
- return (float) log10 (x);
- }
- #endif
- #ifndef HAVE_SCALBN
- #define HAVE_SCALBN 1
- double scalbn (double x, int y);
- double
- scalbn (double x, int y)
- {
- #if (FLT_RADIX == 2) && defined(HAVE_LDEXP)
- return ldexp (x, y);
- #else
- return x * pow (FLT_RADIX, y);
- #endif
- }
- #endif
- #ifndef HAVE_SCALBNF
- #define HAVE_SCALBNF 1
- float scalbnf (float x, int y);
- float
- scalbnf (float x, int y)
- {
- return (float) scalbn (x, y);
- }
- #endif
- #ifndef HAVE_SINF
- #define HAVE_SINF 1
- float sinf (float x);
- float
- sinf (float x)
- {
- return (float) sin (x);
- }
- #endif
- #ifndef HAVE_SINHF
- #define HAVE_SINHF 1
- float sinhf (float x);
- float
- sinhf (float x)
- {
- return (float) sinh (x);
- }
- #endif
- #ifndef HAVE_SQRTF
- #define HAVE_SQRTF 1
- float sqrtf (float x);
- float
- sqrtf (float x)
- {
- return (float) sqrt (x);
- }
- #endif
- #ifndef HAVE_TANF
- #define HAVE_TANF 1
- float tanf (float x);
- float
- tanf (float x)
- {
- return (float) tan (x);
- }
- #endif
- #ifndef HAVE_TANHF
- #define HAVE_TANHF 1
- float tanhf (float x);
- float
- tanhf (float x)
- {
- return (float) tanh (x);
- }
- #endif
- #ifndef HAVE_TRUNC
- #define HAVE_TRUNC 1
- double trunc (double x);
- double
- trunc (double x)
- {
- if (!isfinite (x))
- return x;
- if (x < 0.0)
- return - floor (-x);
- else
- return floor (x);
- }
- #endif
- #ifndef HAVE_TRUNCF
- #define HAVE_TRUNCF 1
- float truncf (float x);
- float
- truncf (float x)
- {
- return (float) trunc (x);
- }
- #endif
- #ifndef HAVE_NEXTAFTERF
- #define HAVE_NEXTAFTERF 1
- /* This is a portable implementation of nextafterf that is intended to be
- independent of the floating point format or its in memory representation.
- This implementation works correctly with denormalized values. */
- float nextafterf (float x, float y);
- float
- nextafterf (float x, float y)
- {
- /* This variable is marked volatile to avoid excess precision problems
- on some platforms, including IA-32. */
- volatile float delta;
- float absx, denorm_min;
- if (isnan (x) || isnan (y))
- return x + y;
- if (x == y)
- return x;
- if (!isfinite (x))
- return x > 0 ? __FLT_MAX__ : - __FLT_MAX__;
- /* absx = fabsf (x); */
- absx = (x < 0.0) ? -x : x;
- /* __FLT_DENORM_MIN__ is non-zero iff the target supports denormals. */
- if (__FLT_DENORM_MIN__ == 0.0f)
- denorm_min = __FLT_MIN__;
- else
- denorm_min = __FLT_DENORM_MIN__;
- if (absx < __FLT_MIN__)
- delta = denorm_min;
- else
- {
- float frac;
- int exp;
- /* Discard the fraction from x. */
- frac = frexpf (absx, &exp);
- delta = scalbnf (0.5f, exp);
- /* Scale x by the epsilon of the representation. By rights we should
- have been able to combine this with scalbnf, but some targets don't
- get that correct with denormals. */
- delta *= __FLT_EPSILON__;
- /* If we're going to be reducing the absolute value of X, and doing so
- would reduce the exponent of X, then the delta to be applied is
- one exponent smaller. */
- if (frac == 0.5f && (y < x) == (x > 0))
- delta *= 0.5f;
- /* If that underflows to zero, then we're back to the minimum. */
- if (delta == 0.0f)
- delta = denorm_min;
- }
- if (y < x)
- delta = -delta;
- return x + delta;
- }
- #endif
- #ifndef HAVE_POWF
- #define HAVE_POWF 1
- float powf (float x, float y);
- float
- powf (float x, float y)
- {
- return (float) pow (x, y);
- }
- #endif
- #ifndef HAVE_ROUND
- #define HAVE_ROUND 1
- /* Round to nearest integral value. If the argument is halfway between two
- integral values then round away from zero. */
- double round (double x);
- double
- round (double x)
- {
- double t;
- if (!isfinite (x))
- return (x);
- if (x >= 0.0)
- {
- t = floor (x);
- if (t - x <= -0.5)
- t += 1.0;
- return (t);
- }
- else
- {
- t = floor (-x);
- if (t + x <= -0.5)
- t += 1.0;
- return (-t);
- }
- }
- #endif
- /* Algorithm by Steven G. Kargl. */
- #if !defined(HAVE_ROUNDL)
- #define HAVE_ROUNDL 1
- long double roundl (long double x);
- #if defined(HAVE_CEILL)
- /* Round to nearest integral value. If the argument is halfway between two
- integral values then round away from zero. */
- long double
- roundl (long double x)
- {
- long double t;
- if (!isfinite (x))
- return (x);
- if (x >= 0.0)
- {
- t = ceill (x);
- if (t - x > 0.5)
- t -= 1.0;
- return (t);
- }
- else
- {
- t = ceill (-x);
- if (t + x > 0.5)
- t -= 1.0;
- return (-t);
- }
- }
- #else
- /* Poor version of roundl for system that don't have ceill. */
- long double
- roundl (long double x)
- {
- if (x > DBL_MAX || x < -DBL_MAX)
- {
- #ifdef HAVE_NEXTAFTERL
- long double prechalf = nextafterl (0.5L, LDBL_MAX);
- #else
- static long double prechalf = 0.5L;
- #endif
- return (GFC_INTEGER_LARGEST) (x + (x > 0 ? prechalf : -prechalf));
- }
- else
- /* Use round(). */
- return round ((double) x);
- }
- #endif
- #endif
- #ifndef HAVE_ROUNDF
- #define HAVE_ROUNDF 1
- /* Round to nearest integral value. If the argument is halfway between two
- integral values then round away from zero. */
- float roundf (float x);
- float
- roundf (float x)
- {
- float t;
- if (!isfinite (x))
- return (x);
- if (x >= 0.0)
- {
- t = floorf (x);
- if (t - x <= -0.5)
- t += 1.0;
- return (t);
- }
- else
- {
- t = floorf (-x);
- if (t + x <= -0.5)
- t += 1.0;
- return (-t);
- }
- }
- #endif
- /* lround{f,,l} and llround{f,,l} functions. */
- #if !defined(HAVE_LROUNDF) && defined(HAVE_ROUNDF)
- #define HAVE_LROUNDF 1
- long int lroundf (float x);
- long int
- lroundf (float x)
- {
- return (long int) roundf (x);
- }
- #endif
- #if !defined(HAVE_LROUND) && defined(HAVE_ROUND)
- #define HAVE_LROUND 1
- long int lround (double x);
- long int
- lround (double x)
- {
- return (long int) round (x);
- }
- #endif
- #if !defined(HAVE_LROUNDL) && defined(HAVE_ROUNDL)
- #define HAVE_LROUNDL 1
- long int lroundl (long double x);
- long int
- lroundl (long double x)
- {
- return (long long int) roundl (x);
- }
- #endif
- #if !defined(HAVE_LLROUNDF) && defined(HAVE_ROUNDF)
- #define HAVE_LLROUNDF 1
- long long int llroundf (float x);
- long long int
- llroundf (float x)
- {
- return (long long int) roundf (x);
- }
- #endif
- #if !defined(HAVE_LLROUND) && defined(HAVE_ROUND)
- #define HAVE_LLROUND 1
- long long int llround (double x);
- long long int
- llround (double x)
- {
- return (long long int) round (x);
- }
- #endif
- #if !defined(HAVE_LLROUNDL) && defined(HAVE_ROUNDL)
- #define HAVE_LLROUNDL 1
- long long int llroundl (long double x);
- long long int
- llroundl (long double x)
- {
- return (long long int) roundl (x);
- }
- #endif
- #ifndef HAVE_LOG10L
- #define HAVE_LOG10L 1
- /* log10 function for long double variables. The version provided here
- reduces the argument until it fits into a double, then use log10. */
- long double log10l (long double x);
- long double
- log10l (long double x)
- {
- #if LDBL_MAX_EXP > DBL_MAX_EXP
- if (x > DBL_MAX)
- {
- double val;
- int p2_result = 0;
- if (x > 0x1p16383L) { p2_result += 16383; x /= 0x1p16383L; }
- if (x > 0x1p8191L) { p2_result += 8191; x /= 0x1p8191L; }
- if (x > 0x1p4095L) { p2_result += 4095; x /= 0x1p4095L; }
- if (x > 0x1p2047L) { p2_result += 2047; x /= 0x1p2047L; }
- if (x > 0x1p1023L) { p2_result += 1023; x /= 0x1p1023L; }
- val = log10 ((double) x);
- return (val + p2_result * .30102999566398119521373889472449302L);
- }
- #endif
- #if LDBL_MIN_EXP < DBL_MIN_EXP
- if (x < DBL_MIN)
- {
- double val;
- int p2_result = 0;
- if (x < 0x1p-16380L) { p2_result += 16380; x /= 0x1p-16380L; }
- if (x < 0x1p-8189L) { p2_result += 8189; x /= 0x1p-8189L; }
- if (x < 0x1p-4093L) { p2_result += 4093; x /= 0x1p-4093L; }
- if (x < 0x1p-2045L) { p2_result += 2045; x /= 0x1p-2045L; }
- if (x < 0x1p-1021L) { p2_result += 1021; x /= 0x1p-1021L; }
- val = fabs (log10 ((double) x));
- return (- val - p2_result * .30102999566398119521373889472449302L);
- }
- #endif
- return log10 (x);
- }
- #endif
- #ifndef HAVE_FLOORL
- #define HAVE_FLOORL 1
- long double floorl (long double x);
- long double
- floorl (long double x)
- {
- /* Zero, possibly signed. */
- if (x == 0)
- return x;
- /* Large magnitude. */
- if (x > DBL_MAX || x < (-DBL_MAX))
- return x;
- /* Small positive values. */
- if (x >= 0 && x < DBL_MIN)
- return 0;
- /* Small negative values. */
- if (x < 0 && x > (-DBL_MIN))
- return -1;
- return floor (x);
- }
- #endif
- #ifndef HAVE_FMODL
- #define HAVE_FMODL 1
- long double fmodl (long double x, long double y);
- long double
- fmodl (long double x, long double y)
- {
- if (y == 0.0L)
- return 0.0L;
- /* Need to check that the result has the same sign as x and magnitude
- less than the magnitude of y. */
- return x - floorl (x / y) * y;
- }
- #endif
- #if !defined(HAVE_CABSF)
- #define HAVE_CABSF 1
- float cabsf (float complex z);
- float
- cabsf (float complex z)
- {
- return hypotf (REALPART (z), IMAGPART (z));
- }
- #endif
- #if !defined(HAVE_CABS)
- #define HAVE_CABS 1
- double cabs (double complex z);
- double
- cabs (double complex z)
- {
- return hypot (REALPART (z), IMAGPART (z));
- }
- #endif
- #if !defined(HAVE_CABSL) && defined(HAVE_HYPOTL)
- #define HAVE_CABSL 1
- long double cabsl (long double complex z);
- long double
- cabsl (long double complex z)
- {
- return hypotl (REALPART (z), IMAGPART (z));
- }
- #endif
- #if !defined(HAVE_CARGF)
- #define HAVE_CARGF 1
- float cargf (float complex z);
- float
- cargf (float complex z)
- {
- return atan2f (IMAGPART (z), REALPART (z));
- }
- #endif
- #if !defined(HAVE_CARG)
- #define HAVE_CARG 1
- double carg (double complex z);
- double
- carg (double complex z)
- {
- return atan2 (IMAGPART (z), REALPART (z));
- }
- #endif
- #if !defined(HAVE_CARGL) && defined(HAVE_ATAN2L)
- #define HAVE_CARGL 1
- long double cargl (long double complex z);
- long double
- cargl (long double complex z)
- {
- return atan2l (IMAGPART (z), REALPART (z));
- }
- #endif
- /* exp(z) = exp(a)*(cos(b) + i sin(b)) */
- #if !defined(HAVE_CEXPF)
- #define HAVE_CEXPF 1
- float complex cexpf (float complex z);
- float complex
- cexpf (float complex z)
- {
- float a, b;
- float complex v;
- a = REALPART (z);
- b = IMAGPART (z);
- COMPLEX_ASSIGN (v, cosf (b), sinf (b));
- return expf (a) * v;
- }
- #endif
- #if !defined(HAVE_CEXP)
- #define HAVE_CEXP 1
- double complex cexp (double complex z);
- double complex
- cexp (double complex z)
- {
- double a, b;
- double complex v;
- a = REALPART (z);
- b = IMAGPART (z);
- COMPLEX_ASSIGN (v, cos (b), sin (b));
- return exp (a) * v;
- }
- #endif
- #if !defined(HAVE_CEXPL) && defined(HAVE_COSL) && defined(HAVE_SINL) && defined(EXPL)
- #define HAVE_CEXPL 1
- long double complex cexpl (long double complex z);
- long double complex
- cexpl (long double complex z)
- {
- long double a, b;
- long double complex v;
- a = REALPART (z);
- b = IMAGPART (z);
- COMPLEX_ASSIGN (v, cosl (b), sinl (b));
- return expl (a) * v;
- }
- #endif
- /* log(z) = log (cabs(z)) + i*carg(z) */
- #if !defined(HAVE_CLOGF)
- #define HAVE_CLOGF 1
- float complex clogf (float complex z);
- float complex
- clogf (float complex z)
- {
- float complex v;
- COMPLEX_ASSIGN (v, logf (cabsf (z)), cargf (z));
- return v;
- }
- #endif
- #if !defined(HAVE_CLOG)
- #define HAVE_CLOG 1
- double complex clog (double complex z);
- double complex
- clog (double complex z)
- {
- double complex v;
- COMPLEX_ASSIGN (v, log (cabs (z)), carg (z));
- return v;
- }
- #endif
- #if !defined(HAVE_CLOGL) && defined(HAVE_LOGL) && defined(HAVE_CABSL) && defined(HAVE_CARGL)
- #define HAVE_CLOGL 1
- long double complex clogl (long double complex z);
- long double complex
- clogl (long double complex z)
- {
- long double complex v;
- COMPLEX_ASSIGN (v, logl (cabsl (z)), cargl (z));
- return v;
- }
- #endif
- /* log10(z) = log10 (cabs(z)) + i*carg(z) */
- #if !defined(HAVE_CLOG10F)
- #define HAVE_CLOG10F 1
- float complex clog10f (float complex z);
- float complex
- clog10f (float complex z)
- {
- float complex v;
- COMPLEX_ASSIGN (v, log10f (cabsf (z)), cargf (z));
- return v;
- }
- #endif
- #if !defined(HAVE_CLOG10)
- #define HAVE_CLOG10 1
- double complex clog10 (double complex z);
- double complex
- clog10 (double complex z)
- {
- double complex v;
- COMPLEX_ASSIGN (v, log10 (cabs (z)), carg (z));
- return v;
- }
- #endif
- #if !defined(HAVE_CLOG10L) && defined(HAVE_LOG10L) && defined(HAVE_CABSL) && defined(HAVE_CARGL)
- #define HAVE_CLOG10L 1
- long double complex clog10l (long double complex z);
- long double complex
- clog10l (long double complex z)
- {
- long double complex v;
- COMPLEX_ASSIGN (v, log10l (cabsl (z)), cargl (z));
- return v;
- }
- #endif
- /* pow(base, power) = cexp (power * clog (base)) */
- #if !defined(HAVE_CPOWF)
- #define HAVE_CPOWF 1
- float complex cpowf (float complex base, float complex power);
- float complex
- cpowf (float complex base, float complex power)
- {
- return cexpf (power * clogf (base));
- }
- #endif
- #if !defined(HAVE_CPOW)
- #define HAVE_CPOW 1
- double complex cpow (double complex base, double complex power);
- double complex
- cpow (double complex base, double complex power)
- {
- return cexp (power * clog (base));
- }
- #endif
- #if !defined(HAVE_CPOWL) && defined(HAVE_CEXPL) && defined(HAVE_CLOGL)
- #define HAVE_CPOWL 1
- long double complex cpowl (long double complex base, long double complex power);
- long double complex
- cpowl (long double complex base, long double complex power)
- {
- return cexpl (power * clogl (base));
- }
- #endif
- /* sqrt(z). Algorithm pulled from glibc. */
- #if !defined(HAVE_CSQRTF)
- #define HAVE_CSQRTF 1
- float complex csqrtf (float complex z);
- float complex
- csqrtf (float complex z)
- {
- float re, im;
- float complex v;
- re = REALPART (z);
- im = IMAGPART (z);
- if (im == 0)
- {
- if (re < 0)
- {
- COMPLEX_ASSIGN (v, 0, copysignf (sqrtf (-re), im));
- }
- else
- {
- COMPLEX_ASSIGN (v, fabsf (sqrtf (re)), copysignf (0, im));
- }
- }
- else if (re == 0)
- {
- float r;
- r = sqrtf (0.5 * fabsf (im));
- COMPLEX_ASSIGN (v, r, copysignf (r, im));
- }
- else
- {
- float d, r, s;
- d = hypotf (re, im);
- /* Use the identity 2 Re res Im res = Im x
- to avoid cancellation error in d +/- Re x. */
- if (re > 0)
- {
- r = sqrtf (0.5 * d + 0.5 * re);
- s = (0.5 * im) / r;
- }
- else
- {
- s = sqrtf (0.5 * d - 0.5 * re);
- r = fabsf ((0.5 * im) / s);
- }
- COMPLEX_ASSIGN (v, r, copysignf (s, im));
- }
- return v;
- }
- #endif
- #if !defined(HAVE_CSQRT)
- #define HAVE_CSQRT 1
- double complex csqrt (double complex z);
- double complex
- csqrt (double complex z)
- {
- double re, im;
- double complex v;
- re = REALPART (z);
- im = IMAGPART (z);
- if (im == 0)
- {
- if (re < 0)
- {
- COMPLEX_ASSIGN (v, 0, copysign (sqrt (-re), im));
- }
- else
- {
- COMPLEX_ASSIGN (v, fabs (sqrt (re)), copysign (0, im));
- }
- }
- else if (re == 0)
- {
- double r;
- r = sqrt (0.5 * fabs (im));
- COMPLEX_ASSIGN (v, r, copysign (r, im));
- }
- else
- {
- double d, r, s;
- d = hypot (re, im);
- /* Use the identity 2 Re res Im res = Im x
- to avoid cancellation error in d +/- Re x. */
- if (re > 0)
- {
- r = sqrt (0.5 * d + 0.5 * re);
- s = (0.5 * im) / r;
- }
- else
- {
- s = sqrt (0.5 * d - 0.5 * re);
- r = fabs ((0.5 * im) / s);
- }
- COMPLEX_ASSIGN (v, r, copysign (s, im));
- }
- return v;
- }
- #endif
- #if !defined(HAVE_CSQRTL) && defined(HAVE_COPYSIGNL) && defined(HAVE_SQRTL) && defined(HAVE_FABSL) && defined(HAVE_HYPOTL)
- #define HAVE_CSQRTL 1
- long double complex csqrtl (long double complex z);
- long double complex
- csqrtl (long double complex z)
- {
- long double re, im;
- long double complex v;
- re = REALPART (z);
- im = IMAGPART (z);
- if (im == 0)
- {
- if (re < 0)
- {
- COMPLEX_ASSIGN (v, 0, copysignl (sqrtl (-re), im));
- }
- else
- {
- COMPLEX_ASSIGN (v, fabsl (sqrtl (re)), copysignl (0, im));
- }
- }
- else if (re == 0)
- {
- long double r;
- r = sqrtl (0.5 * fabsl (im));
- COMPLEX_ASSIGN (v, copysignl (r, im), r);
- }
- else
- {
- long double d, r, s;
- d = hypotl (re, im);
- /* Use the identity 2 Re res Im res = Im x
- to avoid cancellation error in d +/- Re x. */
- if (re > 0)
- {
- r = sqrtl (0.5 * d + 0.5 * re);
- s = (0.5 * im) / r;
- }
- else
- {
- s = sqrtl (0.5 * d - 0.5 * re);
- r = fabsl ((0.5 * im) / s);
- }
- COMPLEX_ASSIGN (v, r, copysignl (s, im));
- }
- return v;
- }
- #endif
- /* sinh(a + i b) = sinh(a) cos(b) + i cosh(a) sin(b) */
- #if !defined(HAVE_CSINHF)
- #define HAVE_CSINHF 1
- float complex csinhf (float complex a);
- float complex
- csinhf (float complex a)
- {
- float r, i;
- float complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, sinhf (r) * cosf (i), coshf (r) * sinf (i));
- return v;
- }
- #endif
- #if !defined(HAVE_CSINH)
- #define HAVE_CSINH 1
- double complex csinh (double complex a);
- double complex
- csinh (double complex a)
- {
- double r, i;
- double complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, sinh (r) * cos (i), cosh (r) * sin (i));
- return v;
- }
- #endif
- #if !defined(HAVE_CSINHL) && defined(HAVE_COSL) && defined(HAVE_COSHL) && defined(HAVE_SINL) && defined(HAVE_SINHL)
- #define HAVE_CSINHL 1
- long double complex csinhl (long double complex a);
- long double complex
- csinhl (long double complex a)
- {
- long double r, i;
- long double complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, sinhl (r) * cosl (i), coshl (r) * sinl (i));
- return v;
- }
- #endif
- /* cosh(a + i b) = cosh(a) cos(b) + i sinh(a) sin(b) */
- #if !defined(HAVE_CCOSHF)
- #define HAVE_CCOSHF 1
- float complex ccoshf (float complex a);
- float complex
- ccoshf (float complex a)
- {
- float r, i;
- float complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, coshf (r) * cosf (i), sinhf (r) * sinf (i));
- return v;
- }
- #endif
- #if !defined(HAVE_CCOSH)
- #define HAVE_CCOSH 1
- double complex ccosh (double complex a);
- double complex
- ccosh (double complex a)
- {
- double r, i;
- double complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, cosh (r) * cos (i), sinh (r) * sin (i));
- return v;
- }
- #endif
- #if !defined(HAVE_CCOSHL) && defined(HAVE_COSL) && defined(HAVE_COSHL) && defined(HAVE_SINL) && defined(HAVE_SINHL)
- #define HAVE_CCOSHL 1
- long double complex ccoshl (long double complex a);
- long double complex
- ccoshl (long double complex a)
- {
- long double r, i;
- long double complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, coshl (r) * cosl (i), sinhl (r) * sinl (i));
- return v;
- }
- #endif
- /* tanh(a + i b) = (tanh(a) + i tan(b)) / (1 + i tanh(a) tan(b)) */
- #if !defined(HAVE_CTANHF)
- #define HAVE_CTANHF 1
- float complex ctanhf (float complex a);
- float complex
- ctanhf (float complex a)
- {
- float rt, it;
- float complex n, d;
- rt = tanhf (REALPART (a));
- it = tanf (IMAGPART (a));
- COMPLEX_ASSIGN (n, rt, it);
- COMPLEX_ASSIGN (d, 1, rt * it);
- return n / d;
- }
- #endif
- #if !defined(HAVE_CTANH)
- #define HAVE_CTANH 1
- double complex ctanh (double complex a);
- double complex
- ctanh (double complex a)
- {
- double rt, it;
- double complex n, d;
- rt = tanh (REALPART (a));
- it = tan (IMAGPART (a));
- COMPLEX_ASSIGN (n, rt, it);
- COMPLEX_ASSIGN (d, 1, rt * it);
- return n / d;
- }
- #endif
- #if !defined(HAVE_CTANHL) && defined(HAVE_TANL) && defined(HAVE_TANHL)
- #define HAVE_CTANHL 1
- long double complex ctanhl (long double complex a);
- long double complex
- ctanhl (long double complex a)
- {
- long double rt, it;
- long double complex n, d;
- rt = tanhl (REALPART (a));
- it = tanl (IMAGPART (a));
- COMPLEX_ASSIGN (n, rt, it);
- COMPLEX_ASSIGN (d, 1, rt * it);
- return n / d;
- }
- #endif
- /* sin(a + i b) = sin(a) cosh(b) + i cos(a) sinh(b) */
- #if !defined(HAVE_CSINF)
- #define HAVE_CSINF 1
- float complex csinf (float complex a);
- float complex
- csinf (float complex a)
- {
- float r, i;
- float complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, sinf (r) * coshf (i), cosf (r) * sinhf (i));
- return v;
- }
- #endif
- #if !defined(HAVE_CSIN)
- #define HAVE_CSIN 1
- double complex csin (double complex a);
- double complex
- csin (double complex a)
- {
- double r, i;
- double complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, sin (r) * cosh (i), cos (r) * sinh (i));
- return v;
- }
- #endif
- #if !defined(HAVE_CSINL) && defined(HAVE_COSL) && defined(HAVE_COSHL) && defined(HAVE_SINL) && defined(HAVE_SINHL)
- #define HAVE_CSINL 1
- long double complex csinl (long double complex a);
- long double complex
- csinl (long double complex a)
- {
- long double r, i;
- long double complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, sinl (r) * coshl (i), cosl (r) * sinhl (i));
- return v;
- }
- #endif
- /* cos(a + i b) = cos(a) cosh(b) - i sin(a) sinh(b) */
- #if !defined(HAVE_CCOSF)
- #define HAVE_CCOSF 1
- float complex ccosf (float complex a);
- float complex
- ccosf (float complex a)
- {
- float r, i;
- float complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, cosf (r) * coshf (i), - (sinf (r) * sinhf (i)));
- return v;
- }
- #endif
- #if !defined(HAVE_CCOS)
- #define HAVE_CCOS 1
- double complex ccos (double complex a);
- double complex
- ccos (double complex a)
- {
- double r, i;
- double complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, cos (r) * cosh (i), - (sin (r) * sinh (i)));
- return v;
- }
- #endif
- #if !defined(HAVE_CCOSL) && defined(HAVE_COSL) && defined(HAVE_COSHL) && defined(HAVE_SINL) && defined(HAVE_SINHL)
- #define HAVE_CCOSL 1
- long double complex ccosl (long double complex a);
- long double complex
- ccosl (long double complex a)
- {
- long double r, i;
- long double complex v;
- r = REALPART (a);
- i = IMAGPART (a);
- COMPLEX_ASSIGN (v, cosl (r) * coshl (i), - (sinl (r) * sinhl (i)));
- return v;
- }
- #endif
- /* tan(a + i b) = (tan(a) + i tanh(b)) / (1 - i tan(a) tanh(b)) */
- #if !defined(HAVE_CTANF)
- #define HAVE_CTANF 1
- float complex ctanf (float complex a);
- float complex
- ctanf (float complex a)
- {
- float rt, it;
- float complex n, d;
- rt = tanf (REALPART (a));
- it = tanhf (IMAGPART (a));
- COMPLEX_ASSIGN (n, rt, it);
- COMPLEX_ASSIGN (d, 1, - (rt * it));
- return n / d;
- }
- #endif
- #if !defined(HAVE_CTAN)
- #define HAVE_CTAN 1
- double complex ctan (double complex a);
- double complex
- ctan (double complex a)
- {
- double rt, it;
- double complex n, d;
- rt = tan (REALPART (a));
- it = tanh (IMAGPART (a));
- COMPLEX_ASSIGN (n, rt, it);
- COMPLEX_ASSIGN (d, 1, - (rt * it));
- return n / d;
- }
- #endif
- #if !defined(HAVE_CTANL) && defined(HAVE_TANL) && defined(HAVE_TANHL)
- #define HAVE_CTANL 1
- long double complex ctanl (long double complex a);
- long double complex
- ctanl (long double complex a)
- {
- long double rt, it;
- long double complex n, d;
- rt = tanl (REALPART (a));
- it = tanhl (IMAGPART (a));
- COMPLEX_ASSIGN (n, rt, it);
- COMPLEX_ASSIGN (d, 1, - (rt * it));
- return n / d;
- }
- #endif
- /* Complex ASIN. Returns wrongly NaN for infinite arguments.
- Algorithm taken from Abramowitz & Stegun. */
- #if !defined(HAVE_CASINF) && defined(HAVE_CLOGF) && defined(HAVE_CSQRTF)
- #define HAVE_CASINF 1
- complex float casinf (complex float z);
- complex float
- casinf (complex float z)
- {
- return -I*clogf (I*z + csqrtf (1.0f-z*z));
- }
- #endif
- #if !defined(HAVE_CASIN) && defined(HAVE_CLOG) && defined(HAVE_CSQRT)
- #define HAVE_CASIN 1
- complex double casin (complex double z);
- complex double
- casin (complex double z)
- {
- return -I*clog (I*z + csqrt (1.0-z*z));
- }
- #endif
- #if !defined(HAVE_CASINL) && defined(HAVE_CLOGL) && defined(HAVE_CSQRTL)
- #define HAVE_CASINL 1
- complex long double casinl (complex long double z);
- complex long double
- casinl (complex long double z)
- {
- return -I*clogl (I*z + csqrtl (1.0L-z*z));
- }
- #endif
- /* Complex ACOS. Returns wrongly NaN for infinite arguments.
- Algorithm taken from Abramowitz & Stegun. */
- #if !defined(HAVE_CACOSF) && defined(HAVE_CLOGF) && defined(HAVE_CSQRTF)
- #define HAVE_CACOSF 1
- complex float cacosf (complex float z);
- complex float
- cacosf (complex float z)
- {
- return -I*clogf (z + I*csqrtf (1.0f-z*z));
- }
- #endif
- #if !defined(HAVE_CACOS) && defined(HAVE_CLOG) && defined(HAVE_CSQRT)
- #define HAVE_CACOS 1
- complex double cacos (complex double z);
- complex double
- cacos (complex double z)
- {
- return -I*clog (z + I*csqrt (1.0-z*z));
- }
- #endif
- #if !defined(HAVE_CACOSL) && defined(HAVE_CLOGL) && defined(HAVE_CSQRTL)
- #define HAVE_CACOSL 1
- complex long double cacosl (complex long double z);
- complex long double
- cacosl (complex long double z)
- {
- return -I*clogl (z + I*csqrtl (1.0L-z*z));
- }
- #endif
- /* Complex ATAN. Returns wrongly NaN for infinite arguments.
- Algorithm taken from Abramowitz & Stegun. */
- #if !defined(HAVE_CATANF) && defined(HAVE_CLOGF)
- #define HAVE_CACOSF 1
- complex float catanf (complex float z);
- complex float
- catanf (complex float z)
- {
- return I*clogf ((I+z)/(I-z))/2.0f;
- }
- #endif
- #if !defined(HAVE_CATAN) && defined(HAVE_CLOG)
- #define HAVE_CACOS 1
- complex double catan (complex double z);
- complex double
- catan (complex double z)
- {
- return I*clog ((I+z)/(I-z))/2.0;
- }
- #endif
- #if !defined(HAVE_CATANL) && defined(HAVE_CLOGL)
- #define HAVE_CACOSL 1
- complex long double catanl (complex long double z);
- complex long double
- catanl (complex long double z)
- {
- return I*clogl ((I+z)/(I-z))/2.0L;
- }
- #endif
- /* Complex ASINH. Returns wrongly NaN for infinite arguments.
- Algorithm taken from Abramowitz & Stegun. */
- #if !defined(HAVE_CASINHF) && defined(HAVE_CLOGF) && defined(HAVE_CSQRTF)
- #define HAVE_CASINHF 1
- complex float casinhf (complex float z);
- complex float
- casinhf (complex float z)
- {
- return clogf (z + csqrtf (z*z+1.0f));
- }
- #endif
- #if !defined(HAVE_CASINH) && defined(HAVE_CLOG) && defined(HAVE_CSQRT)
- #define HAVE_CASINH 1
- complex double casinh (complex double z);
- complex double
- casinh (complex double z)
- {
- return clog (z + csqrt (z*z+1.0));
- }
- #endif
- #if !defined(HAVE_CASINHL) && defined(HAVE_CLOGL) && defined(HAVE_CSQRTL)
- #define HAVE_CASINHL 1
- complex long double casinhl (complex long double z);
- complex long double
- casinhl (complex long double z)
- {
- return clogl (z + csqrtl (z*z+1.0L));
- }
- #endif
- /* Complex ACOSH. Returns wrongly NaN for infinite arguments.
- Algorithm taken from Abramowitz & Stegun. */
- #if !defined(HAVE_CACOSHF) && defined(HAVE_CLOGF) && defined(HAVE_CSQRTF)
- #define HAVE_CACOSHF 1
- complex float cacoshf (complex float z);
- complex float
- cacoshf (complex float z)
- {
- return clogf (z + csqrtf (z-1.0f) * csqrtf (z+1.0f));
- }
- #endif
- #if !defined(HAVE_CACOSH) && defined(HAVE_CLOG) && defined(HAVE_CSQRT)
- #define HAVE_CACOSH 1
- complex double cacosh (complex double z);
- complex double
- cacosh (complex double z)
- {
- return clog (z + csqrt (z-1.0) * csqrt (z+1.0));
- }
- #endif
- #if !defined(HAVE_CACOSHL) && defined(HAVE_CLOGL) && defined(HAVE_CSQRTL)
- #define HAVE_CACOSHL 1
- complex long double cacoshl (complex long double z);
- complex long double
- cacoshl (complex long double z)
- {
- return clogl (z + csqrtl (z-1.0L) * csqrtl (z+1.0L));
- }
- #endif
- /* Complex ATANH. Returns wrongly NaN for infinite arguments.
- Algorithm taken from Abramowitz & Stegun. */
- #if !defined(HAVE_CATANHF) && defined(HAVE_CLOGF)
- #define HAVE_CATANHF 1
- complex float catanhf (complex float z);
- complex float
- catanhf (complex float z)
- {
- return clogf ((1.0f+z)/(1.0f-z))/2.0f;
- }
- #endif
- #if !defined(HAVE_CATANH) && defined(HAVE_CLOG)
- #define HAVE_CATANH 1
- complex double catanh (complex double z);
- complex double
- catanh (complex double z)
- {
- return clog ((1.0+z)/(1.0-z))/2.0;
- }
- #endif
- #if !defined(HAVE_CATANHL) && defined(HAVE_CLOGL)
- #define HAVE_CATANHL 1
- complex long double catanhl (complex long double z);
- complex long double
- catanhl (complex long double z)
- {
- return clogl ((1.0L+z)/(1.0L-z))/2.0L;
- }
- #endif
- #if !defined(HAVE_TGAMMA)
- #define HAVE_TGAMMA 1
- double tgamma (double);
- /* Fallback tgamma() function. Uses the algorithm from
- http://www.netlib.org/specfun/gamma and references therein. */
- #undef SQRTPI
- #define SQRTPI 0.9189385332046727417803297
- #undef PI
- #define PI 3.1415926535897932384626434
- double
- tgamma (double x)
- {
- int i, n, parity;
- double fact, res, sum, xden, xnum, y, y1, ysq, z;
- static double p[8] = {
- -1.71618513886549492533811e0, 2.47656508055759199108314e1,
- -3.79804256470945635097577e2, 6.29331155312818442661052e2,
- 8.66966202790413211295064e2, -3.14512729688483675254357e4,
- -3.61444134186911729807069e4, 6.64561438202405440627855e4 };
- static double q[8] = {
- -3.08402300119738975254353e1, 3.15350626979604161529144e2,
- -1.01515636749021914166146e3, -3.10777167157231109440444e3,
- 2.25381184209801510330112e4, 4.75584627752788110767815e3,
- -1.34659959864969306392456e5, -1.15132259675553483497211e5 };
- static double c[7] = { -1.910444077728e-03,
- 8.4171387781295e-04, -5.952379913043012e-04,
- 7.93650793500350248e-04, -2.777777777777681622553e-03,
- 8.333333333333333331554247e-02, 5.7083835261e-03 };
- static const double xminin = 2.23e-308;
- static const double xbig = 171.624;
- static const double xnan = __builtin_nan ("0x0"), xinf = __builtin_inf ();
- static double eps = 0;
-
- if (eps == 0)
- eps = nextafter (1., 2.) - 1.;
- parity = 0;
- fact = 1;
- n = 0;
- y = x;
- if (isnan (x))
- return x;
- if (y <= 0)
- {
- y = -x;
- y1 = trunc (y);
- res = y - y1;
- if (res != 0)
- {
- if (y1 != trunc (y1*0.5l)*2)
- parity = 1;
- fact = -PI / sin (PI*res);
- y = y + 1;
- }
- else
- return x == 0 ? copysign (xinf, x) : xnan;
- }
- if (y < eps)
- {
- if (y >= xminin)
- res = 1 / y;
- else
- return xinf;
- }
- else if (y < 13)
- {
- y1 = y;
- if (y < 1)
- {
- z = y;
- y = y + 1;
- }
- else
- {
- n = (int)y - 1;
- y = y - n;
- z = y - 1;
- }
- xnum = 0;
- xden = 1;
- for (i = 0; i < 8; i++)
- {
- xnum = (xnum + p[i]) * z;
- xden = xden * z + q[i];
- }
- res = xnum / xden + 1;
- if (y1 < y)
- res = res / y1;
- else if (y1 > y)
- for (i = 1; i <= n; i++)
- {
- res = res * y;
- y = y + 1;
- }
- }
- else
- {
- if (y < xbig)
- {
- ysq = y * y;
- sum = c[6];
- for (i = 0; i < 6; i++)
- sum = sum / ysq + c[i];
- sum = sum/y - y + SQRTPI;
- sum = sum + (y - 0.5) * log (y);
- res = exp (sum);
- }
- else
- return x < 0 ? xnan : xinf;
- }
- if (parity)
- res = -res;
- if (fact != 1)
- res = fact / res;
- return res;
- }
- #endif
- #if !defined(HAVE_LGAMMA)
- #define HAVE_LGAMMA 1
- double lgamma (double);
- /* Fallback lgamma() function. Uses the algorithm from
- http://www.netlib.org/specfun/algama and references therein,
- except for negative arguments (where netlib would return +Inf)
- where we use the following identity:
- lgamma(y) = log(pi/(|y*sin(pi*y)|)) - lgamma(-y)
- */
- double
- lgamma (double y)
- {
- #undef SQRTPI
- #define SQRTPI 0.9189385332046727417803297
- #undef PI
- #define PI 3.1415926535897932384626434
- #define PNT68 0.6796875
- #define D1 -0.5772156649015328605195174
- #define D2 0.4227843350984671393993777
- #define D4 1.791759469228055000094023
- static double p1[8] = {
- 4.945235359296727046734888e0, 2.018112620856775083915565e2,
- 2.290838373831346393026739e3, 1.131967205903380828685045e4,
- 2.855724635671635335736389e4, 3.848496228443793359990269e4,
- 2.637748787624195437963534e4, 7.225813979700288197698961e3 };
- static double q1[8] = {
- 6.748212550303777196073036e1, 1.113332393857199323513008e3,
- 7.738757056935398733233834e3, 2.763987074403340708898585e4,
- 5.499310206226157329794414e4, 6.161122180066002127833352e4,
- 3.635127591501940507276287e4, 8.785536302431013170870835e3 };
- static double p2[8] = {
- 4.974607845568932035012064e0, 5.424138599891070494101986e2,
- 1.550693864978364947665077e4, 1.847932904445632425417223e5,
- 1.088204769468828767498470e6, 3.338152967987029735917223e6,
- 5.106661678927352456275255e6, 3.074109054850539556250927e6 };
- static double q2[8] = {
- 1.830328399370592604055942e2, 7.765049321445005871323047e3,
- 1.331903827966074194402448e5, 1.136705821321969608938755e6,
- 5.267964117437946917577538e6, 1.346701454311101692290052e7,
- 1.782736530353274213975932e7, 9.533095591844353613395747e6 };
- static double p4[8] = {
- 1.474502166059939948905062e4, 2.426813369486704502836312e6,
- 1.214755574045093227939592e8, 2.663432449630976949898078e9,
- 2.940378956634553899906876e10, 1.702665737765398868392998e11,
- 4.926125793377430887588120e11, 5.606251856223951465078242e11 };
- static double q4[8] = {
- 2.690530175870899333379843e3, 6.393885654300092398984238e5,
- 4.135599930241388052042842e7, 1.120872109616147941376570e9,
- 1.488613728678813811542398e10, 1.016803586272438228077304e11,
- 3.417476345507377132798597e11, 4.463158187419713286462081e11 };
- static double c[7] = {
- -1.910444077728e-03, 8.4171387781295e-04,
- -5.952379913043012e-04, 7.93650793500350248e-04,
- -2.777777777777681622553e-03, 8.333333333333333331554247e-02,
- 5.7083835261e-03 };
- static double xbig = 2.55e305, xinf = __builtin_inf (), eps = 0,
- frtbig = 2.25e76;
- int i;
- double corr, res, xden, xm1, xm2, xm4, xnum, ysq;
- if (eps == 0)
- eps = __builtin_nextafter (1., 2.) - 1.;
- if ((y > 0) && (y <= xbig))
- {
- if (y <= eps)
- res = -log (y);
- else if (y <= 1.5)
- {
- if (y < PNT68)
- {
- corr = -log (y);
- xm1 = y;
- }
- else
- {
- corr = 0;
- xm1 = (y - 0.5) - 0.5;
- }
- if ((y <= 0.5) || (y >= PNT68))
- {
- xden = 1;
- xnum = 0;
- for (i = 0; i < 8; i++)
- {
- xnum = xnum*xm1 + p1[i];
- xden = xden*xm1 + q1[i];
- }
- res = corr + (xm1 * (D1 + xm1*(xnum/xden)));
- }
- else
- {
- xm2 = (y - 0.5) - 0.5;
- xden = 1;
- xnum = 0;
- for (i = 0; i < 8; i++)
- {
- xnum = xnum*xm2 + p2[i];
- xden = xden*xm2 + q2[i];
- }
- res = corr + xm2 * (D2 + xm2*(xnum/xden));
- }
- }
- else if (y <= 4)
- {
- xm2 = y - 2;
- xden = 1;
- xnum = 0;
- for (i = 0; i < 8; i++)
- {
- xnum = xnum*xm2 + p2[i];
- xden = xden*xm2 + q2[i];
- }
- res = xm2 * (D2 + xm2*(xnum/xden));
- }
- else if (y <= 12)
- {
- xm4 = y - 4;
- xden = -1;
- xnum = 0;
- for (i = 0; i < 8; i++)
- {
- xnum = xnum*xm4 + p4[i];
- xden = xden*xm4 + q4[i];
- }
- res = D4 + xm4*(xnum/xden);
- }
- else
- {
- res = 0;
- if (y <= frtbig)
- {
- res = c[6];
- ysq = y * y;
- for (i = 0; i < 6; i++)
- res = res / ysq + c[i];
- }
- res = res/y;
- corr = log (y);
- res = res + SQRTPI - 0.5*corr;
- res = res + y*(corr-1);
- }
- }
- else if (y < 0 && __builtin_floor (y) != y)
- {
- /* lgamma(y) = log(pi/(|y*sin(pi*y)|)) - lgamma(-y)
- For abs(y) very close to zero, we use a series expansion to
- the first order in y to avoid overflow. */
- if (y > -1.e-100)
- res = -2 * log (fabs (y)) - lgamma (-y);
- else
- res = log (PI / fabs (y * sin (PI * y))) - lgamma (-y);
- }
- else
- res = xinf;
- return res;
- }
- #endif
- #if defined(HAVE_TGAMMA) && !defined(HAVE_TGAMMAF)
- #define HAVE_TGAMMAF 1
- float tgammaf (float);
- float
- tgammaf (float x)
- {
- return (float) tgamma ((double) x);
- }
- #endif
- #if defined(HAVE_LGAMMA) && !defined(HAVE_LGAMMAF)
- #define HAVE_LGAMMAF 1
- float lgammaf (float);
- float
- lgammaf (float x)
- {
- return (float) lgamma ((double) x);
- }
- #endif
|