113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch//
313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// ====================================================
413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch//
613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Developed at SunSoft, a Sun Microsystems, Inc. business.
713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Permission to use, copy, modify, and distribute this
813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// software is freely granted, provided that this notice
913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// is preserved.
1013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// ====================================================
1113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch//
1213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// The original source code covered by the above license above has been
1313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// modified significantly by Google Inc.
1413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
1513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/ieee754.h"
1713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <cmath>
1913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <limits>
2013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/build_config.h"
2213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/macros.h"
2313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace v8 {
2513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace base {
2613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace ieee754 {
2713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace {
2913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
3013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Disable "potential divide by 0" warning in Visual Studio compiler. */
3113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
3213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_CC_MSVC
3313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
3413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#pragma warning(disable : 4723)
3513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
3613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
3713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
3813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/*
3913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The original fdlibm code used statements like:
4013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  n0 = ((*(int*)&one)>>29)^1;   * index of high word *
4113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ix0 = *(n0+(int*)&x);     * high word of x *
4213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ix1 = *((1-n0)+(int*)&x);   * low word of x *
4313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * to dig two 32 bit words out of the 64 bit IEEE floating point
4413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * value.  That is non-ANSI, and, moreover, the gcc instruction
4513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * scheduler gets it wrong.  We instead use the following macros.
4613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Unlike the original code, we determine the endianness at compile
4713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * time, not at run time; I don't see much benefit to selecting
4813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * endianness at run time.
4913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
5013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
5113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/*
5213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * A union which permits us to convert between a double and two 32 bit
5313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * ints.
5413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
5513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
5613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_TARGET_LITTLE_ENDIAN
5713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
5813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef union {
5913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double value;
6013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct {
6113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint32_t lsw;
6213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint32_t msw;
6313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } parts;
6413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct {
6513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint64_t w;
6613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } xparts;
6713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} ieee_double_shape_type;
6813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
6913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#else
7013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
7113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef union {
7213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double value;
7313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct {
7413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint32_t msw;
7513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint32_t lsw;
7613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } parts;
7713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct {
7813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint64_t w;
7913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } xparts;
8013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} ieee_double_shape_type;
8113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
8213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
8313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
8413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Get two 32 bit ints from a double.  */
8513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
8613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define EXTRACT_WORDS(ix0, ix1, d) \
8713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  do {                             \
8813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ieee_double_shape_type ew_u;   \
8913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ew_u.value = (d);              \
9013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (ix0) = ew_u.parts.msw;        \
9113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (ix1) = ew_u.parts.lsw;        \
9213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } while (0)
9313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
9413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Get a 64-bit int from a double. */
9513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define EXTRACT_WORD64(ix, d)    \
9613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  do {                           \
9713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ieee_double_shape_type ew_u; \
9813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ew_u.value = (d);            \
9913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (ix) = ew_u.xparts.w;        \
10013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } while (0)
10113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
10213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Get the more significant 32 bit int from a double.  */
10313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
10413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define GET_HIGH_WORD(i, d)      \
10513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  do {                           \
10613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ieee_double_shape_type gh_u; \
10713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    gh_u.value = (d);            \
10813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (i) = gh_u.parts.msw;        \
10913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } while (0)
11013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
11113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Get the less significant 32 bit int from a double.  */
11213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
11313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define GET_LOW_WORD(i, d)       \
11413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  do {                           \
11513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ieee_double_shape_type gl_u; \
11613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    gl_u.value = (d);            \
11713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (i) = gl_u.parts.lsw;        \
11813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } while (0)
11913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
12013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Set a double from two 32 bit ints.  */
12113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
12213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define INSERT_WORDS(d, ix0, ix1) \
12313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  do {                            \
12413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ieee_double_shape_type iw_u;  \
12513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    iw_u.parts.msw = (ix0);       \
12613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    iw_u.parts.lsw = (ix1);       \
12713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (d) = iw_u.value;             \
12813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } while (0)
12913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
13013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Set a double from a 64-bit int. */
13113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define INSERT_WORD64(d, ix)     \
13213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  do {                           \
13313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ieee_double_shape_type iw_u; \
13413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    iw_u.xparts.w = (ix);        \
13513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (d) = iw_u.value;            \
13613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } while (0)
13713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
13813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Set the more significant 32 bits of a double from an int.  */
13913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
14013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define SET_HIGH_WORD(d, v)      \
14113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  do {                           \
14213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ieee_double_shape_type sh_u; \
14313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sh_u.value = (d);            \
14413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sh_u.parts.msw = (v);        \
14513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (d) = sh_u.value;            \
14613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } while (0)
14713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
14813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Set the less significant 32 bits of a double from an int.  */
14913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
15013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define SET_LOW_WORD(d, v)       \
15113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  do {                           \
15213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ieee_double_shape_type sl_u; \
15313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sl_u.value = (d);            \
15413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sl_u.parts.lsw = (v);        \
15513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (d) = sl_u.value;            \
15613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } while (0)
15713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
15813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* Support macro. */
15913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
16013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
16113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
16213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochint32_t __ieee754_rem_pio2(double x, double *y) WARN_UNUSED_RESULT;
16313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble __kernel_cos(double x, double y) WARN_UNUSED_RESULT;
16413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochint __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec,
16513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                      const int32_t *ipio2) WARN_UNUSED_RESULT;
16613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble __kernel_sin(double x, double y, int iy) WARN_UNUSED_RESULT;
16713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
16813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* __ieee754_rem_pio2(x,y)
16913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
17013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * return the remainder of x rem pi/2 in y[0]+y[1]
17113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * use __kernel_rem_pio2()
17213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
17313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochint32_t __ieee754_rem_pio2(double x, double *y) {
17413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /*
17513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
17613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
17713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const int32_t two_over_pi[] = {
17813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C,
17913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649,
18013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44,
18113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B,
18213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D,
18313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
18413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330,
18513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08,
18613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA,
18713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x73A8C9, 0x60E27B, 0xC08C6B,
18813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
18913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
19013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const int32_t npio2_hw[] = {
19113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
19213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
19313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
19413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
19513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
19613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      0x404858EB, 0x404921FB,
19713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
19813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
19913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /*
20013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * invpio2:  53 bits of 2/pi
20113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * pio2_1:   first  33 bit of pi/2
20213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * pio2_1t:  pi/2 - pio2_1
20313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * pio2_2:   second 33 bit of pi/2
20413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * pio2_2t:  pi/2 - (pio2_1+pio2_2)
20513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * pio2_3:   third  33 bit of pi/2
20613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
20713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
20813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
20913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
21013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      zero = 0.00000000000000000000e+00,    /* 0x00000000, 0x00000000 */
21113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      half = 5.00000000000000000000e-01,    /* 0x3FE00000, 0x00000000 */
21213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      two24 = 1.67772160000000000000e+07,   /* 0x41700000, 0x00000000 */
21313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
21413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pio2_1 = 1.57079632673412561417e+00,  /* 0x3FF921FB, 0x54400000 */
21513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
21613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pio2_2 = 6.07710050630396597660e-11,  /* 0x3DD0B461, 0x1A600000 */
21713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
21813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pio2_3 = 2.02226624871116645580e-21,  /* 0x3BA3198A, 0x2E000000 */
21913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
22013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
22113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double z, w, t, r, fn;
22213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double tx[3];
22313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t e0, i, j, nx, n, ix, hx;
22413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t low;
22513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
22613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = 0;
22713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(hx, x); /* high word of x */
22813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix = hx & 0x7fffffff;
22913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix <= 0x3fe921fb) { /* |x| ~<= pi/4 , no need for reduction */
23013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    y[0] = x;
23113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    y[1] = 0;
23213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return 0;
23313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
23413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix < 0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */
23513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx > 0) {
23613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      z = x - pio2_1;
23713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */
23813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[0] = z - pio2_1t;
23913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[1] = (z - y[0]) - pio2_1t;
24013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else { /* near pi/2, use 33+33+53 bit pi */
24113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        z -= pio2_2;
24213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[0] = z - pio2_2t;
24313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[1] = (z - y[0]) - pio2_2t;
24413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
24513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return 1;
24613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else { /* negative x */
24713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      z = x + pio2_1;
24813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */
24913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[0] = z + pio2_1t;
25013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[1] = (z - y[0]) + pio2_1t;
25113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else { /* near pi/2, use 33+33+53 bit pi */
25213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        z += pio2_2;
25313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[0] = z + pio2_2t;
25413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[1] = (z - y[0]) + pio2_2t;
25513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
25613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return -1;
25713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
25813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
25913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix <= 0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
26013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    t = fabs(x);
26113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    n = static_cast<int32_t>(t * invpio2 + half);
26213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    fn = static_cast<double>(n);
26313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    r = t - fn * pio2_1;
26413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    w = fn * pio2_1t; /* 1st round good to 85 bit */
26513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (n < 32 && ix != npio2_hw[n - 1]) {
26613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y[0] = r - w; /* quick check no cancellation */
26713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
26813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      uint32_t high;
26913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      j = ix >> 20;
27013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y[0] = r - w;
27113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      GET_HIGH_WORD(high, y[0]);
27213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      i = j - ((high >> 20) & 0x7ff);
27313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (i > 16) { /* 2nd iteration needed, good to 118 */
27413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        t = r;
27513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        w = fn * pio2_2;
27613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        r = t - w;
27713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        w = fn * pio2_2t - ((t - r) - w);
27813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[0] = r - w;
27913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        GET_HIGH_WORD(high, y[0]);
28013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        i = j - ((high >> 20) & 0x7ff);
28113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        if (i > 49) { /* 3rd iteration need, 151 bits acc */
28213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          t = r;      /* will cover all possible cases */
28313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          w = fn * pio2_3;
28413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          r = t - w;
28513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          w = fn * pio2_3t - ((t - r) - w);
28613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          y[0] = r - w;
28713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        }
28813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
28913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
29013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    y[1] = (r - y[0]) - w;
29113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx < 0) {
29213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y[0] = -y[0];
29313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y[1] = -y[1];
29413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return -n;
29513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
29613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return n;
29713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
29813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
29913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /*
30013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * all other (large) arguments
30113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
30213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix >= 0x7ff00000) { /* x is inf or NaN */
30313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    y[0] = y[1] = x - x;
30413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return 0;
30513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
30613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* set z = scalbn(|x|,ilogb(x)-23) */
30713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_LOW_WORD(low, x);
30813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SET_LOW_WORD(z, low);
30913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  e0 = (ix >> 20) - 1046; /* e0 = ilogb(z)-23; */
31013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SET_HIGH_WORD(z, ix - static_cast<int32_t>(e0 << 20));
31113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (i = 0; i < 2; i++) {
31213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    tx[i] = static_cast<double>(static_cast<int32_t>(z));
31313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = (z - tx[i]) * two24;
31413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
31513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  tx[2] = z;
31613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  nx = 3;
31713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  while (tx[nx - 1] == zero) nx--; /* skip zero term */
31813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  n = __kernel_rem_pio2(tx, y, e0, nx, 2, two_over_pi);
31913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx < 0) {
32013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    y[0] = -y[0];
32113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    y[1] = -y[1];
32213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return -n;
32313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
32413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return n;
32513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
32613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
32713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* __kernel_cos( x,  y )
32813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
32913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input x is assumed to be bounded by ~pi/4 in magnitude.
33013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input y is the tail of x.
33113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
33213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Algorithm
33313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      1. Since cos(-x) = cos(x), we need only to consider positive x.
33413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
33513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      3. cos(x) is approximated by a polynomial of degree 14 on
33613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         [0,pi/4]
33713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                                       4            14
33813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
33913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         where the remez error is
34013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
34113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |              2     4     6     8     10    12     14 |     -58
34213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  )| <= 2
34313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |                                                      |
34413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
34513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                     4     6     8     10    12     14
34613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      4. let r = C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  , then
34713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *             cos(x) = 1 - x*x/2 + r
34813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         since cos(x+y) ~ cos(x) - sin(x)*y
34913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                        ~ cos(x) - x*y,
35013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         a correction term is necessary in cos(x) and hence
35113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              cos(x+y) = 1 - (x*x/2 - (r - x*y))
35213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         For better accuracy when x > 0.3, let qx = |x|/4 with
35313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
35413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         Then
35513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
35613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         Note that 1-qx and (x*x/2-qx) is EXACT here, and the
35713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         magnitude of the latter is at least a quarter of x*x/2,
35813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         thus, reducing the rounding error in the subtraction.
35913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
36013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochV8_INLINE double __kernel_cos(double x, double y) {
36113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
36213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
36313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      C1 = 4.16666666666666019037e-02,  /* 0x3FA55555, 0x5555554C */
36413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
36513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      C3 = 2.48015872894767294178e-05,  /* 0x3EFA01A0, 0x19CB1590 */
36613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
36713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      C5 = 2.08757232129817482790e-09,  /* 0x3E21EE9E, 0xBDB4B1C4 */
36813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
36913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
37013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double a, iz, z, r, qx;
37113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t ix;
37213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(ix, x);
37313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix &= 0x7fffffff;                           /* ix = |x|'s high word*/
37413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix < 0x3e400000) {                      /* if x < 2**27 */
37513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (static_cast<int>(x) == 0) return one; /* generate inexact */
37613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
37713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = x * x;
37813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
37913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix < 0x3FD33333) { /* if |x| < 0.3 */
38013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return one - (0.5 * z - (z * r - x * y));
38113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
38213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (ix > 0x3fe90000) { /* x > 0.78125 */
38313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      qx = 0.28125;
38413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
38513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      INSERT_WORDS(qx, ix - 0x00200000, 0); /* x/4 */
38613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
38713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    iz = 0.5 * z - qx;
38813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    a = one - qx;
38913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return a - (iz - (z * r - x * y));
39013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
39113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
39213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
39313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
39413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * double x[],y[]; int e0,nx,prec; int ipio2[];
39513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
39613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * __kernel_rem_pio2 return the last three digits of N with
39713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              y = x - N*pi/2
39813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * so that |y| < pi/2.
39913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
40013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The method is to compute the integer (mod 8) and fraction parts of
40113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * (2/pi)*x without doing the full multiplication. In general we
40213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * skip the part of the product that are known to be a huge integer (
40313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * more accurately, = 0 mod 8 ). Thus the number of operations are
40413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * independent of the exponent of the input.
40513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
40613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * (2/pi) is represented by an array of 24-bit integers in ipio2[].
40713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
40813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input parameters:
40913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      x[]     The input value (must be positive) is broken into nx
41013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              pieces of 24-bit integers in double precision format.
41113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              x[i] will be the i-th 24 bit of x. The scaled exponent
41213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
41313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              match x's up to 24 bits.
41413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
41513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              Example of breaking a double positive z into x[0]+x[1]+x[2]:
41613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      e0 = ilogb(z)-23
41713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      z  = scalbn(z,-e0)
41813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              for i = 0,1,2
41913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      x[i] = floor(z)
42013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      z    = (z-x[i])*2**24
42113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
42213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
42313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      y[]     output result in an array of double precision numbers.
42413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              The dimension of y[] is:
42513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      24-bit  precision       1
42613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      53-bit  precision       2
42713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      64-bit  precision       2
42813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      113-bit precision       3
42913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              The actual value is the sum of them. Thus for 113-bit
43013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              precison, one may have to do something like:
43113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
43213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              long double t,w,r_head, r_tail;
43313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              t = (long double)y[2] + (long double)y[1];
43413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              w = (long double)y[0];
43513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              r_head = t+w;
43613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              r_tail = w - (r_head - t);
43713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
43813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      e0      The exponent of x[0]
43913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      nx      dimension of x[]
44113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
44213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      prec    an integer indicating the precision:
44313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      0       24  bits (single)
44413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      1       53  bits (double)
44513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      2       64  bits (extended)
44613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      3       113 bits (quad)
44713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
44813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      ipio2[]
44913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              integer array, contains the (24*i)-th to (24*i+23)-th
45013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              bit of 2/pi after binary point. The corresponding
45113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              floating value is
45213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
45313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      ipio2[i] * 2^(-24(i+1)).
45413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
45513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * External function:
45613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      double scalbn(), floor();
45713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
45813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
45913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Here is the description of some local variables:
46013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
46113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      jk      jk+1 is the initial number of terms of ipio2[] needed
46213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              in the computation. The recommended value is 2,3,4,
46313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              6 for single, double, extended,and quad.
46413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
46513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      jz      local integer variable indicating the number of
46613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              terms of ipio2[] used.
46713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
46813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      jx      nx - 1
46913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
47013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      jv      index for pointing to the suitable ipio2[] for the
47113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              computation. In general, we want
47213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
47313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              is an integer. Thus
47413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      e0-3-24*jv >= 0 or (e0-3)/24 >= jv
47513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              Hence jv = max(0,(e0-3)/24).
47613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
47713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      jp      jp+1 is the number of terms in PIo2[] needed, jp = jk.
47813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
47913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      q[]     double array with integral value, representing the
48013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              24-bits chunk of the product of x and 2/pi.
48113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
48213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      q0      the corresponding exponent of q[0]. Note that the
48313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              exponent for q[i] would be q0-24*i.
48413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
48513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      PIo2[]  double precision array, obtained by cutting pi/2
48613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              into 24 bits chunks.
48713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
48813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      f[]     ipio2[] in floating point
48913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
49013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      iq[]    integer array by breaking up q[] in 24-bits chunk.
49113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
49213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      fq[]    final product of x*(2/pi) in fq[0],..,fq[jk]
49313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
49413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      ih      integer. If >0 it indicates q[] is >= 0.5, hence
49513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              it also indicates the *sign* of the result.
49613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
49713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
49813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochint __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec,
49913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                      const int32_t *ipio2) {
50013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* Constants:
50113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * The hexadecimal values are the intended ones for the following
50213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * constants. The decimal values may be used, provided that the
50313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * compiler will convert from decimal to binary accurately enough
50413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * to produce the hexadecimal values shown.
50513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
50613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const int init_jk[] = {2, 3, 4, 6}; /* initial value for jk */
50713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
50813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double PIo2[] = {
50913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
51013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
51113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
51213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
51313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
51413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
51513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
51613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
51713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
51813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
51913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
52013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      zero = 0.0,
52113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      one = 1.0,
52213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      two24 = 1.67772160000000000000e+07,  /* 0x41700000, 0x00000000 */
52313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
52413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
52513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t jz, jx, jv, jp, jk, carry, n, iq[20], i, j, k, m, q0, ih;
52613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double z, fw, f[20], fq[20], q[20];
52713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
52813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* initialize jk*/
52913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  jk = init_jk[prec];
53013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  jp = jk;
53113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
53213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* determine jx,jv,q0, note that 3>q0 */
53313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  jx = nx - 1;
53413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  jv = (e0 - 3) / 24;
53513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (jv < 0) jv = 0;
53613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  q0 = e0 - 24 * (jv + 1);
53713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
53813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
53913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  j = jv - jx;
54013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  m = jx + jk;
54113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (i = 0; i <= m; i++, j++) {
54213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    f[i] = (j < 0) ? zero : static_cast<double>(ipio2[j]);
54313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
54413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
54513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* compute q[0],q[1],...q[jk] */
54613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (i = 0; i <= jk; i++) {
54713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j];
54813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    q[i] = fw;
54913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
55013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
55113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  jz = jk;
55213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochrecompute:
55313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* distill q[] into iq[] reversingly */
55413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) {
55513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
55613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    iq[i] = static_cast<int32_t>(z - two24 * fw);
55713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = q[j - 1] + fw;
55813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
55913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
56013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* compute n */
56113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = scalbn(z, q0);           /* actual value of z */
56213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */
56313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  n = static_cast<int32_t>(z);
56413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z -= static_cast<double>(n);
56513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ih = 0;
56613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (q0 > 0) { /* need iq[jz-1] to determine n */
56713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    i = (iq[jz - 1] >> (24 - q0));
56813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    n += i;
56913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    iq[jz - 1] -= i << (24 - q0);
57013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ih = iq[jz - 1] >> (23 - q0);
57113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (q0 == 0) {
57213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ih = iq[jz - 1] >> 23;
57313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (z >= 0.5) {
57413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ih = 2;
57513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
57613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
57713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ih > 0) { /* q > 0.5 */
57813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    n += 1;
57913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    carry = 0;
58013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    for (i = 0; i < jz; i++) { /* compute 1-q */
58113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      j = iq[i];
58213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (carry == 0) {
58313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        if (j != 0) {
58413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          carry = 1;
58513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          iq[i] = 0x1000000 - j;
58613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        }
58713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else {
58813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        iq[i] = 0xffffff - j;
58913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
59013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
59113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (q0 > 0) { /* rare case: chance is 1 in 12 */
59213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      switch (q0) {
59313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 1:
59413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          iq[jz - 1] &= 0x7fffff;
59513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          break;
59613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 2:
59713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          iq[jz - 1] &= 0x3fffff;
59813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          break;
59913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
60013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
60113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (ih == 2) {
60213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      z = one - z;
60313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (carry != 0) z -= scalbn(one, q0);
60413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
60513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
60613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
60713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* check if recomputation is needed */
60813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (z == zero) {
60913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    j = 0;
61013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    for (i = jz - 1; i >= jk; i--) j |= iq[i];
61113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (j == 0) { /* need recomputation */
61213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (k = 1; jk >= k && iq[jk - k] == 0; k++) {
61313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        /* k = no. of terms needed */
61413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
61513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
61613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (i = jz + 1; i <= jz + k; i++) { /* add q[jz+1] to q[jz+k] */
61713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        f[jx + i] = ipio2[jv + i];
61813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j];
61913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        q[i] = fw;
62013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
62113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      jz += k;
62213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      goto recompute;
62313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
62413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
62513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
62613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* chop off zero terms */
62713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (z == 0.0) {
62813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    jz -= 1;
62913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    q0 -= 24;
63013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    while (iq[jz] == 0) {
63113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      jz--;
63213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      q0 -= 24;
63313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
63413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else { /* break z into 24-bit if necessary */
63513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = scalbn(z, -q0);
63613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (z >= two24) {
63713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
63813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      iq[jz] = z - two24 * fw;
63913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      jz += 1;
64013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      q0 += 24;
64113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      iq[jz] = fw;
64213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
64313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      iq[jz] = z;
64413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
64513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
64613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
64713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* convert integer "bit" chunk to floating-point value */
64813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  fw = scalbn(one, q0);
64913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (i = jz; i >= 0; i--) {
65013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    q[i] = fw * iq[i];
65113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    fw *= twon24;
65213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
65313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
65413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* compute PIo2[0,...,jp]*q[jz,...,0] */
65513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (i = jz; i >= 0; i--) {
65613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    for (fw = 0.0, k = 0; k <= jp && k <= jz - i; k++) fw += PIo2[k] * q[i + k];
65713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    fq[jz - i] = fw;
65813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
65913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
66013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* compress fq[] into y[] */
66113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  switch (prec) {
66213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 0:
66313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      fw = 0.0;
66413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (i = jz; i >= 0; i--) fw += fq[i];
66513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y[0] = (ih == 0) ? fw : -fw;
66613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
66713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 1:
66813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 2:
66913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      fw = 0.0;
67013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (i = jz; i >= 0; i--) fw += fq[i];
67113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y[0] = (ih == 0) ? fw : -fw;
67213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      fw = fq[0] - fw;
67313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (i = 1; i <= jz; i++) fw += fq[i];
67413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y[1] = (ih == 0) ? fw : -fw;
67513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
67613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 3: /* painful */
67713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (i = jz; i > 0; i--) {
67813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        fw = fq[i - 1] + fq[i];
67913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        fq[i] += fq[i - 1] - fw;
68013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        fq[i - 1] = fw;
68113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
68213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (i = jz; i > 1; i--) {
68313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        fw = fq[i - 1] + fq[i];
68413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        fq[i] += fq[i - 1] - fw;
68513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        fq[i - 1] = fw;
68613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
68713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (fw = 0.0, i = jz; i >= 2; i--) fw += fq[i];
68813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (ih == 0) {
68913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[0] = fq[0];
69013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[1] = fq[1];
69113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[2] = fw;
69213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else {
69313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[0] = -fq[0];
69413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[1] = -fq[1];
69513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y[2] = -fw;
69613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
69713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
69813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return n & 7;
69913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
70013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
70113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* __kernel_sin( x, y, iy)
70213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
70313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input x is assumed to be bounded by ~pi/4 in magnitude.
70413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input y is the tail of x.
70513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
70613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
70713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Algorithm
70813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      1. Since sin(-x) = -sin(x), we need only to consider positive x.
70913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
71013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      3. sin(x) is approximated by a polynomial of degree 13 on
71113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         [0,pi/4]
71213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                               3            13
71313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              sin(x) ~ x + S1*x + ... + S6*x
71413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         where
71513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
71613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |sin(x)         2     4     6     8     10     12  |     -58
71713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x  +S6*x   )| <= 2
71813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |  x                                               |
71913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
72013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      4. sin(x+y) = sin(x) + sin'(x')*y
72113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                  ~ sin(x) + (1-x*x/2)*y
72213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         For better accuracy, let
72313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                   3      2      2      2      2
72413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
72513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         then                   3    2
72613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              sin(x) = x + (S1*x + (x *(r-y/2)+y))
72713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
72813e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochV8_INLINE double __kernel_sin(double x, double y, int iy) {
72913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
73013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
73113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      S1 = -1.66666666666666324348e-01,  /* 0xBFC55555, 0x55555549 */
73213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      S2 = 8.33333333332248946124e-03,   /* 0x3F811111, 0x1110F8A6 */
73313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      S3 = -1.98412698298579493134e-04,  /* 0xBF2A01A0, 0x19C161D5 */
73413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      S4 = 2.75573137070700676789e-06,   /* 0x3EC71DE3, 0x57B1FE7D */
73513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      S5 = -2.50507602534068634195e-08,  /* 0xBE5AE5E6, 0x8A2B9CEB */
73613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      S6 = 1.58969099521155010221e-10;   /* 0x3DE5D93A, 0x5ACFD57C */
73713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
73813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double z, r, v;
73913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t ix;
74013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(ix, x);
74113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix &= 0x7fffffff;      /* high word of x */
74213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix < 0x3e400000) { /* |x| < 2**-27 */
74313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (static_cast<int>(x) == 0) return x;
74413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } /* generate inexact */
74513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = x * x;
74613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v = z * x;
74713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
74813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (iy == 0) {
74913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x + v * (S1 + z * r);
75013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
75113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x - ((z * (half * y - v * r) - y) - v * S1);
75213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
75313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
75413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
75513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* __kernel_tan( x, y, k )
75613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
75713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input x is assumed to be bounded by ~pi/4 in magnitude.
75813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input y is the tail of x.
75913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Input k indicates whether tan (if k=1) or
76013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * -1/tan (if k= -1) is returned.
76113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
76213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Algorithm
76313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      1. Since tan(-x) = -tan(x), we need only to consider positive x.
76413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
76513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      3. tan(x) is approximated by a odd polynomial of degree 27 on
76613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         [0,0.67434]
76713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                               3             27
76813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              tan(x) ~ x + T1*x + ... + T13*x
76913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         where
77013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
77113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              |tan(x)         2     4            26   |     -59.2
77213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              |----- - (1+T1*x +T2*x +.... +T13*x    )| <= 2
77313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              |  x                                    |
77413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
77513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         Note: tan(x+y) = tan(x) + tan'(x)*y
77613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                        ~ tan(x) + (1+x*x)*y
77713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         Therefore, for better accuracy in computing tan(x+y), let
77813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                   3      2      2       2       2
77913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
78013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         then
78113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                                  3    2
78213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              tan(x+y) = x + (T1*x + (x *(r+y)+y))
78313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
78413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
78513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
78613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                     = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
78713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
78813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble __kernel_tan(double x, double y, int iy) {
78913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double xxx[] = {
79013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      3.33333333333334091986e-01,             /* 3FD55555, 55555563 */
79113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.33333333333201242699e-01,             /* 3FC11111, 1110FE7A */
79213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      5.39682539762260521377e-02,             /* 3FABA1BA, 1BB341FE */
79313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      2.18694882948595424599e-02,             /* 3F9664F4, 8406D637 */
79413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      8.86323982359930005737e-03,             /* 3F8226E3, E96E8493 */
79513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      3.59207910759131235356e-03,             /* 3F6D6D22, C9560328 */
79613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.45620945432529025516e-03,             /* 3F57DBC8, FEE08315 */
79713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      5.88041240820264096874e-04,             /* 3F4344D8, F2F26501 */
79813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      2.46463134818469906812e-04,             /* 3F3026F7, 1A8D1068 */
79913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      7.81794442939557092300e-05,             /* 3F147E88, A03792A6 */
80013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      7.14072491382608190305e-05,             /* 3F12B80F, 32F0A7E9 */
80113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      -1.85586374855275456654e-05,            /* BEF375CB, DB605373 */
80213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      2.59073051863633712884e-05,             /* 3EFB2A70, 74BF7AD4 */
80313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      /* one */ 1.00000000000000000000e+00,   /* 3FF00000, 00000000 */
80413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      /* pio4 */ 7.85398163397448278999e-01,  /* 3FE921FB, 54442D18 */
80513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      /* pio4lo */ 3.06161699786838301793e-17 /* 3C81A626, 33145C07 */
80613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
80713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define one xxx[13]
80813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define pio4 xxx[14]
80913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define pio4lo xxx[15]
81013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define T xxx
81113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
81213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double z, r, v, w, s;
81313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t ix, hx;
81413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
81513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(hx, x);             /* high word of x */
81613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix = hx & 0x7fffffff;             /* high word of |x| */
81713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix < 0x3e300000) {            /* x < 2**-28 */
81813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (static_cast<int>(x) == 0) { /* generate inexact */
81913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      uint32_t low;
82013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      GET_LOW_WORD(low, x);
82113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (((ix | low) | (iy + 1)) == 0) {
82213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return one / fabs(x);
82313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else {
82413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        if (iy == 1) {
82513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return x;
82613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        } else { /* compute -1 / (x+y) carefully */
82713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          double a, t;
82813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
82913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          z = w = x + y;
83013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          SET_LOW_WORD(z, 0);
83113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          v = y - (z - x);
83213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          t = a = -one / w;
83313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          SET_LOW_WORD(t, 0);
83413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          s = one + t * z;
83513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return t + a * (s + t * v);
83613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        }
83713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
83813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
83913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
84013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix >= 0x3FE59428) { /* |x| >= 0.6744 */
84113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx < 0) {
84213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      x = -x;
84313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y = -y;
84413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
84513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = pio4 - x;
84613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    w = pio4lo - y;
84713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    x = z + w;
84813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    y = 0.0;
84913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
85013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = x * x;
85113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  w = z * z;
85213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /*
85313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * Break x^5*(T[1]+x^2*T[2]+...) into
85413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
85513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
85613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
85713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11]))));
85813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v = z *
85913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12])))));
86013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  s = z * x;
86113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r = y + z * (s * (r + v) + y);
86213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r += T[0] * s;
86313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  w = x + r;
86413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix >= 0x3FE59428) {
86513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    v = iy;
86613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return (1 - ((hx >> 30) & 2)) * (v - 2.0 * (x - (w * w / (w + v) - r)));
86713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
86813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (iy == 1) {
86913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return w;
87013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
87113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /*
87213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     * if allow error up to 2 ulp, simply return
87313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     * -1.0 / (x+r) here
87413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     */
87513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /* compute -1.0 / (x+r) accurately */
87613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    double a, t;
87713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = w;
87813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SET_LOW_WORD(z, 0);
87913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    v = r - (z - x);  /* z+v = r+x */
88013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    t = a = -1.0 / w; /* a = -1.0/w */
88113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SET_LOW_WORD(t, 0);
88213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    s = 1.0 + t * z;
88313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return t + a * (s + t * v);
88413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
88513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
88613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#undef one
88713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#undef pio4
88813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#undef pio4lo
88913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#undef T
89013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
89113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
89213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}  // namespace
89313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch/* acos(x)
895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Method :
896f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      acos(x)  = pi/2 - asin(x)
897f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      acos(-x) = pi/2 + asin(x)
898f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * For |x|<=0.5
899f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      acos(x) = pi/2 - (x + x*x^2*R(x^2))     (see asin.c)
900f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * For x>0.5
901f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
902f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              = 2asin(sqrt((1-x)/2))
903f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              = 2s + 2s*z*R(z)        ...z=(1-x)/2, s=sqrt(z)
904f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              = 2f + (2c + 2s*z*R(z))
905f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *     where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
906f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *     for f so that f+c ~ sqrt(z).
907f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * For x<-0.5
908f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      acos(x) = pi - 2asin(sqrt((1-|x|)/2))
909f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
910f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
911f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Special cases:
912f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      if x is NaN, return x itself;
913f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      if |x|>1, return NaN with invalid signal.
914f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
915f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Function needed: sqrt
916f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch */
917f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdouble acos(double x) {
918f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double
919f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      one = 1.00000000000000000000e+00,     /* 0x3FF00000, 0x00000000 */
920f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pi = 3.14159265358979311600e+00,      /* 0x400921FB, 0x54442D18 */
921f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
922f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
923f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS0 = 1.66666666666666657415e-01,     /* 0x3FC55555, 0x55555555 */
924f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS1 = -3.25565818622400915405e-01,    /* 0xBFD4D612, 0x03EB6F7D */
925f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS2 = 2.01212532134862925881e-01,     /* 0x3FC9C155, 0x0E884455 */
926f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS3 = -4.00555345006794114027e-02,    /* 0xBFA48228, 0xB5688F3B */
927f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS4 = 7.91534994289814532176e-04,     /* 0x3F49EFE0, 0x7501B288 */
928f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS5 = 3.47933107596021167570e-05,     /* 0x3F023DE1, 0x0DFDF709 */
929f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      qS1 = -2.40339491173441421878e+00,    /* 0xC0033A27, 0x1C8A2D4B */
930f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      qS2 = 2.02094576023350569471e+00,     /* 0x40002AE5, 0x9C598AC8 */
931f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      qS3 = -6.88283971605453293030e-01,    /* 0xBFE6066C, 0x1B8D0159 */
932f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      qS4 = 7.70381505559019352791e-02;     /* 0x3FB3B8C5, 0xB12E9282 */
933f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
934f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double z, p, q, r, w, s, c, df;
935f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int32_t hx, ix;
936f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  GET_HIGH_WORD(hx, x);
937f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ix = hx & 0x7fffffff;
938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix >= 0x3ff00000) { /* |x| >= 1 */
939f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    uint32_t lx;
940f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    GET_LOW_WORD(lx, x);
941f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (((ix - 0x3ff00000) | lx) == 0) { /* |x|==1 */
942f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (hx > 0)
943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return 0.0; /* acos(1) = 0  */
944f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      else
945f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return pi + 2.0 * pio2_lo; /* acos(-1)= pi */
946f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
947f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return (x - x) / (x - x); /* acos(|x|>1) is NaN */
948f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix < 0x3fe00000) {                            /* |x| < 0.5 */
950f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (ix <= 0x3c600000) return pio2_hi + pio2_lo; /*if|x|<2**-57*/
951f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    z = x * x;
952f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
953f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
954f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r = p / q;
955f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return pio2_hi - (x - (pio2_lo - x * r));
956f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (hx < 0) { /* x < -0.5 */
957f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    z = (one + x) * 0.5;
958f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
959f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
960f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    s = sqrt(z);
961f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r = p / q;
962f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    w = r * s - pio2_lo;
963f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return pi - 2.0 * (s + w);
964f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else { /* x > 0.5 */
965f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    z = (one - x) * 0.5;
966f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    s = sqrt(z);
967f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    df = s;
968f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    SET_LOW_WORD(df, 0);
969f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    c = (z - df * df) / (s + df);
970f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
971f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
972f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r = p / q;
973f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    w = r * s + c;
974f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return 2.0 * (df + w);
975f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
976f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
977f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
978f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch/* acosh(x)
979f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Method :
980f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      Based on
981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              acosh(x) = log [ x + sqrt(x*x-1) ]
982f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      we have
983f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              acosh(x) := log(x)+ln2, if x is large; else
984f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
985f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
986f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
987f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Special cases:
988f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      acosh(x) is NaN with signal if x<1.
989f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      acosh(NaN) is NaN without signal.
990f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch */
991f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdouble acosh(double x) {
992f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double
993f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      one = 1.0,
994f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */
995f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double t;
996f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int32_t hx;
997f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  uint32_t lx;
998f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  EXTRACT_WORDS(hx, lx, x);
999f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (hx < 0x3ff00000) { /* x < 1 */
1000f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return (x - x) / (x - x);
1001f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (hx >= 0x41b00000) { /* x > 2**28 */
1002f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (hx >= 0x7ff00000) {      /* x is inf of NaN */
1003f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return x + x;
1004f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
1005f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return log(x) + ln2; /* acosh(huge)=log(2x) */
1006f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1007f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (((hx - 0x3ff00000) | lx) == 0) {
1008f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return 0.0;                 /* acosh(1) = 0 */
1009f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (hx > 0x40000000) { /* 2**28 > x > 2 */
1010f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    t = x * x;
1011f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return log(2.0 * x - one / (x + sqrt(t - one)));
1012f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else { /* 1<x<2 */
1013f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    t = x - one;
1014f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return log1p(t + sqrt(2.0 * t + t * t));
1015f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1016f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1017f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1018f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch/* asin(x)
1019f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Method :
1020f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      Since  asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
1021f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      we approximate asin(x) on [0,0.5] by
1022f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              asin(x) = x + x*x^2*R(x^2)
1023f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      where
1024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              R(x^2) is a rational approximation of (asin(x)-x)/x^3
1025f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      and its remez error is bounded by
1026f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
1027f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
1028f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      For x in [0.5,1]
1029f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              asin(x) = pi/2-2*asin(sqrt((1-x)/2))
1030f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
1031f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      then for x>0.98
1032f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              asin(x) = pi/2 - 2*(s+s*z*R(z))
1033f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                      = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
1034f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      For x<=0.98, let pio4_hi = pio2_hi/2, then
1035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              f = hi part of s;
1036f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              c = sqrt(z) - f = (z-f*f)/(s+f)         ...f+c=sqrt(z)
1037f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      and
1038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              asin(x) = pi/2 - 2*(s+s*z*R(z))
1039f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                      = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
1040f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                      = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
1041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
1042f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Special cases:
1043f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      if x is NaN, return x itself;
1044f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      if |x|>1, return NaN with invalid signal.
1045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch */
1046f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdouble asin(double x) {
1047f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double
1048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
1049f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      huge = 1.000e+300,
1050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
1051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
1052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
1053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                            /* coefficient for R(x^2) */
1054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS0 = 1.66666666666666657415e-01,     /* 0x3FC55555, 0x55555555 */
1055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS1 = -3.25565818622400915405e-01,    /* 0xBFD4D612, 0x03EB6F7D */
1056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS2 = 2.01212532134862925881e-01,     /* 0x3FC9C155, 0x0E884455 */
1057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS3 = -4.00555345006794114027e-02,    /* 0xBFA48228, 0xB5688F3B */
1058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS4 = 7.91534994289814532176e-04,     /* 0x3F49EFE0, 0x7501B288 */
1059f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      pS5 = 3.47933107596021167570e-05,     /* 0x3F023DE1, 0x0DFDF709 */
1060f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      qS1 = -2.40339491173441421878e+00,    /* 0xC0033A27, 0x1C8A2D4B */
1061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      qS2 = 2.02094576023350569471e+00,     /* 0x40002AE5, 0x9C598AC8 */
1062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      qS3 = -6.88283971605453293030e-01,    /* 0xBFE6066C, 0x1B8D0159 */
1063f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      qS4 = 7.70381505559019352791e-02;     /* 0x3FB3B8C5, 0xB12E9282 */
1064f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1065f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double t, w, p, q, c, r, s;
1066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int32_t hx, ix;
1067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  t = 0;
1069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  GET_HIGH_WORD(hx, x);
1070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ix = hx & 0x7fffffff;
1071f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix >= 0x3ff00000) { /* |x|>= 1 */
1072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    uint32_t lx;
1073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    GET_LOW_WORD(lx, x);
1074f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (((ix - 0x3ff00000) | lx) == 0) /* asin(1)=+-pi/2 with inexact */
1075f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return x * pio2_hi + x * pio2_lo;
1076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return (x - x) / (x - x);       /* asin(|x|>1) is NaN */
1077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (ix < 0x3fe00000) {     /* |x|<0.5 */
1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (ix < 0x3e400000) {          /* if |x| < 2**-27 */
1079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (huge + x > one) return x; /* return x with inexact if x!=0*/
1080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
1081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      t = x * x;
1082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1083f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5)))));
1084f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4)));
1085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    w = p / q;
1086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return x + x * w;
1087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1088f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  /* 1> |x|>= 0.5 */
1089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  w = one - fabs(x);
1090f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  t = w * 0.5;
1091f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5)))));
1092f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4)));
1093f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  s = sqrt(t);
1094f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix >= 0x3FEF3333) { /* if |x| > 0.975 */
1095f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    w = p / q;
1096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    t = pio2_hi - (2.0 * (s + s * w) - pio2_lo);
1097f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
1098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    w = s;
1099f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    SET_LOW_WORD(w, 0);
1100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    c = (t - w * w) / (s + w);
1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    r = p / q;
1102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    p = 2.0 * s * r - (pio2_lo - 2.0 * c);
1103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    q = pio4_hi - 2.0 * w;
1104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    t = pio4_hi - (p - q);
1105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (hx > 0)
1107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return t;
1108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  else
1109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return -t;
1110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch/* asinh(x)
1112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Method :
1113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      Based on
1114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *              asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
1115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      we have
1116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      asinh(x) := x  if  1+x*x=1,
1117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *               := sign(x)*(log(x)+ln2)) for large |x|, else
1118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *               := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
1119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *               := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
1120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch */
1121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdouble asinh(double x) {
1122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double
1123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
1124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
1125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      huge = 1.00000000000000000000e+300;
1126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double t, w;
1128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int32_t hx, ix;
1129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  GET_HIGH_WORD(hx, x);
1130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ix = hx & 0x7fffffff;
1131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix >= 0x7ff00000) return x + x; /* x is inf or NaN */
1132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix < 0x3e300000) {              /* |x|<2**-28 */
1133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (huge + x > one) return x;     /* return x inexact except 0 */
1134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix > 0x41b00000) { /* |x| > 2**28 */
1136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    w = log(fabs(x)) + ln2;
1137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (ix > 0x40000000) { /* 2**28 > |x| > 2.0 */
1138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    t = fabs(x);
1139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    w = log(2.0 * t + one / (sqrt(x * x + one) + t));
1140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else { /* 2.0 > |x| > 2**-28 */
1141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    t = x * x;
1142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    w = log1p(fabs(x) + t / (one + sqrt(one + t)));
1143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (hx > 0) {
1145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return w;
1146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
1147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return -w;
1148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
115113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* atan(x)
115213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method
115313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   1. Reduce x to positive by atan(x) = -atan(-x).
115413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   2. According to the integer k=4t+0.25 chopped, t=x, the argument
115513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      is further reduced to one of the following intervals and the
115613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      arctangent of t is evaluated by the corresponding formula:
115713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
115813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [0,7/16]      atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
115913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [7/16,11/16]  atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
116013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
116113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
116213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [39/16,INF]   atan(x) = atan(INF) + atan( -1/t )
116313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
116413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Constants:
116513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The hexadecimal values are the intended ones for the following
116613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * constants. The decimal values may be used, provided that the
116713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * compiler will convert from decimal to binary accurately enough
116813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * to produce the hexadecimal values shown.
116913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
117013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble atan(double x) {
117113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double atanhi[] = {
117213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
117313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
117413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
117513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
117613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
117713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
117813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double atanlo[] = {
117913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
118013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
118113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
118213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
118313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
118413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
118513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double aT[] = {
118613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      3.33333333333329318027e-01,  /* 0x3FD55555, 0x5555550D */
118713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
118813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.42857142725034663711e-01,  /* 0x3FC24924, 0x920083FF */
118913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
119013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      9.09088713343650656196e-02,  /* 0x3FB745CD, 0xC54C206E */
119113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
119213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      6.66107313738753120669e-02,  /* 0x3FB10D66, 0xA0D03D51 */
119313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
119413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      4.97687799461593236017e-02,  /* 0x3FA97B4B, 0x24760DEB */
119513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
119613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.62858201153657823623e-02,  /* 0x3F90AD3A, 0xE322DA11 */
119713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
119813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
119913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double one = 1.0, huge = 1.0e300;
120013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
120113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double w, s1, s2, z;
120213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t ix, hx, id;
120313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
120413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(hx, x);
120513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix = hx & 0x7fffffff;
120613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix >= 0x44100000) { /* if |x| >= 2^66 */
120713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint32_t low;
120813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    GET_LOW_WORD(low, x);
120913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (low != 0)))
121013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return x + x; /* NaN */
121113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx > 0)
121213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return atanhi[3] + *(volatile double *)&atanlo[3];
121313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    else
121413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return -atanhi[3] - *(volatile double *)&atanlo[3];
121513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
121613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix < 0x3fdc0000) {            /* |x| < 0.4375 */
121713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (ix < 0x3e400000) {          /* |x| < 2^-27 */
121813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (huge + x > one) return x; /* raise inexact */
121913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
122013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    id = -1;
122113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
122213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    x = fabs(x);
122313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (ix < 0x3ff30000) {   /* |x| < 1.1875 */
122413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
122513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        id = 0;
122613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        x = (2.0 * x - one) / (2.0 + x);
122713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else { /* 11/16<=|x|< 19/16 */
122813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        id = 1;
122913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        x = (x - one) / (x + one);
123013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
123113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
123213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (ix < 0x40038000) { /* |x| < 2.4375 */
123313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        id = 2;
123413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        x = (x - 1.5) / (one + 1.5 * x);
123513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else { /* 2.4375 <= |x| < 2^66 */
123613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        id = 3;
123713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        x = -1.0 / x;
123813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
123913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
124013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
124113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* end of argument reduction */
124213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = x * x;
124313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  w = z * z;
124413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
124513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  s1 = z * (aT[0] +
124613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10])))));
124713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
124813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (id < 0) {
124913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x - x * (s1 + s2);
125013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
125113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
125213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return (hx < 0) ? -z : z;
125313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
125413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
125513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
125613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* atan2(y,x)
125713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method :
125813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
125913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  2. Reduce x to positive by (if x and y are unexceptional):
126013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    ARG (x+iy) = arctan(y/x)       ... if x > 0,
126113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
126213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
126313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
126413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
126513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2((anything), NaN ) is NaN;
126613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(NAN , (anything) ) is NaN;
126713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(+-0, +(anything but NaN)) is +-0  ;
126813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(+-0, -(anything but NaN)) is +-pi ;
126913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
127013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
127113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
127213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(+-INF,+INF ) is +-pi/4 ;
127313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(+-INF,-INF ) is +-3pi/4;
127413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
127513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
127613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Constants:
127713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The hexadecimal values are the intended ones for the following
127813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * constants. The decimal values may be used, provided that the
127913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * compiler will convert from decimal to binary accurately enough
128013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * to produce the hexadecimal values shown.
128113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
128213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble atan2(double y, double x) {
128313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static volatile double tiny = 1.0e-300;
128413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
128513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      zero = 0.0,
128613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
128713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
128813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      pi = 3.1415926535897931160E+00;     /* 0x400921FB, 0x54442D18 */
128913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static volatile double pi_lo =
129013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
129113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
129213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double z;
129313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t k, m, hx, hy, ix, iy;
129413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t lx, ly;
129513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
129613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EXTRACT_WORDS(hx, lx, x);
129713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix = hx & 0x7fffffff;
129813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EXTRACT_WORDS(hy, ly, y);
129913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iy = hy & 0x7fffffff;
130013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (((ix | ((lx | -static_cast<int32_t>(lx)) >> 31)) > 0x7ff00000) ||
130113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ((iy | ((ly | -static_cast<int32_t>(ly)) >> 31)) > 0x7ff00000)) {
130213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x + y; /* x or y is NaN */
130313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
130413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (((hx - 0x3ff00000) | lx) == 0) return atan(y); /* x=1.0 */
130513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  m = ((hy >> 31) & 1) | ((hx >> 30) & 2);           /* 2*sign(x)+sign(y) */
130613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
130713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* when y = 0 */
130813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if ((iy | ly) == 0) {
130913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    switch (m) {
131013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 0:
131113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 1:
131213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return y; /* atan(+-0,+anything)=+-0 */
131313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 2:
131413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return pi + tiny; /* atan(+0,-anything) = pi */
131513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 3:
131613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return -pi - tiny; /* atan(-0,-anything) =-pi */
131713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
131813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
131913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* when x = 0 */
132013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if ((ix | lx) == 0) return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
132113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
132213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* when x is INF */
132313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix == 0x7ff00000) {
132413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (iy == 0x7ff00000) {
132513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      switch (m) {
132613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 0:
132713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return pi_o_4 + tiny; /* atan(+INF,+INF) */
132813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 1:
132913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return -pi_o_4 - tiny; /* atan(-INF,+INF) */
133013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 2:
133113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return 3.0 * pi_o_4 + tiny; /*atan(+INF,-INF)*/
133213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 3:
133313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return -3.0 * pi_o_4 - tiny; /*atan(-INF,-INF)*/
133413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
133513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
133613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      switch (m) {
133713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 0:
133813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return zero; /* atan(+...,+INF) */
133913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 1:
134013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return -zero; /* atan(-...,+INF) */
134113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 2:
134213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return pi + tiny; /* atan(+...,-INF) */
134313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        case 3:
134413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return -pi - tiny; /* atan(-...,-INF) */
134513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
134613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
134713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
134813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* when y is INF */
134913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (iy == 0x7ff00000) return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
135013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
135113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* compute y/x */
135213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k = (iy - ix) >> 20;
135313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (k > 60) { /* |y/x| >  2**60 */
135413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = pi_o_2 + 0.5 * pi_lo;
135513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    m &= 1;
135613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (hx < 0 && k < -60) {
135713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = 0.0; /* 0 > |y|/x > -2**-60 */
135813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
135913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    z = atan(fabs(y / x)); /* safe to do y/x */
136013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
136113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  switch (m) {
136213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 0:
136313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return z; /* atan(+,+) */
136413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 1:
136513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return -z; /* atan(-,+) */
136613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 2:
136713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return pi - (z - pi_lo); /* atan(+,-) */
136813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    default:                   /* case 3 */
136913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return (z - pi_lo) - pi; /* atan(-,-) */
137013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
137113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
137213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
137313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* cos(x)
137413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Return cosine function of x.
137513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
137613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * kernel function:
137713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      __kernel_sin            ... sine function on [-pi/4,pi/4]
137813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      __kernel_cos            ... cosine function on [-pi/4,pi/4]
137913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      __ieee754_rem_pio2      ... argument reduction routine
138013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
138113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method.
138213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Let S,C and T denote the sin, cos and tan respectively on
138313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
138413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      in [-pi/4 , +pi/4], and let n = k mod 4.
138513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      We have
138613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
138713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          n        sin(x)      cos(x)        tan(x)
138813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     ----------------------------------------------------------
138913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          0          S           C             T
139013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          1          C          -S            -1/T
139113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          2         -S          -C             T
139213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          3         -C           S            -1/T
139313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     ----------------------------------------------------------
139413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
139513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
139613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Let trig be any of sin, cos, or tan.
139713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      trig(+-INF)  is NaN, with signals;
139813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      trig(NaN)    is that NaN;
139913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
140013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Accuracy:
140113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      TRIG(x) returns trig(x) nearly rounded
140213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
140313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble cos(double x) {
140413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double y[2], z = 0.0;
140513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t n, ix;
140613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
140713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* High word of x. */
140813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(ix, x);
140913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
141013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* |x| ~< pi/4 */
141113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix &= 0x7fffffff;
141213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix <= 0x3fe921fb) {
141313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return __kernel_cos(x, z);
141413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (ix >= 0x7ff00000) {
141513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /* cos(Inf or NaN) is NaN */
141613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x - x;
141713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
141813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /* argument reduction needed */
141913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    n = __ieee754_rem_pio2(x, y);
142013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    switch (n & 3) {
142113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 0:
142213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return __kernel_cos(y[0], y[1]);
142313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 1:
142413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return -__kernel_sin(y[0], y[1], 1);
142513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 2:
142613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return -__kernel_cos(y[0], y[1]);
142713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      default:
142813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return __kernel_sin(y[0], y[1], 1);
142913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
143013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
143113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
143213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
143313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* exp(x)
143413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Returns the exponential of x.
143513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
143613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method
143713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   1. Argument reduction:
143813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
143913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Given x, find r and integer k such that
144013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
144113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *               x = k*ln2 + r,  |r| <= 0.5*ln2.
144213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
144313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Here r will be represented as r = hi-lo for better
144413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      accuracy.
144513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
144613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   2. Approximation of exp(r) by a special rational function on
144713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      the interval [0,0.34658]:
144813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Write
144913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
145013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      We use a special Remes algorithm on [0,0.34658] to generate
145113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      a polynomial of degree 5 to approximate R. The maximum error
145213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      of this polynomial approximation is bounded by 2**-59. In
145313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      other words,
145413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
145513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      (where z=r*r, and the values of P1 to P5 are listed below)
145613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      and
145713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          |                  5          |     -59
145813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          | 2.0+P1*z+...+P5*z   -  R(z) | <= 2
145913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          |                             |
146013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      The computation of exp(r) thus becomes
146113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                             2*r
146213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              exp(r) = 1 + -------
146313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                            R - r
146413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                                 r*R1(r)
146513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                     = 1 + r + ----------- (for better accuracy)
146613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                                2 - R1(r)
146713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      where
146813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                               2       4             10
146913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
147013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
147113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   3. Scale back to obtain exp(x):
147213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      From step 1, we have
147313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         exp(x) = 2^k * exp(r)
147413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
147513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
147613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      exp(INF) is INF, exp(NaN) is NaN;
147713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      exp(-INF) is 0, and
147813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      for finite argument, only exp(0)=1 is exact.
147913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
148013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Accuracy:
148113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      according to an error analysis, the error is always less than
148213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      1 ulp (unit in the last place).
148313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
148413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Misc. info.
148513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      For IEEE double
148613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          if x >  7.09782712893383973096e+02 then exp(x) overflow
148713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          if x < -7.45133219101941108420e+02 then exp(x) underflow
148813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
148913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Constants:
149013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The hexadecimal values are the intended ones for the following
149113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * constants. The decimal values may be used, provided that the
149213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * compiler will convert from decimal to binary accurately enough
149313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * to produce the hexadecimal values shown.
149413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
149513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble exp(double x) {
149613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
149713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      one = 1.0,
149813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      halF[2] = {0.5, -0.5},
149913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      o_threshold = 7.09782712893383973096e+02,  /* 0x40862E42, 0xFEFA39EF */
150013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      u_threshold = -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
150113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ln2HI[2] = {6.93147180369123816490e-01,    /* 0x3fe62e42, 0xfee00000 */
150213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                  -6.93147180369123816490e-01},  /* 0xbfe62e42, 0xfee00000 */
150313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ln2LO[2] = {1.90821492927058770002e-10,    /* 0x3dea39ef, 0x35793c76 */
150413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                  -1.90821492927058770002e-10},  /* 0xbdea39ef, 0x35793c76 */
150513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      invln2 = 1.44269504088896338700e+00,       /* 0x3ff71547, 0x652b82fe */
150613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P1 = 1.66666666666666019037e-01,           /* 0x3FC55555, 0x5555553E */
150713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P2 = -2.77777777770155933842e-03,          /* 0xBF66C16C, 0x16BEBD93 */
150813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P3 = 6.61375632143793436117e-05,           /* 0x3F11566A, 0xAF25DE2C */
150913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P4 = -1.65339022054652515390e-06,          /* 0xBEBBBD41, 0xC5D26BF1 */
151013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P5 = 4.13813679705723846039e-08,           /* 0x3E663769, 0x72BEA4D0 */
151113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      E = 2.718281828459045;                     /* 0x4005bf0a, 0x8b145769 */
151213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
151313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static volatile double
151413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      huge = 1.0e+300,
151513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      twom1000 = 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/
151613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      two1023 = 8.988465674311579539e307;     /* 0x1p1023 */
151713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
151813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double y, hi = 0.0, lo = 0.0, c, t, twopk;
151913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t k = 0, xsb;
152013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t hx;
152113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
152213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(hx, x);
152313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  xsb = (hx >> 31) & 1; /* sign bit of x */
152413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hx &= 0x7fffffff;     /* high word of |x| */
152513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
152613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* filter out non-finite argument */
152713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx >= 0x40862E42) { /* if |x|>=709.78... */
152813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx >= 0x7ff00000) {
152913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      uint32_t lx;
153013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      GET_LOW_WORD(lx, x);
153113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (((hx & 0xfffff) | lx) != 0)
153213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return x + x; /* NaN */
153313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      else
153413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return (xsb == 0) ? x : 0.0; /* exp(+-inf)={inf,0} */
153513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
153613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (x > o_threshold) return huge * huge;         /* overflow */
153713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (x < u_threshold) return twom1000 * twom1000; /* underflow */
153813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
153913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
154013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* argument reduction */
154113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx > 0x3fd62e42) {   /* if  |x| > 0.5 ln2 */
154213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
154313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      /* TODO(rtoy): We special case exp(1) here to return the correct
154413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       * value of E, as the computation below would get the last bit
154513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       * wrong. We should probably fix the algorithm instead.
154613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch       */
154713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (x == 1.0) return E;
154813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      hi = x - ln2HI[xsb];
154913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      lo = ln2LO[xsb];
155013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      k = 1 - xsb - xsb;
155113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
155213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      k = static_cast<int>(invln2 * x + halF[xsb]);
155313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      t = k;
155413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      hi = x - t * ln2HI[0]; /* t*ln2HI is exact here */
155513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      lo = t * ln2LO[0];
155613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
155713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    STRICT_ASSIGN(double, x, hi - lo);
155813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (hx < 0x3e300000) {         /* when |x|<2**-28 */
155913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (huge + x > one) return one + x; /* trigger inexact */
156013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
156113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    k = 0;
156213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
156313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
156413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* x is now in primary range */
156513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t = x * x;
156613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (k >= -1021) {
156713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    INSERT_WORDS(twopk, 0x3ff00000 + (k << 20), 0);
156813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
156913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    INSERT_WORDS(twopk, 0x3ff00000 + ((k + 1000) << 20), 0);
157013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
157113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
157213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (k == 0) {
157313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return one - ((x * c) / (c - 2.0) - x);
157413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
157513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    y = one - ((lo - (x * c) / (2.0 - c)) - hi);
157613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
157713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (k >= -1021) {
157813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k == 1024) return y * 2.0 * two1023;
157913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return y * twopk;
158013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
158113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return y * twopk * twom1000;
158213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
158313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
158413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
158513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/*
158613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method :
158713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    1.Reduced x to positive by atanh(-x) = -atanh(x)
158813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    2.For x>=0.5
158913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              1              2x                          x
159013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
159113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              2             1 - x                      1 - x
159213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
159313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   For x<0.5
159413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
159513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
159613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
159713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  atanh(x) is NaN if |x| > 1 with signal;
159813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  atanh(NaN) is that NaN with no signal;
159913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  atanh(+-1) is +-INF with signal.
160013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
160113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
160213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble atanh(double x) {
160313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double one = 1.0, huge = 1e300;
160413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double zero = 0.0;
160513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
160613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double t;
160713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t hx, ix;
160813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t lx;
160913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EXTRACT_WORDS(hx, lx, x);
161013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix = hx & 0x7fffffff;
161113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if ((ix | ((lx | -static_cast<int32_t>(lx)) >> 31)) > 0x3ff00000) /* |x|>1 */
161213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return (x - x) / (x - x);
161313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix == 0x3ff00000) return x / zero;
161413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix < 0x3e300000 && (huge + x) > zero) return x; /* x<2**-28 */
161513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SET_HIGH_WORD(x, ix);
161613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix < 0x3fe00000) { /* x < 0.5 */
161713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    t = x + x;
161813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    t = 0.5 * log1p(t + t * x / (one - x));
161913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
162013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    t = 0.5 * log1p((x + x) / (one - x));
162113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
162213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx >= 0)
162313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return t;
162413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  else
162513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return -t;
162613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
162713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
162813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* log(x)
162913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Return the logrithm of x
163013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
163113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method :
163213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   1. Argument Reduction: find k and f such that
163313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     x = 2^k * (1+f),
163413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     where  sqrt(2)/2 < 1+f < sqrt(2) .
163513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
163613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   2. Approximation of log(1+f).
163713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
163813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     = 2s + 2/3 s**3 + 2/5 s**5 + .....,
163913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         = 2s + s*R
164013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      We use a special Reme algorithm on [0,0.1716] to generate
164113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  a polynomial of degree 14 to approximate R The maximum error
164213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  of this polynomial approximation is bounded by 2**-58.45. In
164313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  other words,
164413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *            2      4      6      8      10      12      14
164513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
164613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    (the values of Lg1 to Lg7 are listed in the program)
164713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  and
164813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |      2          14          |     -58.45
164913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      | Lg1*s +...+Lg7*s    -  R(z) | <= 2
165013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |                             |
165113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
165213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  In order to guarantee error in log below 1ulp, we compute log
165313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  by
165413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    log(1+f) = f - s*(f - R)  (if f is not too large)
165513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
165613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
165713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  3. Finally,  log(x) = k*ln2 + log(1+f).
165813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
165913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     Here ln2 is split into two floating point number:
166013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      ln2_hi + ln2_lo,
166113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     where n*ln2_hi is always exact for |n| < 2000.
166213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
166313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
166413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  log(x) is NaN with signal if x < 0 (including -INF) ;
166513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  log(+INF) is +INF; log(0) is -INF with signal;
166613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  log(NaN) is that NaN with no signal.
166713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
166813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Accuracy:
166913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  according to an error analysis, the error is always less than
167013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  1 ulp (unit in the last place).
167113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
167213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Constants:
167313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The hexadecimal values are the intended ones for the following
167413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * constants. The decimal values may be used, provided that the
167513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * compiler will convert from decimal to binary accurately enough
167613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * to produce the hexadecimal values shown.
167713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
167813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble log(double x) {
167913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double                      /* -- */
168013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
168113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
168213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      two54 = 1.80143985094819840000e+16,  /* 43500000 00000000 */
168313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lg1 = 6.666666666666735130e-01,      /* 3FE55555 55555593 */
168413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lg2 = 3.999999999940941908e-01,      /* 3FD99999 9997FA04 */
168513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lg3 = 2.857142874366239149e-01,      /* 3FD24924 94229359 */
168613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lg4 = 2.222219843214978396e-01,      /* 3FCC71C5 1D8E78AF */
168713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lg5 = 1.818357216161805012e-01,      /* 3FC74664 96CB03DE */
168813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lg6 = 1.531383769920937332e-01,      /* 3FC39A09 D078C69F */
168913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lg7 = 1.479819860511658591e-01;      /* 3FC2F112 DF3E5244 */
169013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
169113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double zero = 0.0;
169213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static volatile double vzero = 0.0;
169313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
169413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double hfsq, f, s, z, R, w, t1, t2, dk;
169513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t k, hx, i, j;
169613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t lx;
169713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
169813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EXTRACT_WORDS(hx, lx, x);
169913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
170013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k = 0;
170113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx < 0x00100000) { /* x < 2**-1022  */
170213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (((hx & 0x7fffffff) | lx) == 0)
170313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return -two54 / vzero;           /* log(+-0)=-inf */
170413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx < 0) return (x - x) / zero; /* log(-#) = NaN */
170513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    k -= 54;
170613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    x *= two54; /* subnormal number, scale up x */
170713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    GET_HIGH_WORD(hx, x);
170813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
170913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx >= 0x7ff00000) return x + x;
171013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k += (hx >> 20) - 1023;
171113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hx &= 0x000fffff;
171213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i = (hx + 0x95f64) & 0x100000;
171313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
171413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k += (i >> 20);
171513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  f = x - 1.0;
171613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if ((0x000fffff & (2 + hx)) < 3) { /* -2**-20 <= f < 2**-20 */
171713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (f == zero) {
171813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (k == 0) {
171913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return zero;
172013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else {
172113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        dk = static_cast<double>(k);
172213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return dk * ln2_hi + dk * ln2_lo;
172313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
172413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
172513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    R = f * f * (0.5 - 0.33333333333333333 * f);
172613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k == 0) {
172713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return f - R;
172813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
172913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      dk = static_cast<double>(k);
173013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return dk * ln2_hi - ((R - dk * ln2_lo) - f);
173113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
173213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
173313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  s = f / (2.0 + f);
173413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  dk = static_cast<double>(k);
173513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = s * s;
173613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i = hx - 0x6147a;
173713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  w = z * z;
173813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  j = 0x6b851 - hx;
173913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
174013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
174113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i |= j;
174213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  R = t2 + t1;
174313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (i > 0) {
174413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    hfsq = 0.5 * f * f;
174513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k == 0)
174613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return f - (hfsq - s * (hfsq + R));
174713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    else
174813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
174913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
175013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k == 0)
175113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return f - s * (f - R);
175213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    else
175313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
175413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
175513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
175613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
175713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* double log1p(double x)
175813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
175913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method :
176013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   1. Argument Reduction: find k and f such that
176113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      1+x = 2^k * (1+f),
176213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     where  sqrt(2)/2 < 1+f < sqrt(2) .
176313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
176413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Note. If k=0, then f=x is exact. However, if k!=0, then f
176513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  may not be representable exactly. In that case, a correction
176613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  term is need. Let u=1+x rounded. Let c = (1+x)-u, then
176713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
176813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  and add back the correction term c/u.
176913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  (Note: when x > 2**53, one can simply return log(x))
177013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
177113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   2. Approximation of log1p(f).
177213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
177313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     = 2s + 2/3 s**3 + 2/5 s**5 + .....,
177413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         = 2s + s*R
177513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      We use a special Reme algorithm on [0,0.1716] to generate
177613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  a polynomial of degree 14 to approximate R The maximum error
177713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  of this polynomial approximation is bounded by 2**-58.45. In
177813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  other words,
177913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *            2      4      6      8      10      12      14
178013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
178113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    (the values of Lp1 to Lp7 are listed in the program)
178213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  and
178313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |      2          14          |     -58.45
178413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      | Lp1*s +...+Lp7*s    -  R(z) | <= 2
178513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |                             |
178613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
178713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  In order to guarantee error in log below 1ulp, we compute log
178813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  by
178913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    log1p(f) = f - (hfsq - s*(hfsq+R)).
179013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
179113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  3. Finally, log1p(x) = k*ln2 + log1p(f).
179213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *           = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
179313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     Here ln2 is split into two floating point number:
179413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      ln2_hi + ln2_lo,
179513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     where n*ln2_hi is always exact for |n| < 2000.
179613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
179713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
179813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  log1p(x) is NaN with signal if x < -1 (including -INF) ;
179913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  log1p(+INF) is +INF; log1p(-1) is -INF with signal;
180013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  log1p(NaN) is that NaN with no signal.
180113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
180213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Accuracy:
180313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  according to an error analysis, the error is always less than
180413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  1 ulp (unit in the last place).
180513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
180613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Constants:
180713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The hexadecimal values are the intended ones for the following
180813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * constants. The decimal values may be used, provided that the
180913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * compiler will convert from decimal to binary accurately enough
181013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * to produce the hexadecimal values shown.
181113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
181213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Note: Assuming log() return accurate answer, the following
181313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   algorithm can be used to compute log1p(x) to within a few ULP:
181413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
181513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    u = 1+x;
181613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    if(u==1.0) return x ; else
181713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         return log(u)*(x/(u-1.0));
181813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
181913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   See HP-15C Advanced Functions Handbook, p.193.
182013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
182113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble log1p(double x) {
182213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double                      /* -- */
182313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
182413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
182513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      two54 = 1.80143985094819840000e+16,  /* 43500000 00000000 */
182613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lp1 = 6.666666666666735130e-01,      /* 3FE55555 55555593 */
182713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lp2 = 3.999999999940941908e-01,      /* 3FD99999 9997FA04 */
182813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lp3 = 2.857142874366239149e-01,      /* 3FD24924 94229359 */
182913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lp4 = 2.222219843214978396e-01,      /* 3FCC71C5 1D8E78AF */
183013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lp5 = 1.818357216161805012e-01,      /* 3FC74664 96CB03DE */
183113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lp6 = 1.531383769920937332e-01,      /* 3FC39A09 D078C69F */
183213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Lp7 = 1.479819860511658591e-01;      /* 3FC2F112 DF3E5244 */
183313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
183413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double zero = 0.0;
183513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static volatile double vzero = 0.0;
183613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
183713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double hfsq, f, c, s, z, R, u;
183813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t k, hx, hu, ax;
183913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
184013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(hx, x);
184113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ax = hx & 0x7fffffff;
184213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
184313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k = 1;
184413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx < 0x3FDA827A) {    /* 1+x < sqrt(2)+ */
184513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (ax >= 0x3ff00000) { /* x <= -1.0 */
184613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (x == -1.0)
184713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return -two54 / vzero; /* log1p(-1)=+inf */
184813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      else
184913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return (x - x) / (x - x); /* log1p(x<-1)=NaN */
185013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
185113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (ax < 0x3e200000) {    /* |x| < 2**-29 */
185213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (two54 + x > zero    /* raise inexact */
185313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          && ax < 0x3c900000) /* |x| < 2**-54 */
185413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return x;
185513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      else
185613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return x - x * x * 0.5;
185713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
185813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx > 0 || hx <= static_cast<int32_t>(0xbfd2bec4)) {
185913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      k = 0;
186013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      f = x;
186113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      hu = 1;
186213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
186313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
186413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx >= 0x7ff00000) return x + x;
186513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (k != 0) {
186613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx < 0x43400000) {
186713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      STRICT_ASSIGN(double, u, 1.0 + x);
186813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      GET_HIGH_WORD(hu, u);
186913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      k = (hu >> 20) - 1023;
187013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      c = (k > 0) ? 1.0 - (u - x) : x - (u - 1.0); /* correction term */
187113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      c /= u;
187213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
187313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      u = x;
187413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      GET_HIGH_WORD(hu, u);
187513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      k = (hu >> 20) - 1023;
187613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      c = 0;
187713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
187813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    hu &= 0x000fffff;
187913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /*
188013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     * The approximation to sqrt(2) used in thresholds is not
188113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     * critical.  However, the ones used above must give less
188213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     * strict bounds than the one here so that the k==0 case is
188313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     * never reached from here, since here we have committed to
188413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     * using the correction term but don't use it if k==0.
188513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch     */
188613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hu < 0x6a09e) {                  /* u ~< sqrt(2) */
188713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      SET_HIGH_WORD(u, hu | 0x3ff00000); /* normalize u */
188813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
188913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      k += 1;
189013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      SET_HIGH_WORD(u, hu | 0x3fe00000); /* normalize u/2 */
189113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      hu = (0x00100000 - hu) >> 2;
189213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
189313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    f = u - 1.0;
189413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
189513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hfsq = 0.5 * f * f;
189613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hu == 0) { /* |f| < 2**-20 */
189713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (f == zero) {
189813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (k == 0) {
189913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return zero;
190013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else {
190113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        c += k * ln2_lo;
190213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return k * ln2_hi + c;
190313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
190413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
190513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    R = hfsq * (1.0 - 0.66666666666666666 * f);
190613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k == 0)
190713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return f - R;
190813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    else
190913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return k * ln2_hi - ((R - (k * ln2_lo + c)) - f);
191013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
191113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  s = f / (2.0 + f);
191213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = s * s;
191313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  R = z * (Lp1 +
191413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch           z * (Lp2 + z * (Lp3 + z * (Lp4 + z * (Lp5 + z * (Lp6 + z * Lp7))))));
191513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (k == 0)
191613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return f - (hfsq - s * (hfsq + R));
191713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  else
191813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return k * ln2_hi - ((hfsq - (s * (hfsq + R) + (k * ln2_lo + c))) - f);
191913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
192013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
192113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/*
192213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * k_log1p(f):
192313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)].
192413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
192513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The following describes the overall strategy for computing
192613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * logarithms in base e.  The argument reduction and adding the final
192713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * term of the polynomial are done by the caller for increased accuracy
192813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * when different bases are used.
192913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
193013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method :
193113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   1. Argument Reduction: find k and f such that
193213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         x = 2^k * (1+f),
193313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         where  sqrt(2)/2 < 1+f < sqrt(2) .
193413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
193513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   2. Approximation of log(1+f).
193613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
193713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *            = 2s + 2/3 s**3 + 2/5 s**5 + .....,
193813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *            = 2s + s*R
193913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      We use a special Reme algorithm on [0,0.1716] to generate
194013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      a polynomial of degree 14 to approximate R The maximum error
194113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      of this polynomial approximation is bounded by 2**-58.45. In
194213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      other words,
194313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          2      4      6      8      10      12      14
194413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
194513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      (the values of Lg1 to Lg7 are listed in the program)
194613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      and
194713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          |      2          14          |     -58.45
194813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          | Lg1*s +...+Lg7*s    -  R(z) | <= 2
194913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          |                             |
195013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
195113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      In order to guarantee error in log below 1ulp, we compute log
195213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      by
195313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          log(1+f) = f - s*(f - R)            (if f is not too large)
195413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
195513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
195613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   3. Finally,  log(x) = k*ln2 + log(1+f).
195713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
195813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Here ln2 is split into two floating point number:
195913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          ln2_hi + ln2_lo,
196013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      where n*ln2_hi is always exact for |n| < 2000.
196113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
196213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
196313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      log(x) is NaN with signal if x < 0 (including -INF) ;
196413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      log(+INF) is +INF; log(0) is -INF with signal;
196513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      log(NaN) is that NaN with no signal.
196613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
196713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Accuracy:
196813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      according to an error analysis, the error is always less than
196913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      1 ulp (unit in the last place).
197013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
197113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Constants:
197213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The hexadecimal values are the intended ones for the following
197313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * constants. The decimal values may be used, provided that the
197413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * compiler will convert from decimal to binary accurately enough
197513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * to produce the hexadecimal values shown.
197613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
197713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
197813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic const double Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
197913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Lg2 = 3.999999999940941908e-01,                 /* 3FD99999 9997FA04 */
198013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Lg3 = 2.857142874366239149e-01,                 /* 3FD24924 94229359 */
198113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Lg4 = 2.222219843214978396e-01,                 /* 3FCC71C5 1D8E78AF */
198213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Lg5 = 1.818357216161805012e-01,                 /* 3FC74664 96CB03DE */
198313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Lg6 = 1.531383769920937332e-01,                 /* 3FC39A09 D078C69F */
198413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Lg7 = 1.479819860511658591e-01;                 /* 3FC2F112 DF3E5244 */
198513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
198613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/*
198713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * We always inline k_log1p(), since doing so produces a
198813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * substantial performance improvement (~40% on amd64).
198913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
199013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic inline double k_log1p(double f) {
199113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double hfsq, s, z, R, w, t1, t2;
199213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
199313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  s = f / (2.0 + f);
199413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  z = s * s;
199513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  w = z * z;
199613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
199713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
199813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  R = t2 + t1;
199913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hfsq = 0.5 * f * f;
200013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return s * (hfsq + R);
200113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
200213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
200313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/*
200413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Return the base 2 logarithm of x.  See e_log.c and k_log.h for most
200513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * comments.
200613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
200713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel,
200813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * then does the combining and scaling steps
200913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    log2(x) = (f - 0.5*f*f + k_log1p(f)) / ln2 + k
201013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * in not-quite-routine extra precision.
201113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
201213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble log2(double x) {
201313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
201413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      two54 = 1.80143985094819840000e+16,   /* 0x43500000, 0x00000000 */
201513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */
201613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */
201713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
201813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double zero = 0.0;
201913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static volatile double vzero = 0.0;
202013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
202113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double f, hfsq, hi, lo, r, val_hi, val_lo, w, y;
202213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t i, k, hx;
202313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t lx;
202413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
202513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EXTRACT_WORDS(hx, lx, x);
202613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
202713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k = 0;
202813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx < 0x00100000) { /* x < 2**-1022  */
202913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (((hx & 0x7fffffff) | lx) == 0)
203013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return -two54 / vzero;           /* log(+-0)=-inf */
203113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx < 0) return (x - x) / zero; /* log(-#) = NaN */
203213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    k -= 54;
203313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    x *= two54; /* subnormal number, scale up x */
203413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    GET_HIGH_WORD(hx, x);
203513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
203613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx >= 0x7ff00000) return x + x;
203713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx == 0x3ff00000 && lx == 0) return zero; /* log(1) = +0 */
203813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k += (hx >> 20) - 1023;
203913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hx &= 0x000fffff;
204013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i = (hx + 0x95f64) & 0x100000;
204113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
204213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k += (i >> 20);
204313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  y = static_cast<double>(k);
204413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  f = x - 1.0;
204513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hfsq = 0.5 * f * f;
204613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r = k_log1p(f);
204713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
204813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /*
204913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * f-hfsq must (for args near 1) be evaluated in extra precision
205013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * to avoid a large cancellation when x is near sqrt(2) or 1/sqrt(2).
205113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * This is fairly efficient since f-hfsq only depends on f, so can
205213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * be evaluated in parallel with R.  Not combining hfsq with R also
205313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * keeps R small (though not as small as a true `lo' term would be),
205413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * so that extra precision is not needed for terms involving R.
205513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   *
205613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * Compiler bugs involving extra precision used to break Dekker's
205713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * theorem for spitting f-hfsq as hi+lo, unless double_t was used
205813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * or the multi-precision calculations were avoided when double_t
205913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * has extra precision.  These problems are now automatically
206013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * avoided as a side effect of the optimization of combining the
206113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * Dekker splitting step with the clear-low-bits step.
206213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   *
206313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * y must (for args near sqrt(2) and 1/sqrt(2)) be added in extra
206413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * precision to avoid a very large cancellation when x is very near
206513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * these values.  Unlike the above cancellations, this problem is
206613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * specific to base 2.  It is strange that adding +-1 is so much
206713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * harder than adding +-ln2 or +-log10_2.
206813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   *
206913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * This uses Dekker's theorem to normalize y+val_hi, so the
207013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * compiler bugs are back in some configurations, sigh.  And I
207113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * don't want to used double_t to avoid them, since that gives a
207213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * pessimization and the support for avoiding the pessimization
207313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * is not yet available.
207413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   *
207513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * The multi-precision calculations for the multiplications are
207613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * routine.
207713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
207813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hi = f - hfsq;
207913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SET_LOW_WORD(hi, 0);
208013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  lo = (f - hi) - hfsq + r;
208113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  val_hi = hi * ivln2hi;
208213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  val_lo = (lo + hi) * ivln2lo + lo * ivln2hi;
208313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
208413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* spadd(val_hi, val_lo, y), except for not using double_t: */
208513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  w = y + val_hi;
208613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  val_lo += (y - w) + val_hi;
208713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  val_hi = w;
208813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
208913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return val_lo + val_hi;
209013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
209113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
209213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/*
209313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Return the base 10 logarithm of x
209413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
209513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method :
209613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Let log10_2hi = leading 40 bits of log10(2) and
209713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          log10_2lo = log10(2) - log10_2hi,
209813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          ivln10   = 1/log(10) rounded.
209913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Then
210013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              n = ilogb(x),
210113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              if(n<0)  n = n+1;
210213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              x = scalbn(x,-n);
210313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *              log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
210413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
210513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Note 1:
210613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     To guarantee log10(10**n)=n, where 10**n is normal, the rounding
210713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     mode must set to Round-to-Nearest.
210813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Note 2:
210913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [1/log(10)] rounded to 53 bits has error .198 ulps;
211013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      log10 is monotonic at all binary break points.
211113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
211213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Special cases:
211313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      log10(x) is NaN if x < 0;
211413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      log10(+INF) is +INF; log10(0) is -INF;
211513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      log10(NaN) is that NaN;
211613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      log10(10**N) = N  for N=0,1,...,22.
211713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
211813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble log10(double x) {
211913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
212013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
212113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ivln10 = 4.34294481903251816668e-01,
212213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
212313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
212413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
212513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double zero = 0.0;
212613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static volatile double vzero = 0.0;
212713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
212813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double y;
212913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t i, k, hx;
213013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t lx;
213113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
213213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EXTRACT_WORDS(hx, lx, x);
213313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
213413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k = 0;
213513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx < 0x00100000) { /* x < 2**-1022  */
213613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (((hx & 0x7fffffff) | lx) == 0)
213713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return -two54 / vzero;           /* log(+-0)=-inf */
213813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx < 0) return (x - x) / zero; /* log(-#) = NaN */
213913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    k -= 54;
214013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    x *= two54; /* subnormal number, scale up x */
214113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    GET_HIGH_WORD(hx, x);
214213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    GET_LOW_WORD(lx, x);
214313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
214413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx >= 0x7ff00000) return x + x;
214513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx == 0x3ff00000 && lx == 0) return zero; /* log(1) = +0 */
214613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  k += (hx >> 20) - 1023;
214713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
214813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i = (k & 0x80000000) >> 31;
214913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hx = (hx & 0x000fffff) | ((0x3ff - i) << 20);
215013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  y = k + i;
215113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SET_HIGH_WORD(x, hx);
215213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SET_LOW_WORD(x, lx);
215313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
215413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double z = y * log10_2lo + ivln10 * log(x);
215513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return z + y * log10_2hi;
215613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
215713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
215813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* expm1(x)
215913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Returns exp(x)-1, the exponential of x minus 1.
216013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
216113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method
216213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   1. Argument reduction:
216313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Given x, find r and integer k such that
216413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
216513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *               x = k*ln2 + r,  |r| <= 0.5*ln2 ~ 0.34658
216613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
216713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Here a correction term c will be computed to compensate
216813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  the error in r when rounded to a floating-point number.
216913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
217013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   2. Approximating expm1(r) by a special rational function on
217113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  the interval [0,0.34658]:
217213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Since
217313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
217413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  we define R1(r*r) by
217513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
217613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  That is,
217713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
217813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
217913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
218013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      We use a special Reme algorithm on [0,0.347] to generate
218113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   a polynomial of degree 5 in r*r to approximate R1. The
218213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  maximum error of this polynomial approximation is bounded
218313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  by 2**-61. In other words,
218413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
218513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  where   Q1  =  -1.6666666666666567384E-2,
218613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     Q2  =   3.9682539681370365873E-4,
218713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     Q3  =  -9.9206344733435987357E-6,
218813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     Q4  =   2.5051361420808517002E-7,
218913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     Q5  =  -6.2843505682382617102E-9;
219013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    z   =  r*r,
219113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  with error bounded by
219213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |                  5           |     -61
219313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      | 1.0+Q1*z+...+Q5*z   -  R1(z) | <= 2
219413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      |                              |
219513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
219613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  expm1(r) = exp(r)-1 is then computed by the following
219713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   specific way which minimize the accumulation rounding error:
219813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *             2     3
219913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *            r     r    [ 3 - (R1 + R1*r/2)  ]
220013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *        expm1(r) = r + --- + --- * [--------------------]
220113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                  2     2    [ 6 - r*(3 - R1*r/2) ]
220213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
220313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  To compensate the error in the argument reduction, we use
220413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    expm1(r+c) = expm1(r) + c + expm1(r)*c
220513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *         ~ expm1(r) + c + r*c
220613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  Thus c+r*c will be added in as the correction terms for
220713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  expm1(r+c). Now rearrange the term to avoid optimization
220813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   screw up:
220913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *            (      2                                    2 )
221013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *            ({  ( r    [ R1 -  (3 - R1*r/2) ]  )  }    r  )
221113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
221213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                  ({  ( 2    [ 6 - r*(3 - R1*r/2) ]  )  }    2  )
221313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                      (                                             )
221413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
221513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *       = r - E
221613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   3. Scale back to obtain expm1(x):
221713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  From step 1, we have
221813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     expm1(x) = either 2^k*[expm1(r)+1] - 1
221913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *        = or     2^k*[expm1(r) + (1-2^-k)]
222013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *   4. Implementation notes:
222113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  (A). To save one multiplication, we scale the coefficient Qi
222213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *       to Qi*2^i, and replace z by (x^2)/2.
222313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  (B). To achieve maximum accuracy, we compute expm1(x) by
222413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    (i)   if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
222513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    (ii)  if k=0, return r-E
222613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    (iii) if k=-1, return 0.5*(r-E)-0.5
222713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *        (iv)  if k=1 if r < -0.25, return 2*((r+0.5)- E)
222813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *                  else       return  1.0+2.0*(r-E);
222913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    (v)   if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
223013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    (vi)  if k <= 20, return 2^k((1-2^-k)-(E-r)), else
223113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *    (vii) return 2^k(1-((E+2^-k)-r))
223213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
223313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
223413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  expm1(INF) is INF, expm1(NaN) is NaN;
223513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  expm1(-INF) is -1, and
223613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  for finite argument, only expm1(0)=0 is exact.
223713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
223813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Accuracy:
223913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  according to an error analysis, the error is always less than
224013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  1 ulp (unit in the last place).
224113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
224213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Misc. info.
224313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *  For IEEE double
224413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      if x >  7.09782712893383973096e+02 then expm1(x) overflow
224513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
224613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Constants:
224713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * The hexadecimal values are the intended ones for the following
224813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * constants. The decimal values may be used, provided that the
224913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * compiler will convert from decimal to binary accurately enough
225013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * to produce the hexadecimal values shown.
225113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
225213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble expm1(double x) {
225313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double
225413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      one = 1.0,
225513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      tiny = 1.0e-300,
225613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
225713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ln2_hi = 6.93147180369123816490e-01,      /* 0x3fe62e42, 0xfee00000 */
225813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ln2_lo = 1.90821492927058770002e-10,      /* 0x3dea39ef, 0x35793c76 */
225913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      invln2 = 1.44269504088896338700e+00,      /* 0x3ff71547, 0x652b82fe */
226013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      /* Scaled Q's: Qn_here = 2**n * Qn_above, for R(2*z) where z = hxs =
226113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch         x*x/2: */
226213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */
226313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Q2 = 1.58730158725481460165e-03,  /* 3F5A01A0 19FE5585 */
226413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
226513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Q4 = 4.00821782732936239552e-06,  /* 3ED0CFCA 86E65239 */
226613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
226713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
226813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static volatile double huge = 1.0e+300;
226913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
227013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double y, hi, lo, c, t, e, hxs, hfx, r1, twopk;
227113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t k, xsb;
227213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t hx;
227313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
227413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(hx, x);
227513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  xsb = hx & 0x80000000; /* sign bit of x */
227613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hx &= 0x7fffffff;      /* high word of |x| */
227713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
227813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* filter out huge and non-finite argument */
227913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx >= 0x4043687A) {   /* if |x|>=56*ln2 */
228013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx >= 0x40862E42) { /* if |x|>=709.78... */
228113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (hx >= 0x7ff00000) {
228213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        uint32_t low;
228313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        GET_LOW_WORD(low, x);
228413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        if (((hx & 0xfffff) | low) != 0)
228513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return x + x; /* NaN */
228613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        else
228713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          return (xsb == 0) ? x : -1.0; /* exp(+-inf)={inf,-1} */
228813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
228913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (x > o_threshold) return huge * huge; /* overflow */
229013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
229113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (xsb != 0) {        /* x < -56*ln2, return -1.0 with inexact */
229213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (x + tiny < 0.0)  /* raise inexact */
229313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return tiny - one; /* return -1 */
229413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
229513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
229613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
229713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* argument reduction */
229813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx > 0x3fd62e42) {   /* if  |x| > 0.5 ln2 */
229913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
230013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (xsb == 0) {
230113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        hi = x - ln2_hi;
230213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        lo = ln2_lo;
230313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        k = 1;
230413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else {
230513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        hi = x + ln2_hi;
230613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        lo = -ln2_lo;
230713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        k = -1;
230813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
230913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
231013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      k = invln2 * x + ((xsb == 0) ? 0.5 : -0.5);
231113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      t = k;
231213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      hi = x - t * ln2_hi; /* t*ln2_hi is exact here */
231313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      lo = t * ln2_lo;
231413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
231513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    STRICT_ASSIGN(double, x, hi - lo);
231613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    c = (hi - x) - lo;
231713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (hx < 0x3c900000) { /* when |x|<2**-54, return x */
231813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    t = huge + x;               /* return x with inexact flags when x!=0 */
231913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x - (t - (huge + x));
232013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
232113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    k = 0;
232213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
232313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
232413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* x is now in primary range */
232513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hfx = 0.5 * x;
232613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hxs = x * hfx;
232713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r1 = one + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5))));
232813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t = 3.0 - r1 * hfx;
232913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  e = hxs * ((r1 - t) / (6.0 - x * t));
233013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (k == 0) {
233113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x - (x * e - hxs); /* c is 0 */
233213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
233313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    INSERT_WORDS(twopk, 0x3ff00000 + (k << 20), 0); /* 2^k */
233413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    e = (x * (e - c) - c);
233513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    e -= hxs;
233613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k == -1) return 0.5 * (x - e) - 0.5;
233713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k == 1) {
233813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (x < -0.25)
233913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return -2.0 * (e - (x + 0.5));
234013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      else
234113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return one + 2.0 * (x - e);
234213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
234313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k <= -2 || k > 56) { /* suffice to return exp(x)-1 */
234413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y = one - (e - x);
234513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // TODO(mvstanton): is this replacement for the hex float
234613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // sufficient?
234713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // if (k == 1024) y = y*2.0*0x1p1023;
234813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (k == 1024)
234913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y = y * 2.0 * 8.98846567431158e+307;
235013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      else
235113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        y = y * twopk;
235213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return y - one;
235313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
235413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    t = one;
235513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (k < 20) {
235613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      SET_HIGH_WORD(t, 0x3ff00000 - (0x200000 >> k)); /* t=1-2^-k */
235713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y = t - (e - x);
235813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y = y * twopk;
235913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
236013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      SET_HIGH_WORD(t, ((0x3ff - k) << 20)); /* 2^-k */
236113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y = x - (e + t);
236213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y += one;
236313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      y = y * twopk;
236413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
236513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
236613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return y;
236713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
236813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
236913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble cbrt(double x) {
237013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const uint32_t
237113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      B1 = 715094163, /* B1 = (1023-1023/3-0.03306235651)*2**20 */
237213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      B2 = 696219795; /* B2 = (1023-1023/3-54/3-0.03306235651)*2**20 */
237313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
237413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* |1/cbrt(x) - p(x)| < 2**-23.5 (~[-7.93e-8, 7.929e-8]). */
237513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const double P0 = 1.87595182427177009643, /* 0x3ffe03e6, 0x0f61e692 */
237613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P1 = -1.88497979543377169875,                /* 0xbffe28e0, 0x92f02420 */
237713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P2 = 1.621429720105354466140,                /* 0x3ff9f160, 0x4a49d6c2 */
237813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P3 = -0.758397934778766047437,               /* 0xbfe844cb, 0xbee751d9 */
237913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      P4 = 0.145996192886612446982;                /* 0x3fc2b000, 0xd4e4edd7 */
238013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
238113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t hx;
238213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  union {
238313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    double value;
238413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint64_t bits;
238513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } u;
238613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double r, s, t = 0.0, w;
238713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t sign;
238813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t high, low;
238913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
239013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EXTRACT_WORDS(hx, low, x);
239113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  sign = hx & 0x80000000; /* sign= sign(x) */
239213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  hx ^= sign;
239313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx >= 0x7ff00000) return (x + x); /* cbrt(NaN,INF) is itself */
239413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
239513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /*
239613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * Rough cbrt to 5 bits:
239713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   *    cbrt(2**e*(1+m) ~= 2**(e/3)*(1+(e%3+m)/3)
239813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * where e is integral and >= 0, m is real and in [0, 1), and "/" and
239913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * "%" are integer division and modulus with rounding towards minus
240013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * infinity.  The RHS is always >= the LHS and has a maximum relative
240113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * error of about 1 in 16.  Adding a bias of -0.03306235651 to the
240213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * (e%3+m)/3 term reduces the error to about 1 in 32. With the IEEE
240313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * floating point representation, for finite positive normal values,
240413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * ordinary integer divison of the value in bits magically gives
240513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * almost exactly the RHS of the above provided we first subtract the
240613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * exponent bias (1023 for doubles) and later add it back.  We do the
240713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * subtraction virtually to keep e >= 0 so that ordinary integer
240813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * division rounds towards minus infinity; this is also efficient.
240913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
241013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (hx < 0x00100000) {             /* zero or subnormal? */
241113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if ((hx | low) == 0) return (x); /* cbrt(0) is itself */
241213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SET_HIGH_WORD(t, 0x43500000);    /* set t= 2**54 */
241313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    t *= x;
241413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    GET_HIGH_WORD(high, t);
241513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    INSERT_WORDS(t, sign | ((high & 0x7fffffff) / 3 + B2), 0);
241613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
241713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    INSERT_WORDS(t, sign | (hx / 3 + B1), 0);
241813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
241913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
242013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /*
242113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * New cbrt to 23 bits:
242213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   *    cbrt(x) = t*cbrt(x/t**3) ~= t*P(t**3/x)
242313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * where P(r) is a polynomial of degree 4 that approximates 1/cbrt(r)
242413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * to within 2**-23.5 when |r - 1| < 1/10.  The rough approximation
242513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * has produced t such than |t/cbrt(x) - 1| ~< 1/32, and cubing this
242613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * gives us bounds for r = t**3/x.
242713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   *
242813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * Try to optimize for parallel evaluation as in k_tanf.c.
242913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
243013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r = (t * t) * (t / x);
243113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t = t * ((P0 + r * (P1 + r * P2)) + ((r * r) * r) * (P3 + r * P4));
243213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
243313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /*
243413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * Round t away from zero to 23 bits (sloppily except for ensuring that
243513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * the result is larger in magnitude than cbrt(x) but not much more than
243613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * 2 23-bit ulps larger).  With rounding towards zero, the error bound
243713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * would be ~5/6 instead of ~4/6.  With a maximum error of 2 23-bit ulps
243813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * in the rounded t, the infinite-precision error in the Newton
243913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * approximation barely affects third digit in the final error
244013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * 0.667; the error in the rounded t can be up to about 3 23-bit ulps
244113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   * before the final error is larger than 0.667 ulps.
244213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch   */
244313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  u.value = t;
244413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  u.bits = (u.bits + 0x80000000) & 0xffffffffc0000000ULL;
244513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t = u.value;
244613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
244713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* one step Newton iteration to 53 bits with error < 0.667 ulps */
244813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  s = t * t;             /* t*t is exact */
244913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r = x / s;             /* error <= 0.5 ulps; |r| < |t| */
245013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  w = t + t;             /* t+t is exact */
245113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  r = (r - t) / (w + r); /* r-t is exact; w+r ~= 3*t */
245213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  t = t + t * r;         /* error <= 0.5 + 0.5/3 + epsilon */
245313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
245413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return (t);
245513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
245613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
245713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* sin(x)
245813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Return sine function of x.
245913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
246013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * kernel function:
246113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      __kernel_sin            ... sine function on [-pi/4,pi/4]
246213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      __kernel_cos            ... cose function on [-pi/4,pi/4]
246313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      __ieee754_rem_pio2      ... argument reduction routine
246413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
246513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method.
246613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Let S,C and T denote the sin, cos and tan respectively on
246713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
246813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      in [-pi/4 , +pi/4], and let n = k mod 4.
246913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      We have
247013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
247113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          n        sin(x)      cos(x)        tan(x)
247213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     ----------------------------------------------------------
247313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          0          S           C             T
247413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          1          C          -S            -1/T
247513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          2         -S          -C             T
247613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          3         -C           S            -1/T
247713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     ----------------------------------------------------------
247813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
247913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
248013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Let trig be any of sin, cos, or tan.
248113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      trig(+-INF)  is NaN, with signals;
248213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      trig(NaN)    is that NaN;
248313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
248413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Accuracy:
248513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      TRIG(x) returns trig(x) nearly rounded
248613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
248713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble sin(double x) {
248813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double y[2], z = 0.0;
248913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t n, ix;
249013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
249113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* High word of x. */
249213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(ix, x);
249313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
249413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* |x| ~< pi/4 */
249513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix &= 0x7fffffff;
249613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix <= 0x3fe921fb) {
249713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return __kernel_sin(x, z, 0);
249813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (ix >= 0x7ff00000) {
249913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /* sin(Inf or NaN) is NaN */
250013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x - x;
250113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
250213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /* argument reduction needed */
250313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    n = __ieee754_rem_pio2(x, y);
250413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    switch (n & 3) {
250513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 0:
250613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return __kernel_sin(y[0], y[1], 1);
250713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 1:
250813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return __kernel_cos(y[0], y[1]);
250913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case 2:
251013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return -__kernel_sin(y[0], y[1], 1);
251113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      default:
251213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        return -__kernel_cos(y[0], y[1]);
251313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
251413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
251513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
251613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
251713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch/* tan(x)
251813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Return tangent function of x.
251913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
252013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * kernel function:
252113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      __kernel_tan            ... tangent function on [-pi/4,pi/4]
252213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      __ieee754_rem_pio2      ... argument reduction routine
252313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
252413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Method.
252513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Let S,C and T denote the sin, cos and tan respectively on
252613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
252713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      in [-pi/4 , +pi/4], and let n = k mod 4.
252813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      We have
252913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
253013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          n        sin(x)      cos(x)        tan(x)
253113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     ----------------------------------------------------------
253213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          0          S           C             T
253313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          1          C          -S            -1/T
253413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          2         -S          -C             T
253513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *          3         -C           S            -1/T
253613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *     ----------------------------------------------------------
253713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
253813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Special cases:
253913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      Let trig be any of sin, cos, or tan.
254013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      trig(+-INF)  is NaN, with signals;
254113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      trig(NaN)    is that NaN;
254213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *
254313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch * Accuracy:
254413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *      TRIG(x) returns trig(x) nearly rounded
254513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch */
254613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochdouble tan(double x) {
254713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  double y[2], z = 0.0;
254813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int32_t n, ix;
254913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
255013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* High word of x. */
255113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  GET_HIGH_WORD(ix, x);
255213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
255313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  /* |x| ~< pi/4 */
255413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ix &= 0x7fffffff;
255513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (ix <= 0x3fe921fb) {
255613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return __kernel_tan(x, z, 1);
255713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (ix >= 0x7ff00000) {
255813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /* tan(Inf or NaN) is NaN */
255913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return x - x; /* NaN */
256013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
256113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /* argument reduction needed */
256213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    n = __ieee754_rem_pio2(x, y);
256313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    /* 1 -> n even, -1 -> n odd */
256413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return __kernel_tan(y[0], y[1], 1 - ((n & 1) << 1));
256513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
256613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
256713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch/*
2569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * ES6 draft 09-27-13, section 20.2.2.12.
2570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Math.cosh
2571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Method :
2572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
2573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      1. Replace x by |x| (cosh(x) = cosh(-x)).
2574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      2.
2575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                                      [ exp(x) - 1 ]^2
2576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          0        <= x <= ln2/2  :  cosh(x) := 1 + -------------------
2577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                                         2*exp(x)
2578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
2579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                                 exp(x) + 1/exp(x)
2580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          ln2/2    <= x <= 22     :  cosh(x) := -------------------
2581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                                        2
2582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          22       <= x <= lnovft :  cosh(x) := exp(x)/2
2583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          lnovft   <= x <= ln2ovft:  cosh(x) := exp(x/2)/2 * exp(x/2)
2584f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          ln2ovft  <  x           :  cosh(x) := huge*huge (overflow)
2585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
2586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Special cases:
2587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      cosh(x) is |x| if x is +INF, -INF, or NaN.
2588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      only cosh(0)=1 is exact for finite x.
2589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch */
2590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdouble cosh(double x) {
2591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double KCOSH_OVERFLOW = 710.4758600739439;
2592f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double one = 1.0, half = 0.5;
2593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static volatile double huge = 1.0e+300;
2594f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int32_t ix;
2596f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  /* High word of |x|. */
2598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  GET_HIGH_WORD(ix, x);
2599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ix &= 0x7fffffff;
2600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|))
2602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix < 0x3fd62e43) {
2603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    double t = expm1(fabs(x));
2604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    double w = one + t;
2605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // For |x| < 2^-55, cosh(x) = 1
2606f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (ix < 0x3c800000) return w;
2607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return one + (t * t) / (w + w);
2608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2610f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2
2611f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix < 0x40360000) {
2612f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    double t = exp(fabs(x));
2613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return half * t + half / t;
2614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2615f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2616f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| in [22, log(maxdouble)], return half*exp(|x|)
2617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix < 0x40862e42) return half * exp(fabs(x));
2618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2619f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| in [log(maxdouble), overflowthreshold]
2620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (fabs(x) <= KCOSH_OVERFLOW) {
2621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    double w = exp(half * fabs(x));
2622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    double t = half * w;
2623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return t * w;
2624f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  /* x is INF or NaN */
2627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix >= 0x7ff00000) return x * x;
2628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| > overflowthreshold.
2630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return huge * huge;
2631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2632f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2633f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch/*
2634f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * ES6 draft 09-27-13, section 20.2.2.30.
2635f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Math.sinh
2636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Method :
2637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
2638f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      1. Replace x by |x| (sinh(-x) = -sinh(x)).
2639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      2.
2640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                                  E + E/(E+1)
2641f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          0        <= x <= 22     :  sinh(x) := --------------, E=expm1(x)
2642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                                      2
2643f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
2644f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          22       <= x <= lnovft :  sinh(x) := exp(x)/2
2645f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          lnovft   <= x <= ln2ovft:  sinh(x) := exp(x/2)/2 * exp(x/2)
2646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *          ln2ovft  <  x           :  sinh(x) := x*shuge (overflow)
2647f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
2648f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Special cases:
2649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      sinh(x) is |x| if x is +Infinity, -Infinity, or NaN.
2650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      only sinh(0)=0 is exact for finite x.
2651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch */
2652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdouble sinh(double x) {
2653f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double KSINH_OVERFLOW = 710.4758600739439,
2654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                      TWO_M28 =
2655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                          3.725290298461914e-9,  // 2^-28, empty lower half
2656f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      LOG_MAXD = 709.7822265625;  // 0x40862e42 00000000, empty lower half
2657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double shuge = 1.0e307;
2658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2659f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double h = (x < 0) ? -0.5 : 0.5;
2660f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1))
2661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double ax = fabs(x);
2662f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ax < 22) {
2663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // For |x| < 2^-28, sinh(x) = x
2664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (ax < TWO_M28) return x;
2665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    double t = expm1(ax);
2666f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (ax < 1) {
2667f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return h * (2 * t - t * t / (t + 1));
2668f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
2669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return h * (t + t / (t + 1));
2670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2671f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|)
2672f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ax < LOG_MAXD) return h * exp(ax);
2673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| in [log(maxdouble), overflowthreshold]
2674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // overflowthreshold = 710.4758600739426
2675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ax <= KSINH_OVERFLOW) {
2676f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    double w = exp(0.5 * ax);
2677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    double t = h * w;
2678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return t * w;
2679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // |x| > overflowthreshold or is NaN.
2681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Return Infinity of the appropriate sign or NaN.
2682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return x * shuge;
2683f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch/* Tanh(x)
2686f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Return the Hyperbolic Tangent of x
2687f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
2688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Method :
2689f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                 x    -x
2690f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                e  - e
2691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *  0. tanh(x) is defined to be -----------
2692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                 x    -x
2693f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                e  + e
2694f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *  1. reduce x to non-negative by tanh(-x) = -tanh(x).
2695f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *  2.  0      <= x <  2**-28 : tanh(x) := x with inexact if x != 0
2696f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                          -t
2697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      2**-28 <= x <  1      : tanh(x) := -----; t = expm1(-2x)
2698f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                         t + 2
2699f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                               2
2700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      1      <= x <  22     : tanh(x) := 1 - -----; t = expm1(2x)
2701f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *                                             t + 2
2702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      22     <= x <= INF    : tanh(x) := 1.
2703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *
2704f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch * Special cases:
2705f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      tanh(NaN) is NaN;
2706f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *      only tanh(0)=0 is exact for finite argument.
2707f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch */
2708f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdouble tanh(double x) {
2709f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const volatile double tiny = 1.0e-300;
2710f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static const double one = 1.0, two = 2.0, huge = 1.0e300;
2711f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double t, z;
2712f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int32_t jx, ix;
2713f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2714f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  GET_HIGH_WORD(jx, x);
2715f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ix = jx & 0x7fffffff;
2716f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2717f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  /* x is INF or NaN */
2718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix >= 0x7ff00000) {
2719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (jx >= 0)
2720f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return one / x + one; /* tanh(+-inf)=+-1 */
2721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    else
2722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return one / x - one; /* tanh(NaN) = NaN */
2723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  /* |x| < 22 */
2726f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (ix < 0x40360000) {            /* |x|<22 */
2727f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (ix < 0x3e300000) {          /* |x|<2**-28 */
2728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (huge + x > one) return x; /* tanh(tiny) = tiny with inexact */
2729f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
2730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (ix >= 0x3ff00000) { /* |x|>=1  */
2731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      t = expm1(two * fabs(x));
2732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      z = one - two / (t + two);
2733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
2734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      t = expm1(-two * fabs(x));
2735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      z = -t / (t + two);
2736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
2737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    /* |x| >= 22, return +-1 */
2738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
2739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    z = one - tiny; /* raise inexact flag */
2740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return (jx >= 0) ? z : -z;
2742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
274413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}  // namespace ieee754
274513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}  // namespace base
274613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}  // namespace v8
2747