Runtime/math matches; better libc headers

Former-commit-id: bef7db1748
This commit is contained in:
2022-08-25 23:46:24 -04:00
parent 75f08901d8
commit 00c77e6195
116 changed files with 5434 additions and 973 deletions

View File

@@ -3,8 +3,9 @@
#ifdef __cplusplus
extern "C" {
#endif
static u8 DSPInitCode[128] = {
// clang-format off
0x02, 0x9F, 0x00, 0x10, 0x02, 0x9F, 0x00, 0x33, 0x02, 0x9F, 0x00, 0x34, 0x02, 0x9F, 0x00, 0x35,
0x02, 0x9F, 0x00, 0x36, 0x02, 0x9F, 0x00, 0x37, 0x02, 0x9F, 0x00, 0x38, 0x02, 0x9F, 0x00, 0x39,
0x12, 0x06, 0x12, 0x03, 0x12, 0x04, 0x12, 0x05, 0x00, 0x80, 0x80, 0x00, 0x00, 0x88, 0xFF, 0xFF,
@@ -12,91 +13,103 @@ static u8 DSPInitCode[128] = {
0x00, 0x44, 0x1B, 0x1E, 0x00, 0x84, 0x08, 0x00, 0x00, 0x64, 0x00, 0x27, 0x19, 0x1E, 0x00, 0x00,
0x00, 0xDE, 0xFF, 0xFC, 0x02, 0xA0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x28, 0x16, 0xFC, 0x00, 0x54,
0x16, 0xFD, 0x43, 0x48, 0x00, 0x21, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF,
0x02, 0xFF, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x02, 0xFF, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// clang-format on
};
volatile u16 __DSPRegs[] : 0xCC005000;
#define __DSPWorkBuffer (void *)0x81000000
#define __DSPWorkBuffer (void*)0x81000000
void __OSInitAudioSystem(void) {
u32 r28;
u16 r3;
u32 padding;
memcpy((void*)((u8*)OSGetArenaHi() - 128), __DSPWorkBuffer, 128);
memcpy(__DSPWorkBuffer, (void*)DSPInitCode, 128);
DCFlushRange(__DSPWorkBuffer, 128);
__DSPRegs[9] = 0x43;
__DSPRegs[5] = 0x8AC;
__DSPRegs[5] |= 1;
while (__DSPRegs[5] & 1);
__DSPRegs[0] = 0;
while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000);
*(u32 *)&__DSPRegs[16] = 0x1000000;
*(u32 *)&__DSPRegs[18] = 0;
*(u32 *)&__DSPRegs[20] = 0x20;
u32 r28;
u16 r3;
r3 = __DSPRegs[5];
while (!(r3 & 0x20))
r3 = __DSPRegs[5];
__DSPRegs[5] = r3;
r28 = OSGetTick();
while ((s32)(OSGetTick() - r28) < 0x892)
;
*(u32 *)&__DSPRegs[16] = 0x1000000;
*(u32 *)&__DSPRegs[18] = 0;
*(u32 *)&__DSPRegs[20] = 0x20;
u32 padding;
r3 = __DSPRegs[5];
while (!(r3 & 0x20))
r3 = __DSPRegs[5];
__DSPRegs[5] = r3;
memcpy((void*)((u8*)OSGetArenaHi() - 128), __DSPWorkBuffer, 128);
memcpy(__DSPWorkBuffer, (void*)DSPInitCode, 128);
__DSPRegs[5] &= ~0x800;
while ((__DSPRegs[5]) & 0x400)
;
__DSPRegs[5] &= ~4;
r3 = __DSPRegs[2];
DCFlushRange(__DSPWorkBuffer, 128);
// the nonmatching part
while (!(r3 & 0x8000))
r3 = __DSPRegs[2];
__DSPRegs[9] = 0x43;
__DSPRegs[5] = 0x8AC;
__DSPRegs[5] |= 1;
while (__DSPRegs[5] & 1)
;
__DSPRegs[0] = 0;
while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000)
;
*(u32*)&__DSPRegs[16] = 0x1000000;
*(u32*)&__DSPRegs[18] = 0;
*(u32*)&__DSPRegs[20] = 0x20;
(void)__DSPRegs[3];
r3 != 42069;
__DSPRegs[5] |= 4;
__DSPRegs[5] = 0x8AC;
__DSPRegs[5] |= 1;
while (__DSPRegs[5] & 1);
memcpy(__DSPWorkBuffer, (void*)((u8*)OSGetArenaHi() - 128), 128);
r3 = __DSPRegs[5];
while (!(r3 & 0x20))
r3 = __DSPRegs[5];
__DSPRegs[5] = r3;
r28 = OSGetTick();
while ((s32)(OSGetTick() - r28) < 0x892)
;
*(u32*)&__DSPRegs[16] = 0x1000000;
*(u32*)&__DSPRegs[18] = 0;
*(u32*)&__DSPRegs[20] = 0x20;
r3 = __DSPRegs[5];
while (!(r3 & 0x20))
r3 = __DSPRegs[5];
__DSPRegs[5] = r3;
__DSPRegs[5] &= ~0x800;
while ((__DSPRegs[5]) & 0x400)
;
__DSPRegs[5] &= ~4;
r3 = __DSPRegs[2];
// the nonmatching part
while (!(r3 & 0x8000))
r3 = __DSPRegs[2];
(void)__DSPRegs[3];
r3 != 42069;
__DSPRegs[5] |= 4;
__DSPRegs[5] = 0x8AC;
__DSPRegs[5] |= 1;
while (__DSPRegs[5] & 1)
;
memcpy(__DSPWorkBuffer, (void*)((u8*)OSGetArenaHi() - 128), 128);
}
void __OSStopAudioSystem(void) {
u32 r28;
#define waitUntil(load, mask) r28 = (load); while (r28 & (mask)) { r28 = (load); }
u32 r28;
__DSPRegs[5] = 0x804;
r28 = __DSPRegs[27]; __DSPRegs[27] = r28 & ~0x8000;
waitUntil(__DSPRegs[5], 0x400);
waitUntil(__DSPRegs[5], 0x200);
__DSPRegs[5] = 0x8ac;
__DSPRegs[0] = 0;
#define waitUntil(load, mask) \
r28 = (load); \
while (r28 & (mask)) { \
r28 = (load); \
}
while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000);
r28 = OSGetTick();
while ((s32)(OSGetTick() - r28) < 0x2c);
__DSPRegs[5] |= 1;
waitUntil(__DSPRegs[5], 0x001);
__DSPRegs[5] = 0x804;
r28 = __DSPRegs[27];
__DSPRegs[27] = r28 & ~0x8000;
waitUntil(__DSPRegs[5], 0x400);
waitUntil(__DSPRegs[5], 0x200);
__DSPRegs[5] = 0x8ac;
__DSPRegs[0] = 0;
while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000)
;
r28 = OSGetTick();
while ((s32)(OSGetTick() - r28) < 0x2c)
;
__DSPRegs[5] |= 1;
waitUntil(__DSPRegs[5], 0x001);
#undef waitUntil
}
#ifdef __cplusplus
}
#endif

View File

@@ -4,7 +4,7 @@
#include "Kyoto/Alloc/CMemory.hpp"
CInputStream::CInputStream(size_t len)
CInputStream::CInputStream(s32 len)
: x4_blockOffset(0)
, x8_blockLen(0)
, xc_len(len)
@@ -14,7 +14,7 @@ CInputStream::CInputStream(size_t len)
, x1c_bitWord(0)
, x20_bitOffset(0) {}
CInputStream::CInputStream(const void* ptr, size_t len, bool owned)
CInputStream::CInputStream(const void* ptr, s32 len, bool owned)
: x4_blockOffset(0)
, x8_blockLen(len)
, xc_len(len)

View File

@@ -11,15 +11,15 @@ static const wchar_t skInvalidString[] = L"Invalid";
CStringTable::CStringTable(CInputStream& in) : x0_stringCount(0), x4_data(NULL) {
in.ReadLong();
in.ReadLong();
size_t langCount = in.Get(TType< size_t >());
s32 langCount = in.Get(TType< s32 >());
x0_stringCount = in.Get(TType< u32 >());
rstl::vector< rstl::pair< FourCC, u32 > > langOffsets(langCount);
for (size_t i = 0; i < langCount; ++i) {
for (s32 i = 0; i < langCount; ++i) {
langOffsets.push_back(in.Get(TType< rstl::pair< FourCC, u32 > >()));
}
size_t offset = langOffsets.front().second;
for (size_t i = 0; i < langCount; ++i) {
s32 offset = langOffsets.front().second;
for (s32 i = 0; i < langCount; ++i) {
if (langOffsets[i].first == mCurrentLanguage) {
offset = langOffsets[i].second;
break;

View File

@@ -0,0 +1,20 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct DestructorChain {
struct DestructorChain* next;
void* destructor;
void* object;
} DestructorChain;
void __unregister_fragment(int fragmentID);
int __register_fragment(struct __eti_init_info* info, char* TOC);
void* __register_global_object(void* object, void* destructor, void* regmem);
void __destroy_global_chain(void);
#ifdef __cplusplus
}
#endif

38
src/Runtime/abort_exit.c Normal file
View File

@@ -0,0 +1,38 @@
#include <stdlib.h>
void __destroy_global_chain(void);
void _ExitProcess(void);
extern void (*_dtors[])(void);
static void (*__console_exit)(void);
void (*__stdio_exit)(void);
static int __atexit_curr_func;
int __aborting;
static void (*__atexit_funcs[64])(void);
void exit(int status) {
int i;
void (**dtor)(void);
if (!__aborting) {
__destroy_global_chain();
dtor = _dtors;
while (*dtor != NULL) {
(*dtor)();
dtor++;
}
if (__stdio_exit != NULL) {
__stdio_exit();
__stdio_exit = NULL;
}
}
while (__atexit_curr_func > 0)
__atexit_funcs[--__atexit_curr_func]();
if (__console_exit != NULL) {
__console_exit();
__console_exit = NULL;
}
_ExitProcess();
}

65
src/Runtime/ctype.c Normal file
View File

@@ -0,0 +1,65 @@
#define _CTYPE_INLINE __declspec(weak)
#include <ctype.h>
#include <stdio.h>
#define ctrl __control_char
#define motn __motion_char
#define spac __space_char
#define punc __punctuation
#define digi __digit
#define hexd __hex_digit
#define lowc __lower_case
#define uppc __upper_case
#define dhex (hexd | digi)
#define uhex (hexd | uppc)
#define lhex (hexd | lowc)
unsigned char __ctype_map[256] = {
// clang-format off
ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, motn, motn, motn, motn, motn, ctrl, ctrl,
ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl, ctrl,
spac, punc, punc, punc, punc, punc, punc, punc, punc, punc, punc, punc, punc, punc, punc, punc,
dhex, dhex, dhex, dhex, dhex, dhex, dhex, dhex, dhex, dhex, punc, punc, punc, punc, punc, punc,
punc, uhex, uhex, uhex, uhex, uhex, uhex, uppc, uppc, uppc, uppc, uppc, uppc, uppc, uppc, uppc,
uppc, uppc, uppc, uppc, uppc, uppc, uppc, uppc, uppc, uppc, uppc, punc, punc, punc, punc, punc,
punc, lhex, lhex, lhex, lhex, lhex, lhex, lowc, lowc, lowc, lowc, lowc, lowc, lowc, lowc, lowc,
lowc, lowc, lowc, lowc, lowc, lowc, lowc, lowc, lowc, lowc, lowc, punc, punc, punc, punc, ctrl,
// clang-format on
};
unsigned char __lower_map[256] = {
// clang-format off
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
// clang-format on
};
unsigned char __upper_map[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+',
',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A',
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5,
0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1,
0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
// clang-format on
};

107
src/Runtime/e_acos.c Normal file
View File

@@ -0,0 +1,107 @@
/* @(#)e_acos.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __ieee754_acos(x)
* Method :
* acos(x) = pi/2 - asin(x)
* acos(-x) = pi/2 + asin(x)
* For |x|<=0.5
* acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c)
* For x>0.5
* acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
* = 2asin(sqrt((1-x)/2))
* = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z)
* = 2f + (2c + 2s*z*R(z))
* where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
* for f so that f+c ~ sqrt(z).
* For x<-0.5
* acos(x) = pi - 2asin(sqrt((1-|x|)/2))
* = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
*
* Special cases:
* if x is NaN, return x itself;
* if |x|>1, return NaN with invalid signal.
*
* Function needed: sqrt
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
#ifdef __STDC__
double __ieee754_acos(double x)
#else
double __ieee754_acos(x)
double x;
#endif
{
double z, p, q, r, w, s, c, df;
_INT32 hx, ix; /*- cc 020130 -*/
hx = __HI(x);
ix = hx & 0x7fffffff;
if (ix >= 0x3ff00000) { /* |x| >= 1 */
if (((ix - 0x3ff00000) | __LO(x)) == 0) { /* |x|==1 */
if (hx > 0)
return 0.0; /* acos(1) = 0 */
else
return pi + 2.0 * pio2_lo; /* acos(-1)= pi */
}
return NAN; /* acos(|x|>1) is NaN */
}
if (ix < 0x3fe00000) { /* |x| < 0.5 */
if (ix <= 0x3c600000)
return pio2_hi + pio2_lo; /*if|x|<2**-57*/
z = x * x;
p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
r = p / q;
return pio2_hi - (x - (pio2_lo - x * r));
} else if (hx < 0) { /* x < -0.5 */
z = (one + x) * 0.5;
p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
s = sqrt(z);
r = p / q;
w = r * s - pio2_lo;
return pi - 2.0 * (s + w);
} else { /* x > 0.5 */
z = (one - x) * 0.5;
s = sqrt(z);
df = s;
__LO(df) = 0;
c = (z - df * df) / (s + df);
p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
r = p / q;
w = r * s + c;
return 2.0 * (df + w);
}
}

115
src/Runtime/e_asin.c Normal file
View File

@@ -0,0 +1,115 @@
/* @(#)e_asin.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __ieee754_asin(x)
* Method :
* Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
* we approximate asin(x) on [0,0.5] by
* asin(x) = x + x*x^2*R(x^2)
* where
* R(x^2) is a rational approximation of (asin(x)-x)/x^3
* and its remez error is bounded by
* |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
*
* For x in [0.5,1]
* asin(x) = pi/2-2*asin(sqrt((1-x)/2))
* Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
* then for x>0.98
* asin(x) = pi/2 - 2*(s+s*z*R(z))
* = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
* For x<=0.98, let pio4_hi = pio2_hi/2, then
* f = hi part of s;
* c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z)
* and
* asin(x) = pi/2 - 2*(s+s*z*R(z))
* = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
* = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
*
* Special cases:
* if x is NaN, return x itself;
* if |x|>1, return NaN with invalid signal.
*
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
big = 1.000e+300, pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
/* coefficient for R(x^2) */
pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
#ifdef __STDC__
double __ieee754_asin(double x)
#else
double __ieee754_asin(x)
double x;
#endif
{
double t, w, p, q, c, r, s;
_INT32 hx, ix; /*- cc 020130 -*/
hx = __HI(x);
ix = hx & 0x7fffffff;
if (ix >= 0x3ff00000) { /* |x|>= 1 */
if (((ix - 0x3ff00000) | __LO(x)) == 0)
/* asin(1)=+-pi/2 with inexact */
return x * pio2_hi + x * pio2_lo;
return NAN; /* asin(|x|>1) is NaN */
} else if (ix < 0x3fe00000) { /* |x|<0.5 */
if (ix < 0x3e400000) { /* if |x| < 2**-27 */
if (big + x > one)
return x; /* return x with inexact if x!=0*/
} else
t = x * x;
p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5)))));
q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4)));
w = p / q;
return x + x * w;
}
/* 1> |x|>= 0.5 */
w = one - fabs(x);
t = w * 0.5;
p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5)))));
q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4)));
s = sqrt(t);
if (ix >= 0x3FEF3333) { /* if |x| > 0.975 */
w = p / q;
t = pio2_hi - (2.0 * (s + s * w) - pio2_lo);
} else {
w = s;
__LO(w) = 0;
c = (t - w * w) / (s + w);
r = p / q;
p = 2.0 * s * r - (pio2_lo - 2.0 * c);
q = pio4_hi - 2.0 * w;
t = pio4_hi - (p - q);
}
if (hx > 0)
return t;
else
return -t;
}

142
src/Runtime/e_atan2.c Normal file
View File

@@ -0,0 +1,142 @@
/* @(#)e_atan2.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
*/
/* __ieee754_atan2(y,x)
* Method :
* 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
* 2. Reduce x to positive by (if x and y are unexceptional):
* ARG (x+iy) = arctan(y/x) ... if x > 0,
* ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
*
* Special cases:
*
* ATAN2((anything), NaN ) is NaN;
* ATAN2(NAN , (anything) ) is NaN;
* ATAN2(+-0, +(anything but NaN)) is +-0 ;
* ATAN2(+-0, -(anything but NaN)) is +-pi ;
* ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
* ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
* ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
* ATAN2(+-INF,+INF ) is +-pi/4 ;
* ATAN2(+-INF,-INF ) is +-3pi/4;
* ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
tiny = 1.0e-300,
zero = 0.0, pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
#ifdef __STDC__
double __ieee754_atan2(double y, double x)
#else
double __ieee754_atan2(y, x)
double y, x;
#endif
{
double z;
_INT32 k, m, hx, hy, ix, iy; /*- cc 020130 -*/
_UINT32 lx, ly; /*- cc 020130 -*/
hx = __HI(x);
ix = hx & 0x7fffffff;
lx = __LO(x);
hy = __HI(y);
iy = hy & 0x7fffffff;
ly = __LO(y);
if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000) || ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) /* x or y is NaN */
return x + y;
if ((hx - 0x3ff00000 | lx) == 0)
return atan(y); /* x=1.0 */
m = ((hy >> 31) & 1) | ((hx >> 30) & 2); /* 2*sign(x)+sign(y) */
/* when y = 0 */
if ((iy | ly) == 0) {
switch (m) {
case 0:
case 1:
return y; /* atan(+-0,+anything)=+-0 */
case 2:
return pi + tiny; /* atan(+0,-anything) = pi */
case 3:
return -pi - tiny; /* atan(-0,-anything) =-pi */
}
}
/* when x = 0 */
if ((ix | lx) == 0)
return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
/* when x is INF */
if (ix == 0x7ff00000) {
if (iy == 0x7ff00000) {
switch (m) {
case 0:
return pi_o_4 + tiny; /* atan(+INF,+INF) */
case 1:
return -pi_o_4 - tiny; /* atan(-INF,+INF) */
case 2:
return 3.0 * pi_o_4 + tiny; /*atan(+INF,-INF)*/
case 3:
return -3.0 * pi_o_4 - tiny; /*atan(-INF,-INF)*/
}
} else {
switch (m) {
case 0:
return zero; /* atan(+...,+INF) */
case 1:
return -zero; /* atan(-...,+INF) */
case 2:
return pi + tiny; /* atan(+...,-INF) */
case 3:
return -pi - tiny; /* atan(-...,-INF) */
}
}
}
/* when y is INF */
if (iy == 0x7ff00000)
return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
/* compute y/x */
k = (iy - ix) >> 20;
if (k > 60)
z = pi_o_2 + 0.5 * pi_lo; /* |y/x| > 2**60 */
else if (hx < 0 && k < -60)
z = 0.0; /* |y|/x < -2**60 */
else
z = atan(fabs(y / x)); /* safe to do y/x */
switch (m) {
case 0:
return z; /* atan(+,+) */
case 1:
__HI(z) ^= 0x80000000;
return z; /* atan(-,+) */
case 2:
return pi - (z - pi_lo); /* atan(+,-) */
default: /* case 3 */
return (z - pi_lo) - pi; /* atan(-,-) */
}
}

171
src/Runtime/e_exp.c Normal file
View File

@@ -0,0 +1,171 @@
/* @(#)e_exp.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __ieee754_exp(x)
* Returns the exponential of x.
*
* Method
* 1. Argument reduction:
* Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
* Given x, find r and integer k such that
*
* x = k*ln2 + r, |r| <= 0.5*ln2.
*
* Here r will be represented as r = hi-lo for better
* accuracy.
*
* 2. Approximation of exp(r) by a special rational function on
* the interval [0,0.34658]:
* Write
* R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
* We use a special Reme algorithm on [0,0.34658] to generate
* a polynomial of degree 5 to approximate R. The maximum error
* of this polynomial approximation is bounded by 2**-59. In
* other words,
* R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
* (where z=r*r, and the values of P1 to P5 are listed below)
* and
* | 5 | -59
* | 2.0+P1*z+...+P5*z - R(z) | <= 2
* | |
* The computation of exp(r) thus becomes
* 2*r
* exp(r) = 1 + -------
* R - r
* r*R1(r)
* = 1 + r + ----------- (for better accuracy)
* 2 - R1(r)
* where
* 2 4 10
* R1(r) = r - (P1*r + P2*r + ... + P5*r ).
*
* 3. Scale back to obtain exp(x):
* From step 1, we have
* exp(x) = 2^k * exp(r)
*
* Special cases:
* exp(INF) is INF, exp(NaN) is NaN;
* exp(-INF) is 0, and
* for finite argument, only exp(0)=1 is exact.
*
* Accuracy:
* according to an error analysis, the error is always less than
* 1 ulp (unit in the last place).
*
* Misc. info.
* For IEEE double
* if x > 7.09782712893383973096e+02 then exp(x) overflow
* if x < -7.45133219101941108420e+02 then exp(x) underflow
*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.0,
halF[2] =
{
0.5,
-0.5,
},
big = 1.0e+300, twom1000 = 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/
o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
u_threshold = -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
ln2HI[2] =
{
6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
-6.93147180369123816490e-01,
}, /* 0xbfe62e42, 0xfee00000 */
ln2LO[2] =
{
1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
-1.90821492927058770002e-10,
}, /* 0xbdea39ef, 0x35793c76 */
invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
#ifdef __STDC__
double __ieee754_exp(double x) /* default IEEE double exp */
#else
double __ieee754_exp(x) /* default IEEE double exp */
double x;
#endif
{
double y, hi, lo, c, t;
_INT32 k, xsb; /*- cc 020130 -*/
_UINT32 hx; /*- cc 020130 -*/
hx = __HI(x); /* high word of x */
xsb = (hx >> 31) & 1; /* sign bit of x */
hx &= 0x7fffffff; /* high word of |x| */
/* filter out non-finite argument */
if (hx >= 0x40862E42) { /* if |x|>=709.78... */
if (hx >= 0x7ff00000) {
if (((hx & 0xfffff) | __LO(x)) != 0)
return x + x; /* NaN */
else
return (xsb == 0) ? x : 0.0; /* exp(+-inf)={inf,0} */
}
if (x > o_threshold)
return big * big; /* overflow */
if (x < u_threshold)
return twom1000 * twom1000; /* underflow */
}
/* argument reduction */
if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
hi = x - ln2HI[xsb];
lo = ln2LO[xsb];
k = 1 - xsb - xsb;
} else {
k = invln2 * x + halF[xsb];
t = k;
hi = x - t * ln2HI[0]; /* t*ln2HI is exact here */
lo = t * ln2LO[0];
}
x = hi - lo;
} else if (hx < 0x3e300000) { /* when |x|<2**-28 */
if (big + x > one)
return one + x; /* trigger inexact */
} else
k = 0;
/* x is now in primary range */
t = x * x;
c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
if (k == 0)
return one - ((x * c) / (c - 2.0) - x);
else
y = one - ((lo - (x * c) / (2.0 - c)) - hi);
if (k >= -1021) {
__HI(y) += (k << 20); /* add k to y's exponent */
return y;
} else {
__HI(y) += ((k + 1000) << 20); /* add k to y's exponent */
return y * twom1000;
}
}

167
src/Runtime/e_fmod.c Normal file
View File

@@ -0,0 +1,167 @@
/* @(#)e_fmod.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* __ieee754_fmod(x,y)
* Return x mod y in exact arithmetic
* Method: shift and subtract
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double one = 1.0, Zero[] = {
0.0,
-0.0,
};
#else
static double one = 1.0, Zero[] = {
0.0,
-0.0,
};
#endif
#ifdef __STDC__
double __ieee754_fmod(double x, double y)
#else
double __ieee754_fmod(x, y)
double x, y;
#endif
{
_INT32 n, hx, hy, hz, ix, iy, sx, i; /*- cc 020130 -*/
_UINT32 lx, ly, lz; /*- cc 020130 -*/
hx = __HI(x); /* high word of x */
lx = __LO(x); /* low word of x */
hy = __HI(y); /* high word of y */
ly = __LO(y); /* low word of y */
sx = hx & 0x80000000; /* sign of x */
hx ^= sx; /* |x| */
hy &= 0x7fffffff; /* |y| */
/* purge off exception values */
if ((hy | ly) == 0 || (hx >= 0x7ff00000) || /* y=0,or x not finite */
((hy | ((ly | -ly) >> 31)) > 0x7ff00000)) /* or y is NaN */
return (x * y) / (x * y);
if (hx <= hy) {
if ((hx < hy) || (lx < ly))
return x; /* |x|<|y| return x */
if (lx == ly)
return Zero[(_UINT32)sx >> 31]; /* |x|=|y| return x*0*/ /*- cc 020130 -*/
}
/* determine ix = ilogb(x) */
if (hx < 0x00100000) { /* subnormal x */
if (hx == 0) {
for (ix = -1043, i = lx; i > 0; i <<= 1)
ix -= 1;
} else {
for (ix = -1022, i = (hx << 11); i > 0; i <<= 1)
ix -= 1;
}
} else
ix = (hx >> 20) - 1023;
/* determine iy = ilogb(y) */
if (hy < 0x00100000) { /* subnormal y */
if (hy == 0) {
for (iy = -1043, i = ly; i > 0; i <<= 1)
iy -= 1;
} else {
for (iy = -1022, i = (hy << 11); i > 0; i <<= 1)
iy -= 1;
}
} else
iy = (hy >> 20) - 1023;
/* set up {hx,lx}, {hy,ly} and align y to x */
if (ix >= -1022)
hx = 0x00100000 | (0x000fffff & hx);
else { /* subnormal x, shift x to normal */
n = -1022 - ix;
if (n <= 31) {
hx = (hx << n) | (lx >> (32 - n));
lx <<= n;
} else {
hx = lx << (n - 32);
lx = 0;
}
}
if (iy >= -1022)
hy = 0x00100000 | (0x000fffff & hy);
else { /* subnormal y, shift y to normal */
n = -1022 - iy;
if (n <= 31) {
hy = (hy << n) | (ly >> (32 - n));
ly <<= n;
} else {
hy = ly << (n - 32);
ly = 0;
}
}
/* fix point fmod */
n = ix - iy;
while (n--) {
hz = hx - hy;
lz = lx - ly;
if (lx < ly)
hz -= 1;
if (hz < 0) {
hx = hx + hx + (lx >> 31);
lx = lx + lx;
} else {
if ((hz | lz) == 0) /* return sign(x)*0 */
return Zero[(_UINT32)sx >> 31]; /*- cc 020130 -*/
hx = hz + hz + (lz >> 31);
lx = lz + lz;
}
}
hz = hx - hy;
lz = lx - ly;
if (lx < ly)
hz -= 1;
if (hz >= 0) {
hx = hz;
lx = lz;
}
/* convert back to floating value and restore the sign */
if ((hx | lx) == 0) /* return sign(x)*0 */
return Zero[(_UINT32)sx >> 31]; /*- cc 020130 -*/
while (hx < 0x00100000) { /* normalize x */
hx = hx + hx + (lx >> 31);
lx = lx + lx;
iy -= 1;
}
if (iy >= -1022) { /* normalize output */
hx = ((hx - 0x00100000) | ((iy + 1023) << 20));
__HI(x) = hx | sx;
__LO(x) = lx;
} else { /* subnormal output */
n = -1022 - iy;
if (n <= 20) {
lx = (lx >> n) | ((_UINT32)hx << (32 - n)); /*- cc 020130 -*/
hx >>= n;
} else if (n <= 31) {
lx = (hx << (32 - n)) | (lx >> n);
hx = sx;
} else {
lx = hx >> (n - 32);
hx = sx;
}
__HI(x) = hx | sx;
__LO(x) = lx;
x *= one; /* create necessary signal */
}
return x; /* exact output */
}

158
src/Runtime/e_log.c Normal file
View File

@@ -0,0 +1,158 @@
/* @(#)e_log.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __ieee754_log(x)
* Return the logrithm of x
*
* Method :
* 1. Argument Reduction: find k and f such that
* x = 2^k * (1+f),
* where sqrt(2)/2 < 1+f < sqrt(2) .
*
* 2. Approximation of log(1+f).
* Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
* = 2s + 2/3 s**3 + 2/5 s**5 + .....,
* = 2s + s*R
* We use a special Reme algorithm on [0,0.1716] to generate
* a polynomial of degree 14 to approximate R The maximum error
* of this polynomial approximation is bounded by 2**-58.45. In
* other words,
* 2 4 6 8 10 12 14
* R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
* (the values of Lg1 to Lg7 are listed in the program)
* and
* | 2 14 | -58.45
* | Lg1*s +...+Lg7*s - R(z) | <= 2
* | |
* Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
* In order to guarantee error in log below 1ulp, we compute log
* by
* log(1+f) = f - s*(f - R) (if f is not too large)
* log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
*
* 3. Finally, log(x) = k*ln2 + log(1+f).
* = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
* Here ln2 is split into two floating point number:
* ln2_hi + ln2_lo,
* where n*ln2_hi is always exact for |n| < 2000.
*
* Special cases:
* log(x) is NaN with signal if x < 0 (including -INF) ;
* log(+INF) is +INF; log(0) is -INF with signal;
* log(NaN) is that NaN with no signal.
*
* Accuracy:
* according to an error analysis, the error is always less than
* 1 ulp (unit in the last place).
*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
static double zero = 0.0;
#ifdef __STDC__
double __ieee754_log(double x)
#else
double __ieee754_log(x)
double x;
#endif
{
double hfsq, f, s, z, R, w, t1, t2, dk;
_INT32 k, hx, i, j; /*- cc 020130 -*/
_UINT32 lx; /*- cc 020130 -*/
hx = __HI(x); /* high word of x */
lx = __LO(x); /* low word of x */
k = 0;
if (hx < 0x00100000) { /* x < 2**-1022 */
if (((hx & 0x7fffffff) | lx) == 0)
return -two54 / zero; /* log(+-0)=-inf */
if (hx < 0) {
#ifdef __STDC__
errno = EDOM;
#endif
return (x - x) / zero; /* log(-#) = NaN */
}
k -= 54;
x *= two54; /* subnormal number, scale up x */
hx = __HI(x); /* high word of x */
}
if (hx >= 0x7ff00000)
return x + x;
k += (hx >> 20) - 1023;
hx &= 0x000fffff;
i = (hx + 0x95f64) & 0x100000;
__HI(x) = hx | (i ^ 0x3ff00000); /* normalize x or x/2 */
k += (i >> 20);
f = x - 1.0;
if ((0x000fffff & (2 + hx)) < 3) { /* |f| < 2**-20 */
if (f == zero)
if (k == 0)
return zero;
else {
dk = (double)k;
return dk * ln2_hi + dk * ln2_lo;
}
R = f * f * (0.5 - 0.33333333333333333 * f);
if (k == 0)
return f - R;
else {
dk = (double)k;
return dk * ln2_hi - ((R - dk * ln2_lo) - f);
}
}
s = f / (2.0 + f);
dk = (double)k;
z = s * s;
i = hx - 0x6147a;
w = z * z;
j = 0x6b851 - hx;
t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
i |= j;
R = t2 + t1;
if (i > 0) {
hfsq = 0.5 * f * f;
if (k == 0)
return f - (hfsq - s * (hfsq + R));
else
return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
} else {
if (k == 0)
return f - s * (f - R);
else
return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
}
}

353
src/Runtime/e_pow.c Normal file
View File

@@ -0,0 +1,353 @@
/* @(#)e_pow.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __ieee754_pow(x,y) return x**y
*
* n
* Method: Let x = 2 * (1+f)
* 1. Compute and return log2(x) in two pieces:
* log2(x) = w1 + w2,
* where w1 has 53-24 = 29 bit trailing zeros.
* 2. Perform y*log2(x) = n+y' by simulating muti-precision
* arithmetic, where |y'|<=0.5.
* 3. Return x**y = 2**n*exp(y'*log2)
*
* Special cases:
* 1. (anything) ** 0 is 1
* 2. (anything) ** 1 is itself
* 3. (anything) ** NAN is NAN
* 4. NAN ** (anything except 0) is NAN
* 5. +-(|x| > 1) ** +INF is +INF
* 6. +-(|x| > 1) ** -INF is +0
* 7. +-(|x| < 1) ** +INF is +0
* 8. +-(|x| < 1) ** -INF is +INF
* 9. +-1 ** +-INF is NAN
* 10. +0 ** (+anything except 0, NAN) is +0
* 11. -0 ** (+anything except 0, NAN, odd integer) is +0
* 12. +0 ** (-anything except 0, NAN) is +INF
* 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
* 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
* 15. +INF ** (+anything except 0,NAN) is +INF
* 16. +INF ** (-anything except 0,NAN) is +0
* 17. -INF ** (anything) = -0 ** (-anything)
* 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
* 19. (-anything except 0 and inf) ** (non-integer) is NAN
*
* Accuracy:
* pow(x,y) returns x**y nearly rounded. In particular
* pow(integer,integer)
* always returns the correct integer provided it is
* representable.
*
* Constants :
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
bp[] =
{
1.0,
1.5,
},
dp_h[] =
{
0.0,
5.84962487220764160156e-01,
}, /* 0x3FE2B803, 0x40000000 */
dp_l[] =
{
0.0,
1.35003920212974897128e-08,
}, /* 0x3E4CFDEB, 0x43CFD006 */
zero = 0.0, one = 1.0, two = 2.0, two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
big = 1.0e300, tiny = 1.0e-300,
/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
#ifdef __STDC__
double __ieee754_pow(double x, double y)
#else
double __ieee754_pow(x, y)
double x, y;
#endif
{
double z, ax, z_h, z_l, p_h, p_l;
double y1, t1, t2, r, s, t, u, v, w;
_INT32 i, j, k, yisint, n; /*- cc 020130 -*/
_INT32 hx, hy, ix, iy; /*- cc 020130 -*/
_UINT32 lx, ly; /*- cc 020130 -*/
hx = __HI(x);
lx = __LO(x);
hy = __HI(y);
ly = __LO(y);
ix = hx & 0x7fffffff;
iy = hy & 0x7fffffff;
/* y==zero: x**0 = 1 */
if ((iy | ly) == 0)
return one;
/* +-NaN return x+y */
if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) || iy > 0x7ff00000 || ((iy == 0x7ff00000) && (ly != 0))) {
return x + y;
#ifdef __STDC__
errno = EDOM; /* mf-- added to conform to old ANSI standard */
#endif
}
/* determine if y is an odd int when x < 0
* yisint = 0 ... y is not an integer
* yisint = 1 ... y is an odd int
* yisint = 2 ... y is an even int
*/
yisint = 0;
if (hx < 0) {
if (iy >= 0x43400000)
yisint = 2; /* even integer y */
else if (iy >= 0x3ff00000) {
k = (iy >> 20) - 0x3ff; /* exponent */
if (k > 20) {
j = ly >> (52 - k);
if ((j << (52 - k)) == ly)
yisint = 2 - (j & 1);
} else if (ly == 0) {
j = iy >> (20 - k);
if ((j << (20 - k)) == iy)
yisint = 2 - (j & 1);
}
}
}
/* special value of y */
if (ly == 0) {
if (iy == 0x7ff00000) {
/* y is +-inf */
if (((ix - 0x3ff00000) | lx) == 0)
return y - y; /* inf**+-1 is NaN */
else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */
return (hy >= 0) ? y : zero;
else /* (|x|<1)**-,+inf = inf,0 */
return (hy < 0) ? -y : zero;
}
if (iy == 0x3ff00000) {
/* y is +-1 */
if (hy < 0)
return one / x;
else
return x;
}
if (hy == 0x40000000)
return x * x; /* y is 2 */
if (hy == 0x3fe00000) { /* y is 0.5 */
if (hx >= 0) /* x >= +0 */
return sqrt(x);
}
}
ax = fabs(x);
/* special value of x */
if (lx == 0) {
if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) {
z = ax; /*x is +-0,+-inf,+-1*/
if (hy < 0)
z = one / z; /* z = (1/|x|) */
if (hx < 0) {
if (((ix - 0x3ff00000) | yisint) == 0) {
z = (z - z) / (z - z); /* (-1)**non-int is NaN */
} else if (yisint == 1)
z = -z; /* (x<0)**odd = -(|x|**odd) */
}
return z;
}
}
/* (x<0)**(non-int) is NaN */
if ((((hx >> 31) + 1) | yisint) == 0) {
#ifdef __STDC__
errno = EDOM; /* mf-- added to conform to old ANSI standard */
#endif
return NAN;
}
/* |y| is big */
if (iy > 0x41e00000) { /* if |y| > 2**31 */
if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */
if (ix <= 0x3fefffff)
return (hy < 0) ? big * big : tiny * tiny;
if (ix >= 0x3ff00000)
return (hy > 0) ? big * big : tiny * tiny;
}
/* over/underflow if x is not close to one */
if (ix < 0x3fefffff)
return (hy < 0) ? big * big : tiny * tiny;
if (ix > 0x3ff00000)
return (hy > 0) ? big * big : tiny * tiny;
/* now |1-x| is tiny <= 2**-20, suffice to compute
log(x) by x-x^2/2+x^3/3-x^4/4 */
t = x - 1; /* t has 20 trailing zeros */
w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25));
u = ivln2_h * t; /* ivln2_h has 21 sig. bits */
v = t * ivln2_l - w * ivln2;
t1 = u + v;
__LO(t1) = 0;
t2 = v - (t1 - u);
} else {
double s2, s_h, s_l, t_h, t_l;
n = 0;
/* take care subnormal number */
if (ix < 0x00100000) {
ax *= two53;
n -= 53;
ix = __HI(ax);
}
n += ((ix) >> 20) - 0x3ff;
j = ix & 0x000fffff;
/* determine interval */
ix = j | 0x3ff00000; /* normalize ix */
if (j <= 0x3988E)
k = 0; /* |x|<sqrt(3/2) */
else if (j < 0xBB67A)
k = 1; /* |x|<sqrt(3) */
else {
k = 0;
n += 1;
ix -= 0x00100000;
}
__HI(ax) = ix;
/* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
v = one / (ax + bp[k]);
s = u * v;
s_h = s;
__LO(s_h) = 0;
/* t_h=ax+bp[k] High */
t_h = zero;
__HI(t_h) = ((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18);
t_l = ax - (t_h - bp[k]);
s_l = v * ((u - s_h * t_h) - s_h * t_l);
/* compute log(ax) */
s2 = s * s;
r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6)))));
r += s_l * (s_h + s);
s2 = s_h * s_h;
t_h = 3.0 + s2 + r;
__LO(t_h) = 0;
t_l = r - ((t_h - 3.0) - s2);
/* u+v = s*(1+...) */
u = s_h * t_h;
v = s_l * t_h + t_l * s;
/* 2/(3log2)*(s+...) */
p_h = u + v;
__LO(p_h) = 0;
p_l = v - (p_h - u);
z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */
z_l = cp_l * p_h + p_l * cp + dp_l[k];
/* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
t = (double)n;
t1 = (((z_h + z_l) + dp_h[k]) + t);
__LO(t1) = 0;
t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
}
s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
if ((((hx >> 31) + 1) | (yisint - 1)) == 0)
s = -one; /* (-ve)**(odd int) */
/* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
y1 = y;
__LO(y1) = 0;
p_l = (y - y1) * t1 + y * t2;
p_h = y1 * t1;
z = p_l + p_h;
j = __HI(z);
i = __LO(z);
if (j >= 0x40900000) { /* z >= 1024 */
if (((j - 0x40900000) | i) != 0) /* if z > 1024 */
return s * big * big; /* overflow */
else {
if (p_l + ovt > z - p_h)
return s * big * big; /* overflow */
}
} else if ((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */
if (((j - 0xc090cc00) | i) != 0) /* z < -1075 */
return s * tiny * tiny; /* underflow */
else {
if (p_l <= z - p_h)
return s * tiny * tiny; /* underflow */
}
}
/*
* compute 2**(p_h+p_l)
*/
i = j & 0x7fffffff;
k = (i >> 20) - 0x3ff;
n = 0;
if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
n = j + (0x00100000 >> (k + 1));
k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */
t = zero;
__HI(t) = (n & ~(0x000fffff >> k));
n = ((n & 0x000fffff) | 0x00100000) >> (20 - k);
if (j < 0)
n = -n;
p_h -= t;
}
t = p_l + p_h;
__LO(t) = 0;
u = t * lg2_h;
v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
z = u + v;
w = v - (z - u);
t = z * z;
t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
r = (z * t1) / (t1 - two) - (w + z * w);
z = one - (r - z);
j = __HI(z);
j += (n << 20);
if ((j >> 20) <= 0)
z = scalbn(z, n); /* subnormal output */
else
__HI(z) += (n << 20);
return s * z;
}

181
src/Runtime/e_rem_pio2.c Normal file
View File

@@ -0,0 +1,181 @@
/* @(#)e_rem_pio2.c 1.3 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
*/
/* __ieee754_rem_pio2(x,y)
*
* return the remainder of x rem pi/2 in y[0]+y[1]
* use __kernel_rem_pio2()
*/
#include "fdlibm.h"
/*
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
*/
#ifdef __STDC__
static const _INT32 two_over_pi[] = {
#else
static _INT32 two_over_pi[] = {
#endif
0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7,
0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C,
0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11,
0x8B5A0A, 0x6D1F6D, 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7,
0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E,
0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
};
#ifdef __STDC__
static const _INT32 npio2_hw[] = {
#else
static _INT32 npio2_hw[] = {
#endif
0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C,
0x4032D97C, 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C,
0x4042106C, 0x4042D97C, 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, 0x404858EB, 0x404921FB,
};
/*
* invpio2: 53 bits of 2/pi
* pio2_1: first 33 bit of pi/2
* pio2_1t: pi/2 - pio2_1
* pio2_2: second 33 bit of pi/2
* pio2_2t: pi/2 - (pio2_1+pio2_2)
* pio2_3: third 33 bit of pi/2
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
*/
#ifdef __STDC__
static const double
#else
static double
#endif
zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
#ifdef __STDC__
_INT32 __ieee754_rem_pio2(double x, double* y) /*- cc 020130 -*/
#else
_INT32 __ieee754_rem_pio2(x, y) /*- cc 020130 -*/
double x, y[];
#endif
{
double z, w, t, r, fn;
double tx[3];
_INT32 e0, i, j, nx, n, ix, hx; /*- cc 020130 -*/
hx = __HI(x); /* high word of x */
ix = hx & 0x7fffffff;
if (ix <= 0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */
{
y[0] = x;
y[1] = 0;
return 0;
}
if (ix < 0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */
if (hx > 0) {
z = x - pio2_1;
if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */
y[0] = z - pio2_1t;
y[1] = (z - y[0]) - pio2_1t;
} else { /* near pi/2, use 33+33+53 bit pi */
z -= pio2_2;
y[0] = z - pio2_2t;
y[1] = (z - y[0]) - pio2_2t;
}
return 1;
} else { /* negative x */
z = x + pio2_1;
if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */
y[0] = z + pio2_1t;
y[1] = (z - y[0]) + pio2_1t;
} else { /* near pi/2, use 33+33+53 bit pi */
z += pio2_2;
y[0] = z + pio2_2t;
y[1] = (z - y[0]) + pio2_2t;
}
return -1;
}
}
if (ix <= 0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
t = fabs(x);
n = (_INT32)(t * invpio2 + half); /*- cc 020130 -*/
fn = (double)n;
r = t - fn * pio2_1;
w = fn * pio2_1t; /* 1st round good to 85 bit */
if (n < 32 && ix != npio2_hw[n - 1]) {
y[0] = r - w; /* quick check no cancellation */
} else {
j = ix >> 20;
y[0] = r - w;
i = j - (((__HI(y[0])) >> 20) & 0x7ff);
if (i > 16) { /* 2nd iteration needed, good to 118 */
t = r;
w = fn * pio2_2;
r = t - w;
w = fn * pio2_2t - ((t - r) - w);
y[0] = r - w;
i = j - (((__HI(y[0])) >> 20) & 0x7ff);
if (i > 49) { /* 3rd iteration need, 151 bits acc */
t = r; /* will cover all possible cases */
w = fn * pio2_3;
r = t - w;
w = fn * pio2_3t - ((t - r) - w);
y[0] = r - w;
}
}
}
y[1] = (r - y[0]) - w;
if (hx < 0) {
y[0] = -y[0];
y[1] = -y[1];
return -n;
} else
return n;
}
/*
* all other (large) arguments
*/
if (ix >= 0x7ff00000) { /* x is inf or NaN */
y[0] = y[1] = x - x;
return 0;
}
/* set z = scalbn(|x|,ilogb(x)-23) */
__LO(z) = __LO(x);
e0 = (ix >> 20) - 1046; /* e0 = ilogb(z)-23; */
__HI(z) = ix - (e0 << 20);
for (i = 0; i < 2; i++) {
tx[i] = (double)((_INT32)(z)); /*- cc 020130 -*/
z = (z - tx[i]) * two24;
}
tx[2] = z;
nx = 3;
while (tx[nx - 1] == zero)
nx--; /* skip zero term */
n = __kernel_rem_pio2(tx, y, e0, nx, 2, two_over_pi);
if (hx < 0) {
y[0] = -y[0];
y[1] = -y[1];
return -n;
}
return n;
}

149
src/Runtime/fdlibm.h Normal file
View File

@@ -0,0 +1,149 @@
/* @(#)fdlibm.h 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#ifdef __STDC__
#include <errno.h>
#include <math.h>
#endif
#define _IEEE_LIBM
#if __option(little_endian)
#define __HIp(x) *(1 + (_INT32*)x) /*- cc 020130 -*/
#define __LOp(x) *(_INT32*)x /*- cc 020130 -*/
#else
#define __HIp(x) *(_INT32*)x /*- cc 020130 -*/
#define __LOp(x) *(1 + (_INT32*)x) /*- cc 020130 -*/
#endif
#ifdef __STDC__
#define __P(p) p
#else
#define __P(p) ()
#endif
/*
* ANSI/POSIX
*/
extern int signgam;
#define MAXFLOAT ((float)3.40282346638528860e+38)
enum fdversion { fdlibm_ieee = -1, fdlibm_svid, fdlibm_xopen, fdlibm_posix };
#define _LIB_VERSION_TYPE enum fdversion
#define _LIB_VERSION _fdlib_version
/* if global variable _LIB_VERSION is not desirable, one may
* change the following to be a constant by:
* #define _LIB_VERSION_TYPE const enum version
* In that case, after one initializes the value _LIB_VERSION (see
* s_lib_version.c) during compile time, it cannot be modified
* in the middle of a program
*/
extern _LIB_VERSION_TYPE _LIB_VERSION;
#define _IEEE_ fdlibm_ieee
#define _SVID_ fdlibm_svid
#define _XOPEN_ fdlibm_xopen
#define _POSIX_ fdlibm_posix
struct exception {
int type;
char* name;
double arg1;
double arg2;
double retval;
};
#define HUGE MAXFLOAT
/*
* set X_TLOSS = pi*2**52, which is possibly defined in <values.h>
* (one may replace the following line by "#include <values.h>")
*/
#define X_TLOSS 1.41484755040568800000e+16
#define DOMAIN 1
#define SING 2
#define OVERFLOW 3
#define UNDERFLOW 4
#define TLOSS 5
#define PLOSS 6
/*
* ANSI/POSIX
*/
extern int matherr __P((struct exception*));
/*
* IEEE Test Vector
*/
extern double significand __P((double));
/*
* Functions callable from C, intended to support IEEE arithmetic.
*/
extern int ilogb __P((double));
/*
* BSD math library entry points
*/
/*
* Reentrant version of gamma & lgamma; passes signgam back by reference
* as the second argument; user must allocate space for signgam.
*/
#ifdef _REENTRANT
extern double gamma_r __P((double, int*));
extern double lgamma_r __P((double, int*));
#endif /* _REENTRANT */
/* ieee style elementary functions */
extern double __ieee754_sqrt __P((double));
extern double __ieee754_acos __P((double));
extern double __ieee754_acosh __P((double));
extern double __ieee754_log __P((double));
extern double __ieee754_atanh __P((double));
extern double __ieee754_asin __P((double));
extern double __ieee754_atan2 __P((double, double));
extern double __ieee754_exp __P((double));
extern double __ieee754_cosh __P((double));
extern double __ieee754_fmod __P((double, double));
extern double __ieee754_pow __P((double, double));
extern double __ieee754_lgamma_r __P((double, int*));
extern double __ieee754_gamma_r __P((double, int*));
extern double __ieee754_lgamma __P((double));
extern double __ieee754_gamma __P((double));
extern double __ieee754_log10 __P((double));
extern double __ieee754_sinh __P((double));
extern double __ieee754_hypot __P((double, double));
extern double __ieee754_j0 __P((double));
extern double __ieee754_j1 __P((double));
extern double __ieee754_y0 __P((double));
extern double __ieee754_y1 __P((double));
extern double __ieee754_jn __P((int, double));
extern double __ieee754_yn __P((int, double));
extern double __ieee754_remainder __P((double, double));
extern int __ieee754_rem_pio2 __P((double, double*));
extern double __ieee754_scalb __P((double, int));
/* fdlibm kernel function */
extern double __kernel_standard __P((double, double, int));
extern double __kernel_sin __P((double, double, int));
extern double __kernel_cos __P((double, double));
extern double __kernel_tan __P((double, double, int));
extern int __kernel_rem_pio2 __P((double*, double*, int, int, int, const int*));

92
src/Runtime/k_cos.c Normal file
View File

@@ -0,0 +1,92 @@
/* @(#)k_cos.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* __kernel_cos( x, y )
* kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
* Input x is assumed to be bounded by ~pi/4 in magnitude.
* Input y is the tail of x.
*
* Algorithm
* 1. Since cos(-x) = cos(x), we need only to consider positive x.
* 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
* 3. cos(x) is approximated by a polynomial of degree 14 on
* [0,pi/4]
* 4 14
* cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
* where the remez error is
*
* | 2 4 6 8 10 12 14 | -58
* |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
* | |
*
* 4 6 8 10 12 14
* 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
* cos(x) = 1 - x*x/2 + r
* since cos(x+y) ~ cos(x) - sin(x)*y
* ~ cos(x) - x*y,
* a correction term is necessary in cos(x) and hence
* cos(x+y) = 1 - (x*x/2 - (r - x*y))
* For better accuracy when x > 0.3, let qx = |x|/4 with
* the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
* Then
* cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
* Note that 1-qx and (x*x/2-qx) is EXACT here, and the
* magnitude of the latter is at least a quarter of x*x/2,
* thus, reducing the rounding error in the subtraction.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
#ifdef __STDC__
double __kernel_cos(double x, double y)
#else
double __kernel_cos(x, y)
double x, y;
#endif
{
double a, hz, z, r, qx;
int ix;
ix = __HI(x) & 0x7fffffff; /* ix = |x|'s high word*/
if (ix < 0x3e400000) { /* if x < 2**27 */
if (((int)x) == 0)
return one; /* generate inexact */
}
z = x * x;
r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
if (ix < 0x3FD33333) /* if |x| < 0.3 */
return one - (0.5 * z - (z * r - x * y));
else {
if (ix > 0x3fe90000) { /* x > 0.78125 */
qx = 0.28125;
} else {
__HI(qx) = ix - 0x00200000; /* x/4 */
__LO(qx) = 0;
}
hz = 0.5 * z - qx;
a = one - qx;
return a - (hz - (z * r - x * y));
}
}

348
src/Runtime/k_rem_pio2.c Normal file
View File

@@ -0,0 +1,348 @@
/* @(#)k_rem_pio2.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
* double x[],y[]; int e0,nx,prec; int ipio2[];
*
* __kernel_rem_pio2 return the last three digits of N with
* y = x - N*pi/2
* so that |y| < pi/2.
*
* The method is to compute the integer (mod 8) and fraction parts of
* (2/pi)*x without doing the full multiplication. In general we
* skip the part of the product that are known to be a huge integer (
* more accurately, = 0 mod 8 ). Thus the number of operations are
* independent of the exponent of the input.
*
* (2/pi) is represented by an array of 24-bit integers in ipio2[].
*
* Input parameters:
* x[] The input value (must be positive) is broken into nx
* pieces of 24-bit integers in double precision format.
* x[i] will be the i-th 24 bit of x. The scaled exponent
* of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
* match x's up to 24 bits.
*
* Example of breaking a double positive z into x[0]+x[1]+x[2]:
* e0 = ilogb(z)-23
* z = scalbn(z,-e0)
* for i = 0,1,2
* x[i] = floor(z)
* z = (z-x[i])*2**24
*
*
* y[] ouput result in an array of double precision numbers.
* The dimension of y[] is:
* 24-bit precision 1
* 53-bit precision 2
* 64-bit precision 2
* 113-bit precision 3
* The actual value is the sum of them. Thus for 113-bit
* precison, one may have to do something like:
*
* long double t,w,r_head, r_tail;
* t = (long double)y[2] + (long double)y[1];
* w = (long double)y[0];
* r_head = t+w;
* r_tail = w - (r_head - t);
*
* e0 The exponent of x[0]
*
* nx dimension of x[]
*
* prec an integer indicating the precision:
* 0 24 bits (single)
* 1 53 bits (double)
* 2 64 bits (extended)
* 3 113 bits (quad)
*
* ipio2[]
* integer array, contains the (24*i)-th to (24*i+23)-th
* bit of 2/pi after binary point. The corresponding
* floating value is
*
* ipio2[i] * 2^(-24(i+1)).
*
* External function:
* double scalbn(), floor();
*
*
* Here is the description of some local variables:
*
* jk jk+1 is the initial number of terms of ipio2[] needed
* in the computation. The recommended value is 2,3,4,
* 6 for single, double, extended,and quad.
*
* jz local integer variable indicating the number of
* terms of ipio2[] used.
*
* jx nx - 1
*
* jv index for pointing to the suitable ipio2[] for the
* computation. In general, we want
* ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
* is an integer. Thus
* e0-3-24*jv >= 0 or (e0-3)/24 >= jv
* Hence jv = max(0,(e0-3)/24).
*
* jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
*
* q[] double array with integral value, representing the
* 24-bits chunk of the product of x and 2/pi.
*
* q0 the corresponding exponent of q[0]. Note that the
* exponent for q[i] would be q0-24*i.
*
* PIo2[] double precision array, obtained by cutting pi/2
* into 24 bits chunks.
*
* f[] ipio2[] in floating point
*
* iq[] integer array by breaking up q[] in 24-bits chunk.
*
* fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
*
* ih integer. If >0 it indicates q[] is >= 0.5, hence
* it also indicates the *sign* of the result.
*
*/
/*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const _INT32 init_jk[] = {2, 3, 4, 6}; /* initial value for jk */ /*- cc 020130 -*/
#else
static _INT32 init_jk[] = {2, 3, 4, 6}; /*- cc 020130 -*/
#endif
#ifdef __STDC__
static const double PIo2[] = {
#else
static double PIo2[] = {
#endif
1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
};
#ifdef __STDC__
static const double
#else
static double
#endif
zero = 0.0,
one = 1.0, two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
#ifdef __STDC__
_INT32 __kernel_rem_pio2(double* x, double* y, _INT32 e0, _INT32 nx, _INT32 prec, const _INT32* ipio2) /*- cc 020130 -*/
#else
_INT32 __kernel_rem_pio2(x, y, e0, nx, prec, ipio2) /*- cc 020130 -*/
double x[], y[];
_INT32 e0, nx, prec;
_INT32 ipio2[]; /*- cc 020130 -*/
#endif
{
_INT32 jz, jx, jv, jp, jk, carry, n, iq[20], i, j, k, m, q0, ih; /*- cc 020130 -*/
double z, fw, f[20], fq[20], q[20];
/* initialize jk*/
jk = init_jk[prec];
jp = jk;
/* determine jx,jv,q0, note that 3>q0 */
jx = nx - 1;
jv = (e0 - 3) / 24;
if (jv < 0)
jv = 0;
q0 = e0 - 24 * (jv + 1);
/* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
j = jv - jx;
m = jx + jk;
for (i = 0; i <= m; i++, j++)
f[i] = (j < 0) ? zero : (double)ipio2[j];
/* compute q[0],q[1],...q[jk] */
for (i = 0; i <= jk; i++) {
for (j = 0, fw = 0.0; j <= jx; j++)
fw += x[j] * f[jx + i - j];
q[i] = fw;
}
jz = jk;
recompute:
/* distill q[] into iq[] reversingly */
for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) {
fw = (double)((_INT32)(twon24 * z)); /*- cc 020130 -*/
iq[i] = (_INT32)(z - two24 * fw); /*- cc 020130 -*/
z = q[j - 1] + fw;
}
/* compute n */
z = scalbn(z, q0); /* actual value of z */
z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */
n = (_INT32)z; /*- cc 020130 -*/
z -= (double)n;
ih = 0;
if (q0 > 0) { /* need iq[jz-1] to determine n */
i = (iq[jz - 1] >> (24 - q0));
n += i;
iq[jz - 1] -= i << (24 - q0);
ih = iq[jz - 1] >> (23 - q0);
} else if (q0 == 0)
ih = iq[jz - 1] >> 23;
else if (z >= 0.5)
ih = 2;
if (ih > 0) { /* q > 0.5 */
n += 1;
carry = 0;
for (i = 0; i < jz; i++) { /* compute 1-q */
j = iq[i];
if (carry == 0) {
if (j != 0) {
carry = 1;
iq[i] = 0x1000000 - j;
}
} else
iq[i] = 0xffffff - j;
}
if (q0 > 0) { /* rare case: chance is 1 in 12 */
switch (q0) {
case 1:
iq[jz - 1] &= 0x7fffff;
break;
case 2:
iq[jz - 1] &= 0x3fffff;
break;
}
}
if (ih == 2) {
z = one - z;
if (carry != 0)
z -= scalbn(one, q0);
}
}
/* check if recomputation is needed */
if (z == zero) {
j = 0;
for (i = jz - 1; i >= jk; i--)
j |= iq[i];
if (j == 0) { /* need recomputation */
for (k = 1; iq[jk - k] == 0; k++)
; /* k = no. of terms needed */
for (i = jz + 1; i <= jz + k; i++) { /* add q[jz+1] to q[jz+k] */
f[jx + i] = (double)ipio2[jv + i];
for (j = 0, fw = 0.0; j <= jx; j++)
fw += x[j] * f[jx + i - j];
q[i] = fw;
}
jz += k;
goto recompute;
}
}
/* chop off zero terms */
if (z == 0.0) {
jz -= 1;
q0 -= 24;
while (iq[jz] == 0) {
jz--;
q0 -= 24;
}
} else { /* break z into 24-bit if necessary */
z = scalbn(z, -q0);
if (z >= two24) {
fw = (double)((_INT32)(twon24 * z)); /*- cc 020130 -*/
iq[jz] = (_INT32)(z - two24 * fw); /*- cc 020130 -*/
jz += 1;
q0 += 24;
iq[jz] = (_INT32)fw; /*- cc 020130 -*/
} else
iq[jz] = (_INT32)z; /*- cc 020130 -*/
}
/* convert integer "bit" chunk to floating-point value */
fw = scalbn(one, q0);
for (i = jz; i >= 0; i--) {
q[i] = fw * (double)iq[i];
fw *= twon24;
}
/* compute PIo2[0,...,jp]*q[jz,...,0] */
for (i = jz; i >= 0; i--) {
for (fw = 0.0, k = 0; k <= jp && k <= jz - i; k++)
fw += PIo2[k] * q[i + k];
fq[jz - i] = fw;
}
/* compress fq[] into y[] */
switch (prec) {
case 0:
fw = 0.0;
for (i = jz; i >= 0; i--)
fw += fq[i];
y[0] = (ih == 0) ? fw : -fw;
break;
case 1:
case 2:
fw = 0.0;
for (i = jz; i >= 0; i--)
fw += fq[i];
y[0] = (ih == 0) ? fw : -fw;
fw = fq[0] - fw;
for (i = 1; i <= jz; i++)
fw += fq[i];
y[1] = (ih == 0) ? fw : -fw;
break;
case 3: /* painful */
for (i = jz; i > 0; i--) {
fw = fq[i - 1] + fq[i];
fq[i] += fq[i - 1] - fw;
fq[i - 1] = fw;
}
for (i = jz; i > 1; i--) {
fw = fq[i - 1] + fq[i];
fq[i] += fq[i - 1] - fw;
fq[i - 1] = fw;
}
for (fw = 0.0, i = jz; i >= 2; i--)
fw += fq[i];
if (ih == 0) {
y[0] = fq[0];
y[1] = fq[1];
y[2] = fw;
} else {
y[0] = -fq[0];
y[1] = -fq[1];
y[2] = -fw;
}
}
return n & 7;
}

79
src/Runtime/k_sin.c Normal file
View File

@@ -0,0 +1,79 @@
/* @(#)k_sin.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __kernel_sin( x, y, iy)
* kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
* Input x is assumed to be bounded by ~pi/4 in magnitude.
* Input y is the tail of x.
* Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
*
* Algorithm
* 1. Since sin(-x) = -sin(x), we need only to consider positive x.
* 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
* 3. sin(x) is approximated by a polynomial of degree 13 on
* [0,pi/4]
* 3 13
* sin(x) ~ x + S1*x + ... + S6*x
* where
*
* |sin(x) 2 4 6 8 10 12 | -58
* |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
* | x |
*
* 4. sin(x+y) = sin(x) + sin'(x')*y
* ~ sin(x) + (1-x*x/2)*y
* For better accuracy, let
* 3 2 2 2 2
* r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
* then 3 2
* sin(x) = x + (S1*x + (x *(r-y/2)+y))
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
#ifdef __STDC__
double __kernel_sin(double x, double y, int iy)
#else
double __kernel_sin(x, y, iy)
double x, y;
int iy; /* iy=0 if y is zero */
#endif
{
double z, r, v;
int ix;
ix = __HI(x) & 0x7fffffff; /* high word of x */
if (ix < 0x3e400000) /* |x| < 2**-27 */
{
if ((int)x == 0)
return x;
} /* generate inexact */
z = x * x;
v = z * x;
r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
if (iy == 0)
return x + v * (S1 + z * r);
else
return x - ((z * (half * y - v * r) - y) - v * S1);
}

134
src/Runtime/k_tan.c Normal file
View File

@@ -0,0 +1,134 @@
/* @(#)k_tan.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __kernel_tan( x, y, k )
* kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
* Input x is assumed to be bounded by ~pi/4 in magnitude.
* Input y is the tail of x.
* Input k indicates whether tan (if k=1) or
* -1/tan (if k= -1) is returned.
*
* Algorithm
* 1. Since tan(-x) = -tan(x), we need only to consider positive x.
* 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
* 3. tan(x) is approximated by a odd polynomial of degree 27 on
* [0,0.67434]
* 3 27
* tan(x) ~ x + T1*x + ... + T13*x
* where
*
* |tan(x) 2 4 26 | -59.2
* |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
* | x |
*
* Note: tan(x+y) = tan(x) + tan'(x)*y
* ~ tan(x) + (1+x*x)*y
* Therefore, for better accuracy in computing tan(x+y), let
* 3 2 2 2 2
* r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
* then
* 3 2
* tan(x+y) = x + (T1*x + (x *(r+y)+y))
*
* 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
* tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
* = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
pio4lo = 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */
T[] = {
3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */
1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */
5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */
2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */
8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */
3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */
1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */
5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */
2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */
7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */
7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */
-1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */
2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */
};
#ifdef __STDC__
double __kernel_tan(double x, double y, _INT32 iy) /*- cc 020130 -*/
#else
double __kernel_tan(x, y, iy)
double x, y;
_INT32 iy; /*- cc 020130 -*/
#endif
{
double z, r, v, w, s;
_INT32 ix, hx; /*- cc 020130 -*/
hx = __HI(x); /* high word of x */
ix = hx & 0x7fffffff; /* high word of |x| */
if (ix < 0x3e300000) /* x < 2**-28 */
{
if ((_INT32)x == 0) { /* generate inexact */ /*- cc 020130 -*/
if (((ix | __LO(x)) | (iy + 1)) == 0)
return one / fabs(x);
else
return (iy == 1) ? x : -one / x;
}
}
if (ix >= 0x3FE59428) { /* |x|>=0.6744 */
if (hx < 0) {
x = -x;
y = -y;
}
z = pio4 - x;
w = pio4lo - y;
x = z + w;
y = 0.0;
}
z = x * x;
w = z * z;
/* Break x^5*(T[1]+x^2*T[2]+...) into
* x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
* x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
*/
r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11]))));
v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12])))));
s = z * x;
r = y + z * (s * (r + v) + y);
r += T[0] * s;
w = x + r;
if (ix >= 0x3FE59428) {
v = (double)iy;
return (double)(1 - ((hx >> 30) & 2)) * (v - 2.0 * (x - (w * w / (w + v) - r)));
}
if (iy == 1)
return w;
else { /* if allow error up to 2 ulp,
simply return -1.0/(x+r) here */
/* compute -1.0/(x+r) accurately */
double a, t;
z = w;
__LO(z) = 0;
v = r - (z - x); /* z+v = r+x */
t = a = -1.0 / w; /* a = -1.0/w */
__LO(t) = 0;
s = 1.0 + t * z;
return t + a * (s + t * v);
}
}

33
src/Runtime/locale.c Normal file
View File

@@ -0,0 +1,33 @@
#include <limits.h>
#include <locale.h>
struct lconv __lconv = {
".", // decimal_point
"", // thousands_sep
"", // grouping
"", // mon_decimal_point
"", // mon_thousands_sep
"", // mon_grouping
"", // positive_sign
"", // negative_sign
"", // currency_symbol
CHAR_MAX, // frac_digits
CHAR_MAX, // p_cs_precedes
CHAR_MAX, // n_cs_precedes
CHAR_MAX, // p_sep_by_space
CHAR_MAX, // n_sep_by_space
CHAR_MAX, // p_sign_posn
CHAR_MAX, // n_sign_posn
"", // int_curr_symbol
CHAR_MAX, // int_frac_digits
CHAR_MAX, // int_p_cs_precedes
CHAR_MAX, // int_n_cs_precedes
CHAR_MAX, // int_p_sep_by_space
CHAR_MAX, // int_n_sep_by_space
CHAR_MAX, // int_p_sign_posn
CHAR_MAX, // int_n_sign_posn
};
// Just here to generate the extra string,
// the real usage is inside setlocale, which is stripped
static char* locale_name = "C";

3
src/Runtime/math_ppc.c Normal file
View File

@@ -0,0 +1,3 @@
#include <math.h>
float cosf(float x) { return (float)cos((double)x); }

70
src/Runtime/mem.c Normal file
View File

@@ -0,0 +1,70 @@
#include <string.h>
#include "mem_funcs.h"
void* memmove(void* dst, const void* src, size_t n) {
const char* p;
char* q;
int rev = ((unsigned long)src < (unsigned long)dst);
if (n >= __min_bytes_for_long_copy) {
if ((((int)dst ^ (int)src)) & 3)
if (!rev)
__copy_longs_unaligned(dst, src, n);
else
__copy_longs_rev_unaligned(dst, src, n);
else if (!rev)
__copy_longs_aligned(dst, src, n);
else
__copy_longs_rev_aligned(dst, src, n);
return dst;
}
if (!rev) {
for (p = (const char*)src - 1, q = (char*)dst - 1, n++; --n;)
*++q = *++p;
} else {
for (p = (const char*)src + n, q = (char*)dst + n, n++; --n;)
*--q = *--p;
}
return dst;
}
void* memchr(const void* src, int val, size_t n) {
const unsigned char* p;
unsigned long v = (val & 0xff);
for (p = (unsigned char*)src - 1, n++; --n;)
if ((*++p & 0xff) == v)
return (void*)p;
return NULL;
}
void* __memrchr(const void* src, int val, size_t n) {
const unsigned char* p;
unsigned long v = (val & 0xff);
for (p = (unsigned char*)src + n, n++; --n;)
if (*--p == v)
return (void*)p;
return NULL;
}
int memcmp(const void* src1, const void* src2, size_t n) {
const unsigned char* p1;
const unsigned char* p2;
for (p1 = (const unsigned char*)src1 - 1, p2 = (const unsigned char*)src2 - 1, n++; --n;)
if (*++p1 != *++p2)
return ((*p1 < *p2) ? -1 : +1);
return 0;
}

223
src/Runtime/mem_funcs.c Normal file
View File

@@ -0,0 +1,223 @@
#include "mem_funcs.h"
// #pragma ANSI_strict off
#define cps ((unsigned char*)src)
#define cpd ((unsigned char*)dst)
#define lps ((unsigned long*)src)
#define lpd ((unsigned long*)dst)
#define deref_auto_inc(p) *++(p)
void __copy_longs_aligned(void* dst, const void* src, unsigned long n) {
unsigned long i;
i = (-(unsigned long)dst) & 3;
cps = ((unsigned char*)src) - 1;
cpd = ((unsigned char*)dst) - 1;
if (i) {
n -= i;
do
deref_auto_inc(cpd) = deref_auto_inc(cps);
while (--i);
}
lps = ((unsigned long*)(cps + 1)) - 1;
lpd = ((unsigned long*)(cpd + 1)) - 1;
i = n >> 5;
if (i)
do {
deref_auto_inc(lpd) = deref_auto_inc(lps);
deref_auto_inc(lpd) = deref_auto_inc(lps);
deref_auto_inc(lpd) = deref_auto_inc(lps);
deref_auto_inc(lpd) = deref_auto_inc(lps);
deref_auto_inc(lpd) = deref_auto_inc(lps);
deref_auto_inc(lpd) = deref_auto_inc(lps);
deref_auto_inc(lpd) = deref_auto_inc(lps);
deref_auto_inc(lpd) = deref_auto_inc(lps);
} while (--i);
i = (n & 31) >> 2;
if (i)
do
deref_auto_inc(lpd) = deref_auto_inc(lps);
while (--i);
cps = ((unsigned char*)(lps + 1)) - 1;
cpd = ((unsigned char*)(lpd + 1)) - 1;
// TODO longlong required to match?
n &= 3ULL;
if (n)
do
deref_auto_inc(cpd) = deref_auto_inc(cps);
while (--n);
return;
}
void __copy_longs_rev_aligned(void* dst, const void* src, unsigned long n) {
unsigned long i;
cps = ((unsigned char*)src) + n;
cpd = ((unsigned char*)dst) + n;
i = ((unsigned long)cpd) & 3;
if (i) {
n -= i;
do
*--cpd = *--cps;
while (--i);
}
i = n >> 5;
if (i)
do {
*--lpd = *--lps;
*--lpd = *--lps;
*--lpd = *--lps;
*--lpd = *--lps;
*--lpd = *--lps;
*--lpd = *--lps;
*--lpd = *--lps;
*--lpd = *--lps;
} while (--i);
i = (n & 31) >> 2;
if (i)
do
*--lpd = *--lps;
while (--i);
// TODO longlong required to match?
n &= 3ULL;
if (n)
do
*--cpd = *--cps;
while (--n);
return;
}
void __copy_longs_unaligned(void* dst, const void* src, unsigned long n) {
unsigned long i, v1, v2;
unsigned int src_offset, left_shift, right_shift;
i = (-(unsigned long)dst) & 3;
cps = ((unsigned char*)src) - 1;
cpd = ((unsigned char*)dst) - 1;
if (i) {
n -= i;
do
deref_auto_inc(cpd) = deref_auto_inc(cps);
while (--i);
}
src_offset = ((unsigned int)(cps + 1)) & 3;
left_shift = src_offset << 3;
right_shift = 32 - left_shift;
cps -= src_offset;
lps = ((unsigned long*)(cps + 1)) - 1;
lpd = ((unsigned long*)(cpd + 1)) - 1;
i = n >> 3;
v1 = deref_auto_inc(lps);
do {
v2 = deref_auto_inc(lps);
deref_auto_inc(lpd) = (v1 << left_shift) | (v2 >> right_shift);
v1 = deref_auto_inc(lps);
deref_auto_inc(lpd) = (v2 << left_shift) | (v1 >> right_shift);
} while (--i);
if (n & 4) {
v2 = deref_auto_inc(lps);
deref_auto_inc(lpd) = (v1 << left_shift) | (v2 >> right_shift);
}
cps = ((unsigned char*)(lps + 1)) - 1;
cpd = ((unsigned char*)(lpd + 1)) - 1;
// TODO longlong required to match?
n &= 3ULL;
if (n) {
cps -= 4 - src_offset;
do
deref_auto_inc(cpd) = deref_auto_inc(cps);
while (--n);
}
return;
}
void __copy_longs_rev_unaligned(void* dst, const void* src, unsigned long n) {
unsigned long i, v1, v2;
unsigned int src_offset, left_shift, right_shift;
cps = ((unsigned char*)src) + n;
cpd = ((unsigned char*)dst) + n;
i = ((unsigned long)cpd) & 3;
if (i) {
n -= i;
do
*--cpd = *--cps;
while (--i);
}
src_offset = ((unsigned int)cps) & 3;
left_shift = src_offset << 3;
right_shift = 32 - left_shift;
cps += 4 - src_offset;
i = n >> 3;
v1 = *--lps;
do {
v2 = *--lps;
*--lpd = (v2 << left_shift) | (v1 >> right_shift);
v1 = *--lps;
*--lpd = (v1 << left_shift) | (v2 >> right_shift);
} while (--i);
if (n & 4) {
v2 = *--lps;
*--lpd = (v2 << left_shift) | (v1 >> right_shift);
}
// TODO longlong required to match?
n &= 3ULL;
if (n) {
cps += src_offset;
do
*--cpd = *--cps;
while (--n);
}
return;
}

4
src/Runtime/misc_io.c Normal file
View File

@@ -0,0 +1,4 @@
extern void (*__stdio_exit)(void);
void __close_all(void);
void __stdio_atexit(void) { __stdio_exit = __close_all; }

75
src/Runtime/qsort.c Normal file
View File

@@ -0,0 +1,75 @@
#include <stdlib.h>
#define table_ptr(i) (((char*)table_base) + (member_size * ((i)-1)))
#define swap(dst, src, cnt) \
do { \
char* p; \
char* q; \
size_t n = cnt; \
\
unsigned long tmp; \
\
for (p = (char*)src - 1, q = (char*)dst - 1, n++; --n;) { \
tmp = *++q; \
*q = *++p; \
*p = tmp; \
} \
} while (0)
void qsort(void* table_base, size_t num_members, size_t member_size, _compare_function compare_members) {
size_t l, r, j;
char* lp;
char* rp;
char* ip;
char* jp;
char* kp;
if (num_members < 2)
return;
r = num_members;
l = (r / 2) + 1;
lp = table_ptr(l);
rp = table_ptr(r);
for (;;) {
if (l > 1) {
l--;
lp -= member_size;
} else {
swap(lp, rp, member_size);
if (--r == 1)
return;
rp -= member_size;
}
j = l;
jp = table_ptr(j);
while (j * 2 <= r) {
j *= 2;
ip = jp;
jp = table_ptr(j);
if (j < r) {
kp = jp + member_size;
if (compare_members(jp, kp) < 0) {
j++;
jp = kp;
}
}
if (compare_members(ip, jp) < 0)
swap(ip, jp, member_size);
else
break;
}
}
}

10
src/Runtime/rand.c Normal file
View File

@@ -0,0 +1,10 @@
#include <stdlib.h>
static unsigned long int next = 1;
int rand(void) {
next = next * 1103515245 + 12345;
return (next >> 16) & 0x7FFF;
}
void srand(unsigned int seed) { next = seed; }

142
src/Runtime/s_atan.c Normal file
View File

@@ -0,0 +1,142 @@
/* @(#)s_atan.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
*/
/* atan(x)
* Method
* 1. Reduce x to positive by atan(x) = -atan(-x).
* 2. According to the integer k=4t+0.25 chopped, t=x, the argument
* is further reduced to one of the following intervals and the
* arctangent of t is evaluated by the corresponding formula:
*
* [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
* [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
* [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
* [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
* [39/16,INF] atan(x) = atan(INF) + atan( -1/t )
*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double atanhi[] = {
#else
static double atanhi[] = {
#endif
4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
};
#ifdef __STDC__
static const double atanlo[] = {
#else
static double atanlo[] = {
#endif
2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
};
#ifdef __STDC__
static const double aT[] = {
#else
static double aT[] = {
#endif
3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
-1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
-1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
-7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
-5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
-3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
};
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.0,
big = 1.0e300;
#ifdef __STDC__
double atan(double x)
#else
double atan(x)
double x;
#endif
{
double w, s1, s2, z;
_INT32 ix, hx, id; /*- cc 020130 -*/
hx = __HI(x);
ix = hx & 0x7fffffff;
if (ix >= 0x44100000) { /* if |x| >= 2^66 */
if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (__LO(x) != 0)))
return x + x; /* NaN */
if (hx > 0)
return atanhi[3] + atanlo[3];
else
return -atanhi[3] - atanlo[3];
}
if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
if (ix < 0x3e200000) { /* |x| < 2^-29 */
if (big + x > one)
return x; /* raise inexact */
}
id = -1;
} else {
x = fabs(x);
if (ix < 0x3ff30000) { /* |x| < 1.1875 */
if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
id = 0;
x = (2.0 * x - one) / (2.0 + x);
} else { /* 11/16<=|x|< 19/16 */
id = 1;
x = (x - one) / (x + one);
}
} else {
if (ix < 0x40038000) { /* |x| < 2.4375 */
id = 2;
x = (x - 1.5) / (one + 1.5 * x);
} else { /* 2.4375 <= |x| < 2^66 */
id = 3;
x = -1.0 / x;
}
}
}
/* end of argument reduction */
z = x * x;
w = z * z;
/* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
s1 = z * (aT[0] + w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10])))));
s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
if (id < 0)
return x - x * (s1 + s2);
else {
z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
return (hx < 0) ? -z : z;
}
}

30
src/Runtime/s_copysign.c Normal file
View File

@@ -0,0 +1,30 @@
/* @(#)s_copysign.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* copysign(double x, double y)
* copysign(x,y) returns a value with the magnitude of x and
* with the sign bit of y.
*/
#include "fdlibm.h"
#ifdef __STDC__
double copysign(double x, double y)
#else
double __copysign(x, y)
double x, y;
#endif
{
__HI(x) = (__HI(x) & 0x7fffffff) | (__HI(y) & 0x80000000);
return x;
}

75
src/Runtime/s_cos.c Normal file
View File

@@ -0,0 +1,75 @@
/* @(#)s_cos.c 1.3 95/01/18 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* cos(x)
* Return cosine function of x.
*
* kernel function:
* __kernel_sin ... sine function on [-pi/4,pi/4]
* __kernel_cos ... cosine function on [-pi/4,pi/4]
* __ieee754_rem_pio2 ... argument reduction routine
*
* Method.
* Let S,C and T denote the sin, cos and tan respectively on
* [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
* in [-pi/4 , +pi/4], and let n = k mod 4.
* We have
*
* n sin(x) cos(x) tan(x)
* ----------------------------------------------------------
* 0 S C T
* 1 C -S -1/T
* 2 -S -C T
* 3 -C S -1/T
* ----------------------------------------------------------
*
* Special cases:
* Let trig be any of sin, cos, or tan.
* trig(+-INF) is NaN, with signals;
* trig(NaN) is that NaN;
*
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
#include "fdlibm.h"
#ifdef __STDC__
double cos(double x)
#else
double cos(x)
double x;
#endif
{
double y[2], z = 0.0;
int n, ix;
/* High word of x. */
ix = __HI(x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if (ix <= 0x3fe921fb)
return __kernel_cos(x, z);
/* cos(Inf or NaN) is NaN */
else if (ix >= 0x7ff00000)
return x - x;
/* argument reduction needed */
else {
n = __ieee754_rem_pio2(x, y);
switch (n & 3) {
case 0:
return __kernel_cos(y[0], y[1]);
case 1:
return -__kernel_sin(y[0], y[1], 1);
case 2:
return -__kernel_cos(y[0], y[1]);
default:
return __kernel_sin(y[0], y[1], 1);
}
}
}

87
src/Runtime/s_floor.c Normal file
View File

@@ -0,0 +1,87 @@
/* @(#)s_floor.c 1.3 95/01/18 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* floor(x)
* Return x rounded toward -inf to integral value
* Method:
* Bit twiddling.
* Exception:
* Inexact flag raised if x not equal to floor(x).
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double huge = 1.0e300;
#else
static double huge = 1.0e300;
#endif
#ifdef __STDC__
double floor(double x)
#else
double floor(x)
double x;
#endif
{
int i0, i1, j0;
unsigned i, j;
i0 = __HI(x);
i1 = __LO(x);
j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
if (j0 < 20) {
if (j0 < 0) { /* raise inexact if x != 0 */
if (huge + x > 0.0) { /* return 0*sign(x) if |x|<1 */
if (i0 >= 0) {
i0 = i1 = 0;
} else if (((i0 & 0x7fffffff) | i1) != 0) {
i0 = 0xbff00000;
i1 = 0;
}
}
} else {
i = (0x000fffff) >> j0;
if (((i0 & i) | i1) == 0)
return x; /* x is integral */
if (huge + x > 0.0) { /* raise inexact flag */
if (i0 < 0)
i0 += (0x00100000) >> j0;
i0 &= (~i);
i1 = 0;
}
}
} else if (j0 > 51) {
if (j0 == 0x400)
return x + x; /* inf or NaN */
else
return x; /* x is integral */
} else {
i = ((unsigned)(0xffffffff)) >> (j0 - 20);
if ((i1 & i) == 0)
return x; /* x is integral */
if (huge + x > 0.0) { /* raise inexact flag */
if (i0 < 0) {
if (j0 == 20)
i0 += 1;
else {
j = i1 + (1 << (52 - j0));
if (j < i1)
i0 += 1; /* got a carry */
i1 = j;
}
}
i1 &= (~i);
}
}
__HI(x) = i0;
__LO(x) = i1;
return x;
}

57
src/Runtime/s_frexp.c Normal file
View File

@@ -0,0 +1,57 @@
/* @(#)s_frexp.c 1.3 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* for non-zero x
* x = frexp(arg,&exp);
* return a double fp quantity x such that 0.5 <= |x| <1.0
* and the corresponding binary exponent "exp". That is
* arg = x*2^exp.
* If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg
* with *exp=0.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
#ifdef __STDC__
double frexp(double x, int* eptr)
#else
double frexp(x, eptr)
double x;
int* eptr;
#endif
{
int hx, ix, lx;
hx = __HI(x);
ix = 0x7fffffff & hx;
lx = __LO(x);
*eptr = 0;
if (ix >= 0x7ff00000 || ((ix | lx) == 0))
return x; /* 0,inf,nan */
if (ix < 0x00100000) { /* subnormal */
x *= two54;
hx = __HI(x);
ix = hx & 0x7fffffff;
*eptr = -54;
}
*eptr += (ix >> 20) - 1022;
hx = (hx & 0x800fffff) | 0x3fe00000;
__HI(x) = hx;
return x;
}

54
src/Runtime/s_ldexp.c Normal file
View File

@@ -0,0 +1,54 @@
/* @(#)s_ldexp.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#include "fdlibm.h"
static const double two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
big = 1.0e+300, tiny = 1.0e-300;
double ldexp(double x, int n) {
_INT32 k, hx, lx; /*- cc 020130 -*/
if (!isfinite(x) || x == 0.0)
return x;
hx = __HI(x);
lx = __LO(x);
k = (hx & 0x7ff00000) >> 20; /* extract exponent */
if (k == 0) { /* 0 or subnormal x */
if ((lx | (hx & 0x7fffffff)) == 0)
return x; /* +-0 */
x *= two54;
hx = __HI(x);
k = ((hx & 0x7ff00000) >> 20) - 54;
if (n < -50000)
return tiny * x; /*underflow*/
}
if (k == 0x7ff)
return x + x; /* NaN or Inf */
k = k + n;
if (k > 0x7fe)
return big * copysign(big, x); /* overflow */
if (k > 0) /* normal result */
{
__HI(x) = (hx & 0x800fffff) | (k << 20);
return x;
}
if (k <= -54)
if (n > 50000) /* in case integer overflow in n+k */
return big * copysign(big, x); /*overflow*/
else
return tiny * copysign(tiny, x); /*underflow*/
k += 54; /* subnormal result */
__HI(x) = (hx & 0x800fffff) | (k << 20);
return x * twom54;
}

79
src/Runtime/s_modf.c Normal file
View File

@@ -0,0 +1,79 @@
/* @(#)s_modf.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* modf(double x, double *iptr)
* return fraction part of x, and return x's integral part in *iptr.
* Method:
* Bit twiddling.
*
* Exception:
* No exception.
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double one = 1.0;
#else
static double one = 1.0;
#endif
#ifdef __STDC__
double modf(double x, double* iptr)
#else
double modf(x, iptr)
double x, *iptr;
#endif
{
_INT32 i0, i1, j0; /*- cc 020130 -*/
_UINT32 i; /*- cc 020130 -*/
i0 = __HI(x); /* high x */
i1 = __LO(x); /* low x */
j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; /* exponent of x */
if (j0 < 20) { /* integer part in high x */
if (j0 < 0) { /* |x|<1 */
__HIp(iptr) = i0 & 0x80000000;
__LOp(iptr) = 0; /* *iptr = +-0 */
return x;
} else {
i = (0x000fffff) >> j0;
if (((i0 & i) | i1) == 0) { /* x is integral */
*iptr = x;
__HI(x) &= 0x80000000;
__LO(x) = 0; /* return +-0 */
return x;
} else {
__HIp(iptr) = i0 & (~i);
__LOp(iptr) = 0;
return x - *iptr;
}
}
} else if (j0 > 51) { /* no fraction part */
*iptr = x * one;
__HI(x) &= 0x80000000;
__LO(x) = 0; /* return +-0 */
return x;
} else { /* fraction part in low x */
i = ((_UINT32)(0xffffffff)) >> (j0 - 20); /*- cc 020130 -*/
if ((i1 & i) == 0) { /* x is integral */
*iptr = x;
__HI(x) &= 0x80000000;
__LO(x) = 0; /* return +-0 */
return x;
} else {
__HIp(iptr) = i0;
__LOp(iptr) = i1 & (~i);
return x - *iptr;
}
}
}

88
src/Runtime/s_nextafter.c Normal file
View File

@@ -0,0 +1,88 @@
/* @(#)s_nextafter.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* IEEE functions
* nextafter(x,y)
* return the next machine floating-point number of x in the
* direction toward y.
* Special cases:
*/
#include "fdlibm.h"
#ifdef __STDC__
double nextafter(double x, double y)
#else
double nextafter(x, y)
double x, y;
#endif
{
_INT32 hx, hy, ix, iy; /*- cc 020130 -*/
_UINT32 lx, ly; /*- cc 020130 -*/
hx = __HI(x); /* high word of x */
lx = __LO(x); /* low word of x */
hy = __HI(y); /* high word of y */
ly = __LO(y); /* low word of y */
ix = hx & 0x7fffffff; /* |x| */
iy = hy & 0x7fffffff; /* |y| */
if (((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0) || /* x is nan */
((iy >= 0x7ff00000) && ((iy - 0x7ff00000) | ly) != 0)) /* y is nan */
return x + y;
if (x == y)
return x; /* x=y, return x */
if ((ix | lx) == 0) { /* x == 0 */
__HI(x) = hy & 0x80000000; /* return +-minsubnormal */
__LO(x) = 1;
y = x * x;
if (y == x)
return y;
else
return x; /* raise underflow flag */
}
if (hx >= 0) { /* x > 0 */
if (hx > hy || ((hx == hy) && (lx > ly))) { /* x > y, x -= ulp */
if (lx == 0)
hx -= 1;
lx -= 1;
} else { /* x < y, x += ulp */
lx += 1;
if (lx == 0)
hx += 1;
}
} else { /* x < 0 */
if (hy >= 0 || hx > hy || ((hx == hy) && (lx > ly))) { /* x < y, x -= ulp */
if (lx == 0)
hx -= 1;
lx -= 1;
} else { /* x > y, x += ulp */
lx += 1;
if (lx == 0)
hx += 1;
}
}
hy = hx & 0x7ff00000;
if (hy >= 0x7ff00000)
return x + x; /* overflow */
if (hy < 0x00100000) { /* underflow */
y = x * x;
if (y != x) { /* raise underflow flag */
__HI(y) = hx;
__LO(y) = lx;
return y;
}
}
__HI(x) = hx;
__LO(x) = lx;
return x;
}

84
src/Runtime/s_sin.c Normal file
View File

@@ -0,0 +1,84 @@
/* @(#)s_sin.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* sin(x)
* Return sine function of x.
*
* kernel function:
* __kernel_sin ... sine function on [-pi/4,pi/4]
* __kernel_cos ... cose function on [-pi/4,pi/4]
* __ieee754_rem_pio2 ... argument reduction routine
*
* Method.
* Let S,C and T denote the sin, cos and tan respectively on
* [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
* in [-pi/4 , +pi/4], and let n = k mod 4.
* We have
*
* n sin(x) cos(x) tan(x)
* ----------------------------------------------------------
* 0 S C T
* 1 C -S -1/T
* 2 -S -C T
* 3 -C S -1/T
* ----------------------------------------------------------
*
* Special cases:
* Let trig be any of sin, cos, or tan.
* trig(+-INF) is NaN, with signals;
* trig(NaN) is that NaN;
*
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
#include "fdlibm.h"
#ifdef __STDC__
double sin(double x)
#else
double sin(x)
double x;
#endif
{
double y[2], z = 0.0;
int n, ix;
/* High word of x. */
ix = __HI(x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if (ix <= 0x3fe921fb)
return __kernel_sin(x, z, 0);
/* sin(Inf or NaN) is NaN */
else if (ix >= 0x7ff00000)
return x - x;
/* argument reduction needed */
else {
n = __ieee754_rem_pio2(x, y);
switch (n & 3) {
case 0:
return __kernel_sin(y[0], y[1], 1);
case 1:
return __kernel_cos(y[0], y[1]);
case 2:
return -__kernel_sin(y[0], y[1], 1);
default:
return -__kernel_cos(y[0], y[1]);
}
}
}

73
src/Runtime/s_tan.c Normal file
View File

@@ -0,0 +1,73 @@
/* @(#)s_tan.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* tan(x)
* Return tangent function of x.
*
* kernel function:
* __kernel_tan ... tangent function on [-pi/4,pi/4]
* __ieee754_rem_pio2 ... argument reduction routine
*
* Method.
* Let S,C and T denote the sin, cos and tan respectively on
* [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
* in [-pi/4 , +pi/4], and let n = k mod 4.
* We have
*
* n sin(x) cos(x) tan(x)
* ----------------------------------------------------------
* 0 S C T
* 1 C -S -1/T
* 2 -S -C T
* 3 -C S -1/T
* ----------------------------------------------------------
*
* Special cases:
* Let trig be any of sin, cos, or tan.
* trig(+-INF) is NaN, with signals;
* trig(NaN) is that NaN;
*
* Accuracy:
* TRIG(x) returns trig(x) nearly rounded
*/
#include "fdlibm.h"
#ifdef __STDC__
double tan(double x)
#else
double tan(x)
double x;
#endif
{
double y[2], z = 0.0;
_INT32 n, ix; /*- cc 020130 -*/
/* High word of x. */
ix = __HI(x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if (ix <= 0x3fe921fb)
return __kernel_tan(x, z, 1);
/* tan(Inf or NaN) is NaN */
else if (ix >= 0x7ff00000)
return x - x; /* NaN */
/* argument reduction needed */
else {
n = __ieee754_rem_pio2(x, y);
return __kernel_tan(y[0], y[1], 1 - ((n & 1) << 1)); /* 1 -- n even
-1 -- n odd */
}
}

39
src/Runtime/w_acos.c Normal file
View File

@@ -0,0 +1,39 @@
/* @(#)w_acos.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* wrap_acos(x)
*/
#include "fdlibm.h"
#ifdef __STDC__
double acos(double x) /* wrapper acos */
#else
double acos(x) /* wrapper acos */
double x;
#endif
{
#ifdef _IEEE_LIBM
return __ieee754_acos(x);
#else
double z;
z = __ieee754_acos(x);
if (_LIB_VERSION == _IEEE_ || isnan(x))
return z;
if (fabs(x) > 1.0) {
return __kernel_standard(x, x, 1); /* acos(|x|>1) */
} else
return z;
#endif
}

40
src/Runtime/w_asin.c Normal file
View File

@@ -0,0 +1,40 @@
/* @(#)w_asin.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
*/
/*
* wrapper asin(x)
*/
#include "fdlibm.h"
#ifdef __STDC__
double asin(double x) /* wrapper asin */
#else
double asin(x) /* wrapper asin */
double x;
#endif
{
#ifdef _IEEE_LIBM
return __ieee754_asin(x);
#else
double z;
z = __ieee754_asin(x);
if (_LIB_VERSION == _IEEE_ || isnan(x))
return z;
if (fabs(x) > 1.0) {
return __kernel_standard(x, x, 2); /* asin(|x|>1) */
} else
return z;
#endif
}

40
src/Runtime/w_atan2.c Normal file
View File

@@ -0,0 +1,40 @@
/* @(#)w_atan2.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
*/
/*
* wrapper atan2(y,x)
*/
#include "fdlibm.h"
#ifdef __STDC__
double atan2(double y, double x) /* wrapper atan2 */
#else
double atan2(y, x) /* wrapper atan2 */
double y, x;
#endif
{
#ifdef _IEEE_LIBM
return __ieee754_atan2(y, x);
#else
double z;
z = __ieee754_atan2(y, x);
if (_LIB_VERSION == _IEEE_ || isnan(x) || isnan(y))
return z;
if (x == 0.0 && y == 0.0) {
return __kernel_standard(y, x, 3); /* atan2(+-0,+-0) */
} else
return z;
#endif
}

49
src/Runtime/w_exp.c Normal file
View File

@@ -0,0 +1,49 @@
/* @(#)w_exp.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* wrapper exp(x)
*/
#include "fdlibm.h"
#ifdef __STDC__
static const double
#else
static double
#endif
o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
u_threshold = -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */
#ifdef __STDC__
double exp(double x) /* wrapper pow */
#else
double exp(x) /* wrapper exp */
double x;
#endif
{
#ifdef _IEEE_LIBM
return __ieee754_exp(x);
#else
double z;
z = __ieee754_exp(x);
if (_LIB_VERSION == _IEEE_)
return z;
if (isfinite(x)) {
if (x > o_threshold)
return __kernel_standard(x, x, 6); /* exp overflow */
else if (x < u_threshold)
return __kernel_standard(x, x, 7); /* exp underflow */
}
return z;
#endif
}

38
src/Runtime/w_fmod.c Normal file
View File

@@ -0,0 +1,38 @@
/* @(#)w_fmod.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* wrapper fmod(x,y)
*/
#include "fdlibm.h"
#ifdef __STDC__
double fmod(double x, double y) /* wrapper fmod */
#else
double fmod(x, y) /* wrapper fmod */
double x, y;
#endif
{
#ifdef _IEEE_LIBM
return __ieee754_fmod(x, y);
#else
double z;
z = __ieee754_fmod(x, y);
if (_LIB_VERSION == _IEEE_ || isnan(y) || isnan(x))
return z;
if (y == 0.0) {
return __kernel_standard(x, y, 27); /* fmod(x,0) */
} else
return z;
#endif
}

38
src/Runtime/w_log.c Normal file
View File

@@ -0,0 +1,38 @@
/* @(#)w_log.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* wrapper log(x)
*/
#include "fdlibm.h"
#ifdef __STDC__
double log(double x) /* wrapper pow */
#else
double log(x) /* wrapper log */
double x;
#endif
{
#ifdef _IEEE_LIBM
return __ieee754_log(x);
#else
double z;
z = __ieee754_log(x);
if (_LIB_VERSION == _IEEE_ || isnan(x) || x > 0.0)
return z;
if (x == 0.0)
return __kernel_standard(x, x, 16); /* log(0) */
else
return __kernel_standard(x, x, 17); /* log(x<0) */
#endif
}

58
src/Runtime/w_pow.c Normal file
View File

@@ -0,0 +1,58 @@
/* @(#)w_pow.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* wrapper pow(x,y) return x**y
*/
#include "fdlibm.h"
#ifdef __STDC__
double pow(double x, double y) /* wrapper pow */
#else
double pow(x, y) /* wrapper pow */
double x, y;
#endif
{
#ifdef _IEEE_LIBM
return __ieee754_pow(x, y);
#else
double z;
z = __ieee754_pow(x, y);
if (_LIB_VERSION == _IEEE_ || isnan(y))
return z;
if (isnan(x)) {
if (y == 0.0)
return __kernel_standard(x, y, 42); /* pow(NaN,0.0) */
else
return z;
}
if (x == 0.0) {
if (y == 0.0)
return __kernel_standard(x, y, 20); /* pow(0.0,0.0) */
if (isfinite(y) && y < 0.0)
return __kernel_standard(x, y, 23); /* pow(0.0,negative) */
return z;
}
if (!isfinite(z)) {
if (isfinite(x) && isfinite(y)) {
if (isnan(z))
return __kernel_standard(x, y, 24); /* pow neg**non-int */
else
return __kernel_standard(x, y, 21); /* pow overflow */
}
}
if (z == 0.0 && isfinite(x) && isfinite(y))
return __kernel_standard(x, y, 22); /* pow underflow */
return z;
#endif
}

28
src/Runtime/wchar_io.c Normal file
View File

@@ -0,0 +1,28 @@
#include <stdio.h>
int fwide(FILE* stream, int mode) {
int orientation;
int result;
if ((stream == NULL) || (stream->mode.file_kind == __closed_file))
return 0;
orientation = stream->mode.file_orientation;
switch (orientation) {
case __unoriented:
if (mode > 0)
stream->mode.file_orientation = __wide_oriented;
else if (mode < 0)
stream->mode.file_orientation = __char_oriented;
result = mode;
break;
case __wide_oriented:
result = 1;
break;
case __char_oriented:
result = -1;
break;
}
return result;
}