mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Improved support for freestanding.
This commit is contained in:
committed by
Christoffer Lerno
parent
f37f779e5a
commit
a22ebbb0ef
@@ -1,7 +1,14 @@
|
||||
module std::io::os;
|
||||
import libc;
|
||||
|
||||
$if (env::OS_TYPE == OsType.WIN32):
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn String! getcwd(Allocator* allocator = mem::default_allocator())
|
||||
{
|
||||
unreachable("'getcwd' not available");
|
||||
}
|
||||
|
||||
$elif (env::OS_TYPE == OsType.WIN32):
|
||||
|
||||
extern fn Char16* _wgetcwd(Char16* buffer, int maxlen);
|
||||
extern fn usz wcslen(Char16* str);
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
module libc;
|
||||
|
||||
|
||||
// stdlib
|
||||
|
||||
|
||||
// Constants need to be per os/arch
|
||||
const int EXIT_FAILURE = 1;
|
||||
const int EXIT_SUCCESS = 0;
|
||||
@@ -24,8 +21,6 @@ struct LongDivResult
|
||||
long rem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn Errno errno()
|
||||
{
|
||||
return (Errno)os::errno();
|
||||
@@ -38,6 +33,10 @@ fn void errno_set(Errno e)
|
||||
|
||||
define TerminateFunction = fn void();
|
||||
define CompareFunction = fn int(void*, void*);
|
||||
define JmpBuf = CInt[$$JMP_BUF_SIZE];
|
||||
|
||||
$if (env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
extern fn double atof(char* str);
|
||||
extern fn int atoi(char* str);
|
||||
extern fn CLongLong atoll(char* str);
|
||||
@@ -58,8 +57,6 @@ extern fn LongDivResult ldiv(long number, long denom);
|
||||
extern fn int rand();
|
||||
extern fn void srand(uint seed);
|
||||
|
||||
define JmpBuf = CInt[$$JMP_BUF_SIZE];
|
||||
|
||||
extern fn void longjmp(JmpBuf* buffer, CInt value);
|
||||
$if (env::OS_TYPE == OsType.WIN32):
|
||||
// TODO win32 aarch64
|
||||
@@ -75,7 +72,7 @@ extern fn void* memchr(void* str, int c, usz n);
|
||||
extern fn int memcmp(void* str1, void* str2, usz n);
|
||||
extern fn void* memcpy(void* dest, void* src, usz n);
|
||||
extern fn void* memmove(void* dest, void* src, usz n);
|
||||
extern fn void* memset(void* dest, usz n);
|
||||
extern fn void* memset(void* dest, CInt value, usz n);
|
||||
extern fn char* strcat(char* dest, char* src);
|
||||
extern fn char* strncat(char* dest, char* src, usz n);
|
||||
extern fn char* strchr(char* str, int c);
|
||||
@@ -99,13 +96,61 @@ extern fn void* calloc(usz count, usz size);
|
||||
extern fn void* free(void*);
|
||||
extern fn void* realloc(void* ptr, usz size);
|
||||
|
||||
$else:
|
||||
|
||||
fn void longjmp(JmpBuf* buffer, CInt value) @weak @extname("longjmp")
|
||||
{
|
||||
unreachable("longjmp unavailable");
|
||||
}
|
||||
|
||||
fn CInt setjmp(JmpBuf* buffer) @weak @extname("setjmp")
|
||||
{
|
||||
unreachable("setjmp unavailable");
|
||||
}
|
||||
|
||||
fn void* malloc(usz size) @weak @extname("malloc")
|
||||
{
|
||||
unreachable("malloc unavailable");
|
||||
}
|
||||
fn void* calloc(usz count, usz size) @weak @extname("calloc")
|
||||
{
|
||||
unreachable("calloc unavailable");
|
||||
}
|
||||
fn void* free(void*) @weak @extname("free")
|
||||
{
|
||||
unreachable("free unavailable");
|
||||
}
|
||||
|
||||
fn void* realloc(void* ptr, usz size) @weak @extname("realloc")
|
||||
{
|
||||
unreachable("realloc unavailable");
|
||||
}
|
||||
|
||||
fn void* memcpy(void* dest, void* src, usz n) @weak @extname("memcpy")
|
||||
{
|
||||
for (usz i = 0; i < n; i++) ((char*)dest)[i] = ((char*)src)[i];
|
||||
return dest;
|
||||
}
|
||||
|
||||
fn void* memmove(void* dest, void* src, usz n) @weak @extname("memmove")
|
||||
{
|
||||
return memcpy(dest, src, n) @inline;
|
||||
}
|
||||
|
||||
fn void* memset(void* dest, CInt value, usz n) @weak @extname("memset")
|
||||
{
|
||||
for (usz i = 0; i < n; i++) ((char*)dest)[i] = (char)value;
|
||||
return dest;
|
||||
}
|
||||
|
||||
$endif;
|
||||
|
||||
// stdio
|
||||
|
||||
define Fpos = long;
|
||||
define CFile = void*;
|
||||
|
||||
$switch (env::OS_TYPE):
|
||||
$case OsType.LINUX:
|
||||
$if (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX):
|
||||
extern CFile __stdin @extname("stdin");
|
||||
extern CFile __stdout @extname("stdout");
|
||||
extern CFile __stderr @extname("stderr");
|
||||
@@ -115,7 +160,7 @@ $case OsType.LINUX:
|
||||
macro CFile stdin() { return __stdin; }
|
||||
macro CFile stdout() { return __stdout; }
|
||||
macro CFile stderr() { return __stderr; }
|
||||
$case OsType.MACOSX:
|
||||
$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOSX):
|
||||
extern CFile __stdinp;
|
||||
extern CFile __stdoutp;
|
||||
extern CFile __stderrp;
|
||||
@@ -124,19 +169,18 @@ $case OsType.MACOSX:
|
||||
macro CFile stdin() { return __stdinp; }
|
||||
macro CFile stdout() { return __stdoutp; }
|
||||
macro CFile stderr() { return __stderrp; }
|
||||
$case OsType.WIN32:
|
||||
$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.WIN32):
|
||||
extern fn CFile __acrt_iob_func(CInt c);
|
||||
extern fn usz _msize(void* ptr);
|
||||
macro usz malloc_size(void* ptr) { return _msize(ptr); }
|
||||
macro CFile stdin() { return __acrt_iob_func(0); }
|
||||
macro CFile stdout() { return __acrt_iob_func(1); }
|
||||
macro CFile stderr() { return __acrt_iob_func(2); }
|
||||
$default:
|
||||
$else:
|
||||
macro CFile stdin() { return (CFile*)(uptr)0; }
|
||||
macro CFile stdout() { return (CFile*)(uptr)1; }
|
||||
macro CFile stderr() { return (CFile*)(uptr)2; }
|
||||
$endswitch;
|
||||
|
||||
$endif;
|
||||
|
||||
const HAS_MALLOC_SIZE =
|
||||
env::OS_TYPE == OsType.LINUX
|
||||
@@ -159,6 +203,8 @@ const int FILENAME_MAX = 1024;
|
||||
define Errno = distinct CInt;
|
||||
define SeekIndex = CLong;
|
||||
|
||||
$if (env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
extern fn int fclose(CFile stream);
|
||||
extern fn void clearerr(CFile stream);
|
||||
extern fn int feof(CFile stream);
|
||||
@@ -190,13 +236,78 @@ extern fn char* fgets(char* str, int n, CFile stream);
|
||||
extern fn int fputc(int c, CFile stream);
|
||||
extern fn int getc(CFile stream);
|
||||
extern fn int getchar();
|
||||
extern fn int putc(char c, CFile stream);
|
||||
extern fn int putc(int c, CFile stream);
|
||||
extern fn int putchar(int c);
|
||||
extern fn int puts(char* str);
|
||||
extern fn int ungetc(int c, CFile stream);
|
||||
extern fn void perror(char* str);
|
||||
extern fn isz getline(char** linep, usz* linecapp, CFile stream);
|
||||
|
||||
$else:
|
||||
|
||||
fn int fseek(CFile stream, SeekIndex offset, int whence) @weak @extname("fseek")
|
||||
{
|
||||
unreachable("'fseek' not available.");
|
||||
}
|
||||
fn CFile fopen(char* filename, char* mode) @weak @extname("fopen")
|
||||
{
|
||||
unreachable("'fopen' not available.");
|
||||
}
|
||||
|
||||
fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream) @weak @extname("fwrite")
|
||||
{
|
||||
unreachable("'fwrite' not available.");
|
||||
}
|
||||
|
||||
fn usz fread(void* ptr, usz size, usz nmemb, CFile stream) @weak @extname("fread")
|
||||
{
|
||||
unreachable("'fread' not available.");
|
||||
}
|
||||
|
||||
fn CFile fclose(CFile) @weak @extname("fclose")
|
||||
{
|
||||
unreachable("'fclose' not available.");
|
||||
}
|
||||
|
||||
fn int fflush(CFile stream) @weak @extname("fflush")
|
||||
{
|
||||
unreachable("'fflush' not available.");
|
||||
}
|
||||
|
||||
fn int fputc(int c, CFile stream) @weak @extname("fputc")
|
||||
{
|
||||
unreachable("'fputc' not available.");
|
||||
}
|
||||
|
||||
fn char* fgets(char* str, int n, CFile stream) @weak @extname("fgets")
|
||||
{
|
||||
unreachable("'fgets' not available.");
|
||||
}
|
||||
|
||||
fn int fgetc(CFile stream) @weak @extname("fgetc")
|
||||
{
|
||||
unreachable("'fgetc' not available.");
|
||||
}
|
||||
|
||||
fn int feof(CFile stream) @weak @extname("feof")
|
||||
{
|
||||
unreachable("'feof' not available.");
|
||||
}
|
||||
|
||||
fn int putc(int c, CFile stream) @weak @extname("putc")
|
||||
{
|
||||
unreachable("'putc' not available.");
|
||||
}
|
||||
fn int putchar(int c) @weak @extname("putchar")
|
||||
{
|
||||
unreachable("'putchar' not available.");
|
||||
}
|
||||
fn int puts(char* str) @weak @extname("puts")
|
||||
{
|
||||
unreachable("'puts' not available.");
|
||||
}
|
||||
|
||||
$endif;
|
||||
// vsprintf vprintf not supported
|
||||
|
||||
// time.h
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
module libc::os;
|
||||
|
||||
$switch (env::OS_TYPE):
|
||||
|
||||
$case LINUX:
|
||||
$if (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX):
|
||||
|
||||
extern fn int* __errno_location();
|
||||
|
||||
macro int errno() => *__errno_location();
|
||||
macro void errno_set(int err) => *(__errno_location()) = err;
|
||||
|
||||
$case MACOSX:
|
||||
$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOSX):
|
||||
|
||||
extern fn int* __error();
|
||||
macro int errno() => *__error();
|
||||
macro void errno_set(int err) => *(__error()) = err;
|
||||
|
||||
$case WIN32:
|
||||
$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.WIN32):
|
||||
|
||||
macro int errno()
|
||||
{
|
||||
@@ -29,9 +26,10 @@ macro void errno_set(int err) => _set_errno(err);
|
||||
extern fn void _get_errno(int* result);
|
||||
extern fn void _set_errno(int err);
|
||||
|
||||
$default:
|
||||
$else:
|
||||
|
||||
macro int errno() => 1;
|
||||
fn void errno_set(int err) {}
|
||||
tlocal int _errno_c3 = 0;
|
||||
fn void errno_set(int err) => _errno_c3 = err;
|
||||
fn int errno() => _errno_c3;
|
||||
|
||||
$endswitch;
|
||||
$endif;
|
||||
|
||||
@@ -124,8 +124,17 @@ $if (env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
extern fn double _atan(double x) @extname("atan");
|
||||
extern fn float _atanf(float x) @extname("atanf");
|
||||
extern fn double _atan2(double x) @extname("atan2");
|
||||
extern fn float _atan2f(float x) @extname("atan2f");
|
||||
extern fn double _atan2(double, double) @extname("atan2");
|
||||
extern fn float _atan2f(float, float) @extname("atan2f");
|
||||
|
||||
macro atan2(x, y)
|
||||
{
|
||||
$if ($typeof(x).typeid == float.typeid && $typeof(y).typeid == float.typeid):
|
||||
return _atan2f(x, y);
|
||||
$else:
|
||||
return _atan2(x, y);
|
||||
$endif;
|
||||
}
|
||||
|
||||
macro atan(x)
|
||||
{
|
||||
@@ -136,16 +145,32 @@ macro atan(x)
|
||||
$endif;
|
||||
}
|
||||
|
||||
$else:
|
||||
|
||||
macro atan2(x, y)
|
||||
{
|
||||
$if ($typeof(x).typeid == float.typeid && $typeof(y).typeid == float.typeid):
|
||||
return _atan2f(x);
|
||||
return atan::_atan2f(x, y);
|
||||
$else:
|
||||
return _atan2(x);
|
||||
return atan::_atan2(x, y);
|
||||
$endif;
|
||||
}
|
||||
|
||||
macro atan(x)
|
||||
{
|
||||
$if ($typeof(x).typeid == float.typeid):
|
||||
return atan::_atanf(x);
|
||||
$else:
|
||||
return atan::_atan(x);
|
||||
$endif;
|
||||
}
|
||||
|
||||
$endif;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @require values::@is_floatlike(x) `The input must be a floating point value or float vector`
|
||||
**/
|
||||
@@ -575,15 +600,28 @@ macro next_power_of_2(x)
|
||||
return y;
|
||||
}
|
||||
|
||||
import std::io;
|
||||
private macro equals_vec(v1, v2)
|
||||
{
|
||||
var $elements = v1.len;
|
||||
var abs_diff = math::abs(v1 - v2);
|
||||
io::printfn("diff %s", abs_diff);
|
||||
var abs_v1 = math::abs(v1);
|
||||
var abs_v2 = math::abs(v2);
|
||||
io::printfn("abs %s", abs_v1);
|
||||
$typeof(abs_v2) eps = 1;
|
||||
return abs_diff.comp_le(FLOAT_EPSILON * math::max(abs_v1, abs_v2, eps)).and();
|
||||
}
|
||||
}
|
||||
|
||||
macro uint double.high_word(double d) => (uint)(bitcast(d, ulong) >> 32);
|
||||
macro uint double.low_word(double d) => (uint)bitcast(d, ulong);
|
||||
macro uint float.word(float d) => bitcast(d, uint);
|
||||
|
||||
macro is_nan(x)
|
||||
{
|
||||
$switch ($typeof(x)):
|
||||
$case float:
|
||||
return bitcast(x, uint) & 0x7fffffff > 0x7f800000;
|
||||
$case double:
|
||||
return bitcast(x, ulong) & (((ulong)-1) >> 1) > (0x7ffu64 << 52);
|
||||
$default:
|
||||
$assert(false, "Type cannot be used with is_nan");
|
||||
$endswitch;
|
||||
}
|
||||
|
||||
47
lib/std/math/math_libc.c3
Normal file
47
lib/std/math/math_libc.c3
Normal file
@@ -0,0 +1,47 @@
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_atan.c
|
||||
* ====================================================
|
||||
* 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.
|
||||
*/
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_atanf.c */
|
||||
/*
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
*/
|
||||
/*
|
||||
* ====================================================
|
||||
* 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.
|
||||
* ====================================================
|
||||
*/
|
||||
module std::math;
|
||||
|
||||
|
||||
|
||||
324
lib/std/math/math_nolibc/atan.c3
Normal file
324
lib/std/math/math_nolibc/atan.c3
Normal file
@@ -0,0 +1,324 @@
|
||||
module std::math::nolibc::atan;
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
private const double[*] ATANHI = {
|
||||
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 */
|
||||
};
|
||||
|
||||
private const double[*] ATANLO = {
|
||||
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 */
|
||||
};
|
||||
|
||||
private const double[*] AT = {
|
||||
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 */
|
||||
};
|
||||
|
||||
fn double _atan(double x) @weak @extname("atan")
|
||||
{
|
||||
int id = void;
|
||||
uint ix = x.high_word();
|
||||
uint sign = ix >> 31;
|
||||
ix &= 0x7fffffff;
|
||||
switch
|
||||
{
|
||||
case ix >= 0x44100000:
|
||||
/* if |x| >= 2^66 */
|
||||
if (math::is_nan(x)) return x;
|
||||
double z = ATANHI[3] + 0x1p-120f;
|
||||
return sign ? -z : z;
|
||||
case ix < 0x3fdc0000:
|
||||
/* |x| < 0.4375 */
|
||||
if (ix < 0x3e400000)
|
||||
{
|
||||
/* |x| < 2^-27 */
|
||||
if (ix < 0x00100000)
|
||||
{
|
||||
/* raise underflow for subnormal x */
|
||||
(float)@volatile_load(x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
id = -1;
|
||||
case ix < 0x3ff30000:
|
||||
/* |x| < 1.1875 */
|
||||
x = math::abs(x);
|
||||
if (ix < 0x3fe60000)
|
||||
{
|
||||
/* 7/16 <= |x| < 11/16 */
|
||||
id = 0;
|
||||
x = (2 * x - 1) / (2 + x);
|
||||
}
|
||||
else
|
||||
{ /* 11/16 <= |x| < 19/16 */
|
||||
id = 1;
|
||||
x = (x - 1) / (x + 1);
|
||||
}
|
||||
case ix < 0x40038000:
|
||||
x = math::abs(x);
|
||||
/* |x| < 2.4375 */
|
||||
id = 2;
|
||||
x = (x - 1.5) / (1 + 1.5 * x);
|
||||
default:
|
||||
/* 2.4375 <= |x| < 2^66 */
|
||||
id = 3;
|
||||
x = -1 / math::abs(x);
|
||||
}
|
||||
/* end of argument reduction */
|
||||
double z = x * x;
|
||||
double w = z * z;
|
||||
/* break sum from i=0 to 10 AT[i]z**(i+1) into odd and even poly */
|
||||
double s1 = z * (AT[0] + w * (AT[2] + w * (AT[4] + w * (AT[6] + w * (AT[8] + w * AT[10])))));
|
||||
double s2 = w * (AT[1] + w * (AT[3] + w * (AT[5] + w * (AT[7] + w * AT[9]))));
|
||||
if (id < 0) return x - x * (s1 + s2);
|
||||
z = ATANHI[id] - (x * (s1 + s2) - ATANLO[id] - x);
|
||||
return sign ? -z : z;
|
||||
}
|
||||
|
||||
private const float[*] ATANHIF = {
|
||||
4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
|
||||
7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
|
||||
9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
|
||||
1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
|
||||
};
|
||||
|
||||
private const float[*] ATANLOF = {
|
||||
5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
|
||||
3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
|
||||
3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
|
||||
7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
|
||||
};
|
||||
|
||||
private const float[*] ATF = {
|
||||
3.3333328366e-01,
|
||||
-1.9999158382e-01,
|
||||
1.4253635705e-01,
|
||||
-1.0648017377e-01,
|
||||
6.1687607318e-02,
|
||||
};
|
||||
|
||||
fn float _atanf(float x) @weak @extname("atanf")
|
||||
{
|
||||
int id = void;
|
||||
uint ix = x.word();
|
||||
uint sign = ix >> 31;
|
||||
ix &= 0x7fffffff;
|
||||
if (ix >= 0x4c800000)
|
||||
{
|
||||
/* if |x| >= 2**26 */
|
||||
if (math::is_nan(x)) return x;
|
||||
float z = ATANHIF[3] + 0x1p-120f;
|
||||
return sign ? -z : z;
|
||||
}
|
||||
switch
|
||||
{
|
||||
case ix < 0x3ee00000:
|
||||
/* |x| < 0.4375 */
|
||||
if (ix < 0x39800000)
|
||||
{
|
||||
/* |x| < 2**-12 */
|
||||
if (ix < 0x00800000)
|
||||
{
|
||||
/* raise underflow for subnormal x */
|
||||
float f = @volatile_load(x);
|
||||
f = f * f;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
id = -1;
|
||||
case ix < 0x3f980000:
|
||||
/* |x| < 1.1875 */
|
||||
x = math::abs(x);
|
||||
if (ix < 0x3f300000)
|
||||
{
|
||||
/* 7/16 <= |x| < 11/16 */
|
||||
id = 0;
|
||||
x = (2.0f * x - 1.0f) / (2.0f + x);
|
||||
break;
|
||||
}
|
||||
/* 11/16 <= |x| < 19/16 */
|
||||
id = 1;
|
||||
x = (x - 1.0f) / (x + 1.0f);
|
||||
case ix < 0x401c0000:
|
||||
x = math::abs(x);
|
||||
/* |x| < 2.4375 */
|
||||
id = 2;
|
||||
x = (x - 1.5f) / (1.0f + 1.5f * x);
|
||||
default:
|
||||
/* 2.4375 <= |x| < 2**26 */
|
||||
x = math::abs(x);
|
||||
id = 3;
|
||||
x = -1.0f / x;
|
||||
}
|
||||
/* end of argument reduction */
|
||||
float z = x * x;
|
||||
float w = z * z;
|
||||
/* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
|
||||
float s1 = z * (ATF[0] + w * (ATF[2] + w * ATF[4]));
|
||||
float s2 = w * (ATF[1] + w * ATF[3]);
|
||||
if (id < 0) return x - x * (s1 + s2) * 10000;
|
||||
z = ATANHIF[id] - ((x * (s1 + s2) - ATANLOF[id]) - x);
|
||||
return sign ? -z : z;
|
||||
}
|
||||
|
||||
private const PI_LO = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
|
||||
|
||||
private macro void extract_words(double d, uint* hi, uint* lo)
|
||||
{
|
||||
ulong rep = bitcast(d, ulong);
|
||||
*hi = (uint)(rep >> 32);
|
||||
*lo = (uint)rep;
|
||||
}
|
||||
|
||||
fn double _atan2(double y, double x) @weak @extname("atan2")
|
||||
{
|
||||
if (math::is_nan(x) || math::is_nan(y)) return x + y;
|
||||
|
||||
uint lx = void;
|
||||
uint ix = void;
|
||||
extract_words(x, &ix, &lx);
|
||||
uint ly = void;
|
||||
uint iy = void;
|
||||
extract_words(y, &iy, &ly);
|
||||
|
||||
// x = 1.0
|
||||
if ((ix - 0x3ff00000) | lx == 0) return _atan(y);
|
||||
// 2*sign(x) + sign(y)
|
||||
uint m = ((iy >> 31) & 1) | ((ix >> 30) & 2);
|
||||
ix = ix & 0x7fffffff;
|
||||
iy = iy & 0x7fffffff;
|
||||
|
||||
// when y = 0
|
||||
if (iy | ly == 0)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case 0:
|
||||
case 1: return y; /* atan(+-0,+anything)=+-0 */
|
||||
case 2: return math::PI; /* atan(+0,-anything) = pi */
|
||||
case 3: return -math::PI; /* atan(-0,-anything) =-pi */
|
||||
}
|
||||
}
|
||||
// when x = 0 */
|
||||
if (ix | lx == 0) return m & 1 ? -math::PI_2 : math::PI_2;
|
||||
/* when x is INF */
|
||||
if (ix == 0x7ff00000)
|
||||
{
|
||||
if (iy == 0x7ff00000)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case 0: return math::PI_4; /* atan(+INF,+INF) */
|
||||
case 1: return -math::PI_4; /* atan(-INF,+INF) */
|
||||
case 2: return math::PI_4 + math::PI_2; /* atan(+INF,-INF) */
|
||||
case 3: return - (math::PI_4 + math::PI_2); /* atan(-INF,-INF) */
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
switch (m)
|
||||
{
|
||||
case 0: return 0.0; /* atan(+...,+INF) */
|
||||
case 1: return -0.0; /* atan(-...,+INF) */
|
||||
case 2: return math::PI; /* atan(+...,-INF) */
|
||||
case 3: return -math::PI; /* atan(-...,-INF) */
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
/* |y/x| > 0x1p64 */
|
||||
if (ix + (64 << 20) < iy || iy == 0x7ff00000) return m & 1 ? -math::PI_2 : math::PI_2;
|
||||
|
||||
/* z = atan(|y/x|) without spurious underflow */
|
||||
double z = ((m & 2) && iy + (64 << 20) < ix) ? 0 : _atan(math::abs(y/x));
|
||||
switch (m)
|
||||
{
|
||||
case 0: return z; /* atan(+,+) */
|
||||
case 1: return -z; /* atan(-,+) */
|
||||
case 2: return math::PI - (z - PI_LO); /* atan(+,-) */
|
||||
default: return (z - PI_LO) - math::PI; /* atan(-,-) */
|
||||
}
|
||||
}
|
||||
|
||||
private const float PI_F = 3.1415927410e+00; /* 0x40490fdb */
|
||||
private const float PI_LO_F = -8.7422776573e-08; /* 0xb3bbbd2e */
|
||||
|
||||
fn float _atan2f(float y, float x) @weak @extname("atan2f")
|
||||
{
|
||||
if (math::is_nan(x) || math::is_nan(y)) return x + y;
|
||||
uint ix = bitcast(x, uint);
|
||||
uint iy = bitcast(y, uint);
|
||||
/* x=1.0 */
|
||||
if (ix == 0x3f800000) return _atanf(y);
|
||||
/* 2*sign(x)+sign(y) */
|
||||
uint m = ((iy >> 31) & 1) | ((ix >> 30) & 2);
|
||||
ix &= 0x7fffffff;
|
||||
iy &= 0x7fffffff;
|
||||
|
||||
/* when y = 0 */
|
||||
if (iy == 0)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case 0:
|
||||
case 1: return y; /* atan(+-0,+anything)=+-0 */
|
||||
case 2: return PI_F; /* atan(+0,-anything) = pi */
|
||||
case 3: return -PI_F; /* atan(-0,-anything) =-pi */
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
/* when x = 0 */
|
||||
if (ix == 0) return m & 1 ? -(float)math::PI_2 : (float)math::PI_2;
|
||||
/* when x is INF */
|
||||
if (ix == 0x7f800000)
|
||||
{
|
||||
if (iy == 0x7f800000)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case 0: return (float)math::PI_4; /* atan(+INF,+INF) */
|
||||
case 1: return (float)-math::PI_4; /* atan(-INF,+INF) */
|
||||
case 2: return (float)(math::PI_4 + math::PI_2); /*atan(+INF,-INF)*/
|
||||
case 3: return -(float)(math::PI_4 + math::PI_2); /*atan(-INF,-INF)*/
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
switch (m)
|
||||
{
|
||||
case 0: return 0.0f; /* atan(+...,+INF) */
|
||||
case 1: return -0.0f; /* atan(-...,+INF) */
|
||||
case 2: return PI_F; /* atan(+...,-INF) */
|
||||
case 3: return -PI_F; /* atan(-...,-INF) */
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
/* |y/x| > 0x1p26 */
|
||||
if (ix + 26 << 23 < iy || iy == 0x7f800000) return m & 1 ? -(float)math::PI_2 : (float)math::PI_2;
|
||||
|
||||
/* z = atan(|y/x|) with correct underflow */
|
||||
/*|y/x| < 0x1p-26, x < 0 */
|
||||
float z = (m & 2 && iy + 26 << 23 < ix) ? 0.0f : _atanf(math::abs(y / x));
|
||||
switch (m)
|
||||
{
|
||||
case 0: return z; /* atan(+,+) */
|
||||
case 1: return -z; /* atan(-,+) */
|
||||
case 2: return PI_F - (z - PI_LO_F); /* atan(+,-) */
|
||||
default: return (z - PI_LO_F) - PI_F; /* atan(-,-) */
|
||||
}
|
||||
}
|
||||
|
||||
$endif;
|
||||
21
lib/std/math/math_nolibc/floor.c3
Normal file
21
lib/std/math/math_nolibc/floor.c3
Normal file
@@ -0,0 +1,21 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
|
||||
fn double floor(double x) @weak @extname("floor")
|
||||
{
|
||||
const double TOINT = 1 / math::DOUBLE_EPSILON;
|
||||
ulong ui = bitcast(x, ulong);
|
||||
int e = (int)((ui >> 52) & 0x7ff);
|
||||
double y;
|
||||
if (e >= 0x3ff+52 || x == 0) return x;
|
||||
/* y = int(x) - x, where int(x) is an integer neighbor of x */
|
||||
y = ui >> 63 ? (x - TOINT) + TOINT - x : (x + TOINT) - TOINT - x;
|
||||
|
||||
/* special case because of non-nearest rounding modes */
|
||||
if (e <= 0x3ff-1)
|
||||
{
|
||||
@volatile_load(y);
|
||||
return ui >> 63 ? -1 : 0;
|
||||
}
|
||||
return y > 0 ? x + y - 1 : x + y;
|
||||
}
|
||||
347
lib/std/math/math_nolibc/rempi.c3
Normal file
347
lib/std/math/math_nolibc/rempi.c3
Normal file
@@ -0,0 +1,347 @@
|
||||
module std::math::nolibc::rempi;
|
||||
import std::math;
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2f.c */
|
||||
/*
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
* Debugged and optimized by Bruce D. Evans.
|
||||
*/
|
||||
/*
|
||||
* ====================================================
|
||||
* 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.
|
||||
* ====================================================
|
||||
*/
|
||||
/* __rem_pio2f(x,y)
|
||||
*
|
||||
* return the remainder of x rem pi/2 in *y
|
||||
* use double precision for everything except passing x
|
||||
* use __rem_pio2_large() for large x
|
||||
*/
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
/*
|
||||
* invpio2: 53 bits of 2/pi
|
||||
* pio2_1: first 25 bits of pi/2
|
||||
* pio2_1t: pi/2 - pio2_1
|
||||
*/
|
||||
private const double TOINT = 1.5 / math::DOUBLE_EPSILON;
|
||||
private const double PIO4 = 0x1.921fb6p-1;
|
||||
private const double INVPIO2 = 6.36619772367581382433e-01; /* 0x3FE45F30, 0x6DC9C883 */
|
||||
private const double PIO2_1 = 1.57079631090164184570e+00; /* 0x3FF921FB, 0x50000000 */
|
||||
private const double PIO2_1T = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
|
||||
|
||||
fn int __rem_pio2f(float x, double *y)
|
||||
{
|
||||
uint ux = bitcast(x, uint);
|
||||
uint ix = ux & 0x7fffffff;
|
||||
/* 25+53 bit pi is good enough for medium size */
|
||||
if (ix < 0x4dc90fdb)
|
||||
{
|
||||
// |x| ~< 2^28*(pi/2), medium size
|
||||
// Use a specialized rint() to get f.
|
||||
uint f = (uint)(((double)x * INVPIO2 + TOINT) - TOINT);
|
||||
int n = (int)f;
|
||||
*y = x - f * PIO2_1 - f * PIO2_1T;
|
||||
/* Matters with directed rounding. */
|
||||
if (*y < -PIO4) // likely false
|
||||
{
|
||||
n--;
|
||||
f--;
|
||||
*y = x - f * PIO2_1 - f * PIO2_1T;
|
||||
}
|
||||
else if (*y > PIO4) // likely false
|
||||
{
|
||||
n++;
|
||||
f++;
|
||||
*y = x - f * PIO2_1 - f * PIO2_1T;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
if (ix >= 0x7f800000)
|
||||
{
|
||||
// x is inf or NaN */
|
||||
*y = x-x;
|
||||
return 0;
|
||||
}
|
||||
/* scale x into [2^23, 2^24-1] */
|
||||
int sign = ux >> 31;
|
||||
int e0 = (ix >> 23) - (0x7f + 23); /* e0 = ilogb(|x|)-23, positive */
|
||||
ux = ix - e0 << 23;
|
||||
double tx = bitcast(ux, float);
|
||||
double ty = void;
|
||||
int n = __rem_pio2_large(&tx,&ty, e0, 1, 0);
|
||||
if (sign)
|
||||
{
|
||||
*y = (float)-ty;
|
||||
return -n;
|
||||
}
|
||||
*y = (float)ty;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */
|
||||
/*
|
||||
* ====================================================
|
||||
* 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.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
const int[*] INIT_JK = {3,4,4,6}; /* initial value for jk */
|
||||
|
||||
const int[*] IPIO2 = {
|
||||
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, };
|
||||
|
||||
const double[*] PIO2 = {
|
||||
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 */
|
||||
};
|
||||
|
||||
fn int __rem_pio2_large(double* x, double* y, int e0, int nx, int prec)
|
||||
{
|
||||
double[20] f = void;
|
||||
double[20] fq = void;
|
||||
double[20] q = void;
|
||||
int[20] iq = void;
|
||||
double fw = void;
|
||||
/* initialize jk*/
|
||||
int jk = INIT_JK[prec];
|
||||
int jp = jk;
|
||||
|
||||
/* determine jx,jv,q0, note that 3>q0 */
|
||||
int jx = nx - 1;
|
||||
int jv = (e0 - 3) / 24;
|
||||
if (jv < 0) jv = 0;
|
||||
int q0 = e0 - 24 * (jv + 1);
|
||||
|
||||
// set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk]
|
||||
int j = jv - jx;
|
||||
int m = jx + jk;
|
||||
for (int i = 0; i <= m; i++, j++)
|
||||
{
|
||||
f[i] = j < 0 ? 0.0 : (double)IPIO2[j];
|
||||
}
|
||||
|
||||
// compute q[0],q[1],...q[jk]
|
||||
for (int i = 0; i <= jk; i++)
|
||||
{
|
||||
for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j];
|
||||
q[i] = fw;
|
||||
}
|
||||
|
||||
int jz = jk;
|
||||
double z = void;
|
||||
int ih = 0;
|
||||
int n = void;
|
||||
while (1)
|
||||
{
|
||||
/* distill q[] into iq[] reversingly */
|
||||
z = q[jz];
|
||||
j = jz;
|
||||
for (int i = 0; j > 0; i++, j--)
|
||||
{
|
||||
fw = (double)(int)(0x1p-24 * z);
|
||||
iq[i] = (int)(z - 0x1p24 * fw);
|
||||
z = q[j - 1] + fw;
|
||||
}
|
||||
// compute n
|
||||
z = nolibc::scalbn(z, q0); /* actual value of z */
|
||||
z -= 8.0 * nolibc::floor(z * 0.125); /* trim off integer >= 8 */
|
||||
n = (int)z;
|
||||
z -= (double)n;
|
||||
switch
|
||||
{
|
||||
case q0 > 0:
|
||||
// need iq[jz-1] to determine n
|
||||
int i = iq[jz - 1] >> (24 - q0);
|
||||
n += i;
|
||||
iq[jz - 1] -= i << (24 - q0);
|
||||
ih = iq[jz - 1] >> (23 - q0);
|
||||
case q0 == 0:
|
||||
ih = iq[jz - 1] >> 23;
|
||||
case z >= 0.5:
|
||||
ih = 2;
|
||||
}
|
||||
if (ih > 0)
|
||||
{
|
||||
/* q > 0.5 */
|
||||
n += 1;
|
||||
int carry = 0;
|
||||
for (int 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;
|
||||
case 2: iq[jz - 1] &= 0x3fffff;
|
||||
}
|
||||
}
|
||||
if (ih == 2)
|
||||
{
|
||||
z = 1.0 - z;
|
||||
if (carry != 0) z -= nolibc::scalbn(1.0, q0);
|
||||
}
|
||||
}
|
||||
|
||||
// check if recomputation is needed
|
||||
if (z == 0.0)
|
||||
{
|
||||
j = 0;
|
||||
for (int i = jz - 1; i >= jk; i--) j |= iq[i];
|
||||
if (j == 0)
|
||||
{
|
||||
/* need recomputation */
|
||||
int k = 1;
|
||||
for (; iq[jk - k] == 0; k++); /* k = no. of terms needed */
|
||||
|
||||
for (int 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;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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 = nolibc::scalbn(z,-q0);
|
||||
if (z >= 0x1p24)
|
||||
{
|
||||
fw = (double)(int)(0x1p-24 * z);
|
||||
iq[jz] = (int)(z - 0x1p24 * fw);
|
||||
jz += 1;
|
||||
q0 += 24;
|
||||
iq[jz] = (int)fw;
|
||||
}
|
||||
else
|
||||
{
|
||||
iq[jz] = (int)z;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert integer "bit" chunk to floating-point value */
|
||||
fw = nolibc::scalbn(1.0 , q0);
|
||||
for (int i = jz; i >= 0; i --)
|
||||
{
|
||||
q[i] = fw * (double)iq[i];
|
||||
fw *= 0x1p-24;
|
||||
}
|
||||
|
||||
/* compute PIO2[0,...,jp]*q[jz,...,0] */
|
||||
for (int i = jz; i >= 0; i--)
|
||||
{
|
||||
for (fw = 0.0, int 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 (int i = jz; i >= 0; i--) fw += fq[i];
|
||||
y[0] = ih == 0 ? fw : -fw;
|
||||
case 1:
|
||||
case 2:
|
||||
fw = 0.0;
|
||||
for (int i = jz; i >= 0; i--)
|
||||
fw += fq[i];
|
||||
// TODO: drop excess precision here once double_t is used
|
||||
fw = (double)fw;
|
||||
y[0] = ih == 0 ? fw : -fw;
|
||||
fw = fq[0]-fw;
|
||||
for (int i = 1; i <= jz; i++) fw += fq[i];
|
||||
y[1] = ih == 0 ? fw : -fw;
|
||||
case 3: /* painful */
|
||||
for (int i = jz; i > 0; i--)
|
||||
{
|
||||
fw = fq[i - 1] + fq[i];
|
||||
fq[i] += fq[i - 1] - fw;
|
||||
fq[i - 1] = fw;
|
||||
}
|
||||
for (int 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, int 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;
|
||||
}
|
||||
|
||||
$endif;
|
||||
27
lib/std/math/math_nolibc/scalbn.c3
Normal file
27
lib/std/math/math_nolibc/scalbn.c3
Normal file
@@ -0,0 +1,27 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
fn double scalbn(double x, int n) @weak @extname("scalbn")
|
||||
{
|
||||
switch
|
||||
{
|
||||
case n > 1023:
|
||||
x *= 0x1p1023;
|
||||
n -= 1023;
|
||||
if (n > 1023)
|
||||
{
|
||||
x *= 0x1p1023;
|
||||
n -= 1023;
|
||||
if (n > 1023) n = 1023;
|
||||
}
|
||||
case n < -1022:
|
||||
x *= 0x1p-1022 * 0x1p53;
|
||||
n += 1022 - 53;
|
||||
if (n < -1022)
|
||||
{
|
||||
x *= 0x1p-1022 * 0x1p53;
|
||||
n += 1022 - 53;
|
||||
if (n < -1022) n = -1022;
|
||||
}
|
||||
}
|
||||
return x * bitcast(((ulong)(0x3ff + n)) << 52, double);
|
||||
}
|
||||
177
lib/std/math/math_nolibc/trig.c3
Normal file
177
lib/std/math/math_nolibc/trig.c3
Normal file
@@ -0,0 +1,177 @@
|
||||
module std::math::nolibc::trig;
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */
|
||||
/*
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
* Optimized by Bruce D. Evans.
|
||||
*/
|
||||
/*
|
||||
* ====================================================
|
||||
* 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.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
private const double S1PI2_F = math::PI_2; /* 0x3FF921FB, 0x54442D18 */
|
||||
private const double S2PI2_F = math::PI; /* 0x400921FB, 0x54442D18 */
|
||||
private const double S3PI2_F = math::PI + math::PI_2; /* 0x4012D97C, 0x7F3321D2 */
|
||||
private const double S4PI2_F = math::PI + math::PI; /* 0x401921FB, 0x54442D18 */
|
||||
|
||||
fn float _sinf(float x) @weak @extname("sinf")
|
||||
{
|
||||
uint ix = bitcast(x, uint);
|
||||
int sign = ix >> 31;
|
||||
ix &= 0x7fffffff;
|
||||
switch
|
||||
{
|
||||
case ix <= 0x3f490fda:
|
||||
// |x| ~<= pi/4
|
||||
if (ix < 0x39800000)
|
||||
{
|
||||
/* |x| < 2**-12 */
|
||||
// raise inexact if x!=0 and underflow if subnormal
|
||||
if (ix < 0x00800000)
|
||||
{
|
||||
@volatile_load(x) / 0x1p120f;
|
||||
}
|
||||
else
|
||||
{
|
||||
@volatile_load(x) + 0x1p120f;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
return __sindf(x);
|
||||
case ix <= 0x407b53d1:
|
||||
// |x| ~<= 5*pi/4
|
||||
if (ix <= 0x4016cbe3)
|
||||
{
|
||||
// |x| ~<= 3pi/4
|
||||
if (sign) return -__cosdf(x + S1PI2_F);
|
||||
return __cosdf(x - S1PI2_F);
|
||||
}
|
||||
return __sindf(sign ? -(x + S2PI2_F) : -(x - S2PI2_F));
|
||||
case ix <= 0x40e231d5:
|
||||
// |x| ~<= 9*pi/4
|
||||
if (ix <= 0x40afeddf)
|
||||
{
|
||||
// |x| ~<= 7*pi/4
|
||||
return sign ? __cosdf(x + S3PI2_F) : -__cosdf(x - S3PI2_F);
|
||||
}
|
||||
return __sindf(sign ? x + S4PI2_F : x - S4PI2_F);
|
||||
case ix >= 0x7f800000:
|
||||
// sin(Inf or NaN) is NaN
|
||||
return x - x;
|
||||
}
|
||||
/* general argument reduction needed */
|
||||
double y = void;
|
||||
int n = rempi::__rem_pio2f(x, &y);
|
||||
switch (n & 3)
|
||||
{
|
||||
case 0: return __sindf(y);
|
||||
case 1: return __cosdf(y);
|
||||
case 2: return __sindf(-y);
|
||||
default: return -__cosdf(y);
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_sinf.c */
|
||||
/*
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
* Optimized by Bruce D. Evans.
|
||||
*/
|
||||
/*
|
||||
* ====================================================
|
||||
* 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)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */
|
||||
private const double S1 = -0x15555554cbac77.0p-55; /* -0.166666666416265235595 */
|
||||
private const double S2 = 0x111110896efbb2.0p-59; /* 0.0083333293858894631756 */
|
||||
private const double S3 = -0x1a00f9e2cae774.0p-65; /* -0.000198393348360966317347 */
|
||||
private const double S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */
|
||||
|
||||
fn float __sindf(double x)
|
||||
{
|
||||
double z = x * x;
|
||||
double w = z * z;
|
||||
double r = S3 + z * S4;
|
||||
double s = z * x;
|
||||
return (float)((x + s * (S1 + z * S2)) + s * w * r);
|
||||
}
|
||||
|
||||
/* origin: FreeBSD /usr/src/lib/msun/src/k_cosf.c */
|
||||
/*
|
||||
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
|
||||
* Debugged and optimized by Bruce D. Evans.
|
||||
*/
|
||||
/*
|
||||
* ====================================================
|
||||
* 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.
|
||||
* ====================================================
|
||||
*/
|
||||
/* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */
|
||||
|
||||
private const double C0 = -0x1ffffffd0c5e81.0p-54; /* -0.499999997251031003120 */
|
||||
private const double C1 = 0x155553e1053a42.0p-57; /* 0.0416666233237390631894 */
|
||||
private const double C2 = -0x16c087e80f1e27.0p-62; /* -0.00138867637746099294692 */
|
||||
private const double C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
|
||||
|
||||
fn float __cosdf(double x)
|
||||
{
|
||||
/* Try to optimize for parallel evaluation as in __tandf.c. */
|
||||
double z = x * x;
|
||||
double w = z * z;
|
||||
double r = C2 + z * C3;
|
||||
return (float)(((1.0f + z * C0) + w * C1) + (w * z) * r);
|
||||
}
|
||||
|
||||
fn float cosf_broken(float x) @extname("cosf") @weak
|
||||
{
|
||||
unreachable("'cosf' not supported");
|
||||
}
|
||||
|
||||
fn double sin_broken(double x) @extname("sin") @weak
|
||||
{
|
||||
unreachable("'sin' not supported");
|
||||
}
|
||||
fn double cos_broken(double x) @extname("cos") @weak
|
||||
{
|
||||
unreachable("'cos' not supported");
|
||||
}
|
||||
|
||||
fn float roundf_broken(float x) @extname("roundf") @weak
|
||||
{
|
||||
unreachable("'roundf' not supported");
|
||||
}
|
||||
|
||||
fn double round_broken(double x) @extname("round") @weak
|
||||
{
|
||||
unreachable("'round' not supported");
|
||||
}
|
||||
|
||||
fn float powf_broken(float x) @extname("powf") @weak
|
||||
{
|
||||
unreachable("'powf' not supported");
|
||||
}
|
||||
|
||||
$endif;
|
||||
6
lib/std/threads/os/thread_none.c3
Normal file
6
lib/std/threads/os/thread_none.c3
Normal file
@@ -0,0 +1,6 @@
|
||||
module std::thread;
|
||||
|
||||
define NativeMutex = distinct int;
|
||||
define NativeConditionVariable = distinct int;
|
||||
define NativeOnceFlag = distinct int;
|
||||
define NativeThread = distinct int;
|
||||
@@ -3,9 +3,15 @@ module std::thread;
|
||||
enum ThreadModel
|
||||
{
|
||||
WIN32,
|
||||
POSIX
|
||||
POSIX,
|
||||
NONE
|
||||
}
|
||||
|
||||
$if (env::COMPILER_LIBC_AVAILABLE):
|
||||
const ThreadModel THREAD_MODEL = env::OS_TYPE == OsType.WIN32 ? ThreadModel.WIN32 : ThreadModel.POSIX;
|
||||
$else:
|
||||
const ThreadModel THREAD_MODEL = NONE;
|
||||
$endif;
|
||||
|
||||
define MutexType = distinct int;
|
||||
|
||||
|
||||
@@ -498,10 +498,6 @@ static bool linker_setup(const char ***args_ref, const char **files_to_link, uns
|
||||
}
|
||||
break;
|
||||
case OS_TYPE_NONE:
|
||||
if (!active_target.no_libc)
|
||||
{
|
||||
error_exit("Linking is not supported for freestanding.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (unsigned i = 0; i < file_count; i++)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
extern void LLVMSetTargetMachineUseInitArray(LLVMTargetMachineRef ref, bool use_init_array);
|
||||
|
||||
static ObjectFormatType object_format_from_os(OsType os, ArchType arch_type);
|
||||
static unsigned arch_pointer_bit_width(OsType os, ArchType arch);
|
||||
static ArchType arch_from_llvm_string(StringSlice string);
|
||||
static EnvironmentType environment_type_from_llvm_string(StringSlice string);
|
||||
@@ -14,7 +15,6 @@ static AlignData os_target_alignment_of_int(OsType os, ArchType arch, uint32_t b
|
||||
static AlignData os_target_alignment_of_float(OsType os, ArchType arch, uint32_t bits);
|
||||
static OsType os_from_llvm_string(StringSlice string);
|
||||
static VendorType vendor_from_llvm_string(StringSlice string);
|
||||
static ObjectFormatType object_format_from_os(OsType os);
|
||||
static unsigned os_target_supports_int128(OsType os, ArchType arch);
|
||||
static unsigned os_target_supports_float16(OsType os, ArchType arch);
|
||||
static unsigned os_target_supports_float128(OsType os, ArchType arch);
|
||||
@@ -895,15 +895,17 @@ static unsigned os_target_supports_vec(OsType os, ArchType arch, int bits, bool
|
||||
}
|
||||
}
|
||||
|
||||
static ObjectFormatType object_format_from_os(OsType os)
|
||||
static ObjectFormatType object_format_from_os(OsType os, ArchType arch_type)
|
||||
{
|
||||
switch (os)
|
||||
{
|
||||
case OS_UNSUPPORTED:
|
||||
return OBJ_FORMAT_UNSUPPORTED;
|
||||
case OS_TYPE_LINUX:
|
||||
case OS_TYPE_UNKNOWN:
|
||||
case OS_TYPE_NONE:
|
||||
if (arch_type == ARCH_TYPE_WASM64 || arch_type == ARCH_TYPE_WASM32) return OBJ_FORMAT_WASM;
|
||||
FALLTHROUGH;
|
||||
case OS_TYPE_LINUX:
|
||||
case OS_TYPE_NETBSD:
|
||||
case OS_TYPE_OPENBSD:
|
||||
case OS_TYPE_FREE_BSD:
|
||||
@@ -1395,7 +1397,7 @@ void target_setup(BuildTarget *target)
|
||||
platform_target.big_endian = arch_big_endian(platform_target.arch);
|
||||
platform_target.width_pointer = arch_pointer_bit_width(platform_target.os, platform_target.arch);
|
||||
platform_target.alloca_address_space = 0;
|
||||
platform_target.object_format = object_format_from_os(platform_target.os);
|
||||
platform_target.object_format = object_format_from_os(platform_target.os, platform_target.arch);
|
||||
switch (platform_target.object_format)
|
||||
{
|
||||
case OBJ_FORMAT_COFF:
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.20"
|
||||
#define COMPILER_VERSION "0.4.21"
|
||||
Reference in New Issue
Block a user