msl_c mostly matching for wii/shield (#2994)

This commit is contained in:
TakaRikka
2025-12-24 16:54:21 -08:00
committed by GitHub
parent 8a478c5ebe
commit cefe919b8d
58 changed files with 3997 additions and 695 deletions
+2 -1
View File
@@ -4609,7 +4609,7 @@ PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/printf.c:
.sdata2 start:0x80752ED0 end:0x80752ED8
PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/float.c:
.sdata start:0x8074C238 end:0x8074C24C
.sdata start:0x8074C238 end:0x8074C248
PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/scanf.c:
.text start:0x80621C6C end:0x80623150
@@ -4890,6 +4890,7 @@ TRK_MINNOW_DOLPHIN/debugger/embedded/MetroTRK/Os/dolphin/target_options.c:
NdevExi2AD/DebuggerDriver.c:
.text start:0x8062ECBC end:0x8062F1EC
.sdata start:0x8074C248 end:0x8074C24C
.sbss start:0x8074D728 end:0x8074D73C
NdevExi2AD/exi2.c:
+5 -2
View File
@@ -306,10 +306,13 @@ cflags_runtime = [
"-str reuse,pool,readonly",
"-common off",
"-char signed",
# "-inline deferred,auto"
"-func_align 4",
"-DMSL_USE_INLINES=1",
]
if config.version not in ["ShieldD", "Shield"]:
if config.version in ["RZDE01_00", "RZDE01_02", "RZDP01", "RZDJ01", "ShieldD", "Shield"]:
cflags_runtime.extend(["-ipa file", "-fp_contract off"])
else:
cflags_runtime.extend(["-inline deferred,auto"])
cflags_trk = [
+2 -5
View File
@@ -31,6 +31,8 @@
#define DEBUG 0
#endif
#define MSL_INLINE inline
#define ARRAY_SIZE(o) (s32)(sizeof(o) / sizeof(o[0]))
#define ARRAY_SIZEU(o) (sizeof(o) / sizeof(o[0]))
@@ -87,11 +89,6 @@ void* __memcpy(void*, const void*, int);
#define POINTER_ADD(ptr_, offset_) POINTER_ADD_TYPE(__typeof__(ptr_), ptr_, offset_)
// floating-point constants
#define _HUGE_ENUF 1e+300
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
#define HUGE_VAL ((double)INFINITY)
#define HUGE_VALL ((long double)INFINITY)
#define DOUBLE_INF HUGE_VAL
static const float INF = 2000000000.0f;
// hack to make strings with no references compile properly
+4 -9
View File
@@ -1,6 +1,9 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRFileLoader.h"
#define MSL_USE_INLINES 1 // needed to inline tolower call. not inlined elsewhere in the repo
#include "string.h"
#include "ctype.h"
#include "global.h"
@@ -122,15 +125,7 @@ const char* JKRFileLoader::fetchVolumeName(char* buffer, s32 bufferSize, const c
path++;
while (*path != 0 && *path != '/') {
if (1 < bufferSize) {
int lower_char;
int ch = (int)*path;
if (ch == -1) {
lower_char = -1;
} else {
lower_char = __lower_map[ch & 0xFF];
}
*buffer = lower_char;
*buffer = tolower(*path);
buffer++;
bufferSize--;
}
@@ -20,6 +20,8 @@ typedef long long int64_t;
typedef uint32_t uintptr_t;
typedef int32_t intptr_t;
typedef long long intmax_t;
#ifdef __cplusplus
};
}
@@ -28,9 +28,9 @@ enum __file_kinds {
};
enum __file_orientation {
/* 0x0 */ UNORIENTED,
/* 0x1 */ CHAR_ORIENTED,
/* 0x2 */ WIDE_ORIENTED,
__unoriented,
__char_oriented,
__wide_oriented
};
typedef struct _file_modes {
@@ -6,6 +6,10 @@
#define NAN (*(float*) __float_nan)
#define HUGE_VALF (*(float*) __float_huge)
#if !PLATFORM_GCN
#define HUGE_VAL (*(double*)__double_huge)
#endif
#define M_PI 3.14159265358979323846f
#define M_SQRT3 1.73205f
@@ -44,34 +48,65 @@ float sinf(float);
double sqrt(double);
double tan(double);
float tanf(float);
inline float expf(float x) {
return exp(x);
}
inline float ceilf(float num) {
return ceil(num);
}
double log10(double);
inline double fabs(double f) {
return __fabs(f);
}
inline float fabsf(float f) {
return (float)fabs((double)f);
inline long double fabsl(long double x) {
return fabs((double)x);
}
inline float floorf(float num) {
MSL_INLINE float acosf(float x) {
return acos(x);
}
MSL_INLINE float atan2f(float y, float x) {
return (float)atan2(y, x);
}
MSL_INLINE float ceilf(float num) {
return ceil(num);
}
MSL_INLINE float cosf(float x) {
return cos(x);
}
MSL_INLINE float expf(float x) {
return exp(x);
}
MSL_INLINE float floorf(float num) {
return floor(num);
}
inline float fmodf(float f1, float f2) {
MSL_INLINE float powf(float x, float y) {
return pow(x, y);
}
MSL_INLINE float sinf(float x) {
return sin(x);
}
MSL_INLINE float fabsf(float f) {
return (float)fabs((double)f);
}
MSL_INLINE float fmodf(float f1, float f2) {
return fmod(f1, f2);
}
MSL_INLINE float log10f(float x) {
return log10(x);
}
#include "global.h"
#if PLATFORM_WII || PLATFORM_SHIELD
inline float sqrtf(float mag) {
MSL_INLINE float sqrtf(float mag) {
return sqrt(mag);
}
#else
@@ -87,7 +122,7 @@ inline float sqrtf(float mag) {
static double _half = 0.5;
static double _three = 3.0;
#endif
inline float sqrtf(float mag) {
MSL_INLINE float sqrtf(float mag) {
#ifndef DECOMPCTX
// part of the same hack, these are defined outside of the function when using decompctx
static const double _half = 0.5;
@@ -110,15 +145,10 @@ inline float sqrtf(float mag) {
}
#endif
inline float atan2f(float y, float x) {
return (float)atan2(y, x);
MSL_INLINE float tanf(float x) {
return tan(x);
}
inline float sinf(float x) { return sin(x); }
inline float cosf(float x) { return cos(x); }
inline float tanf(float x) { return tan(x); }
inline float acosf(float x) { return acos(x); }
#ifdef __cplusplus
};
#endif
@@ -1,6 +1,8 @@
#ifndef _MSL_COMMON_CRITICAL_REGIONS_H
#define _MSL_COMMON_CRITICAL_REGIONS_H
#include "global.h"
#ifdef __cplusplus
extern "C" {
#endif
@@ -20,11 +22,17 @@ enum critical_regions {
void __init_critical_regions(void);
void __kill_critical_regions(void);
#if PLATFORM_GCN
void __begin_critical_region(int region);
void __end_critical_region(int region);
#else
#define __begin_critical_region(region)
#define __end_critical_region(region)
#endif
#ifdef __cplusplus
}
#endif
#endif
#endif
@@ -1,12 +1,15 @@
#ifndef _MSL_COMMON_CTYPE_H
#define _MSL_COMMON_CTYPE_H
#include "global.h"
#ifdef __cplusplus
extern "C" {
#endif
#define EOF -1L
#if PLATFORM_GCN
extern unsigned char __ctype_map[];
extern unsigned char __lower_map[];
extern unsigned char __upper_map[];
@@ -28,19 +31,135 @@ extern unsigned char __upper_map[];
#define __control (__motion_char | __control_char)
#define __zero_fill(c) ((int)(unsigned char)(c))
int tolower(int);
inline int isalpha(int c) { return (int)(__ctype_map[(unsigned char)c] & __letter); }
inline int isdigit(int c) { return (int)(__ctype_map[(unsigned char)c] & __digit); }
inline int isspace(int c) { return (int)(__ctype_map[(unsigned char)c] & __whitespace); }
inline int isupper(int c) { return (int)(__ctype_map[(unsigned char)c] & __upper_case); }
inline int isxdigit(int c) { return (int)(__ctype_map[(unsigned char)c] & __hex_digit); }
// added underscore to avoid naming conflicts
inline int _tolower(int c) { return (c == -1 ? -1 : (int)__lower_map[(unsigned char)c]); }
inline int toupper(int c) { return (c == -1 ? -1 : (int)__upper_map[(unsigned char)c]); }
#else
#include <locale.h>
extern const unsigned char __lower_mapC[0x100];
extern const unsigned char __upper_mapC[0x100];
extern const unsigned short __ctype_mapC[0x100];
#define ctype_alpha 0x0001
#define ctype_blank 0x0002
#define ctype_cntrl 0x0004
#define ctype_digit 0x0008
#define ctype_graph 0x0010
#define ctype_lower 0x0020
#define ctype_print 0x0040
#define ctype_punct 0x0080
#define ctype_space 0x0100
#define ctype_upper 0x0200
#define ctype_xdigit 0x0400
#define ctype_alnum (ctype_alpha | ctype_digit)
#endif
int tolower(int);
#if MSL_USE_INLINES
MSL_INLINE int isalnum(int c) {
#if !PLATFORM_GCN
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_alnum);
#endif
}
MSL_INLINE int isalpha(int c) {
#if PLATFORM_GCN
return (int)(__ctype_map[(unsigned char)c] & __letter);
#else
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_alpha);
#endif
}
MSL_INLINE int isblank(int c) {
#if !PLATFORM_GCN
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_blank);
#endif
}
MSL_INLINE int iscntrl(int c) {
#if !PLATFORM_GCN
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_cntrl);
#endif
}
MSL_INLINE int isdigit(int c) {
#if PLATFORM_GCN
return (int)(__ctype_map[(unsigned char)c] & __digit);
#else
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_digit);
#endif
}
MSL_INLINE int isgraph(int c) {
#if !PLATFORM_GCN
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_graph);
#endif
}
MSL_INLINE int islower(int c) {
#if !PLATFORM_GCN
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_lower);
#endif
}
MSL_INLINE int isprint(int c) {
#if !PLATFORM_GCN
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_print);
#endif
}
MSL_INLINE int ispunct(int c) {
#if !PLATFORM_GCN
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_punct);
#endif
}
MSL_INLINE int isupper(int c) {
#if PLATFORM_GCN
return (int)(__ctype_map[(unsigned char)c] & __upper_case);
#else
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_upper);
#endif
}
MSL_INLINE int isxdigit(int c) {
#if PLATFORM_GCN
return (int)(__ctype_map[(unsigned char)c] & __hex_digit);
#else
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_xdigit);
#endif
}
MSL_INLINE int isspace(int c) {
#if PLATFORM_GCN
return (int)(__ctype_map[(unsigned char)c] & __whitespace);
#else
return (c < 0 || c >= 256) ? 0 : (int)(_current_locale.ctype_cmpt_ptr->ctype_map_ptr[c] & ctype_space);
#endif
}
MSL_INLINE int tolower(int c) {
#if PLATFORM_GCN
return (c == -1) ? -1 : (int) (__lower_map[(unsigned char)c]);
#else
return ((c < 0) || (c >= 0x100)) ? c : (int) (_current_locale.ctype_cmpt_ptr->lower_map_ptr[c]);
#endif
}
MSL_INLINE int toupper(int c) {
#if PLATFORM_GCN
return (c == -1 ? -1 : (int)__upper_map[(unsigned char)c]);
#else
return (c < 0 || c >= 256) ? c : (int)(&_current_locale)->ctype_cmpt_ptr->upper_map_ptr[c];
#endif
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* _MSL_COMMON_CTYPE_H */
#endif /* _MSL_COMMON_CTYPE_H */
@@ -1,6 +1,8 @@
#ifndef MSL_COMMON_SRC_ERRNO_H
#define MSL_COMMON_SRC_ERRNO_H
#include "global.h"
#ifdef __cplusplus
extern "C" {
#endif
@@ -2,6 +2,7 @@
#define _MSL_COMMON_FLOAT_H
#include <fdlibm.h>
#include "global.h"
#define FP_SNAN 0
#define FP_QNAN 1
@@ -22,6 +23,7 @@
((sizeof(x) == sizeof(float)) ? __fpclassifyf((float)(x)) : \
__fpclassifyd((double)(x)) )
#endif
#define signbit(x) ((sizeof(x) == sizeof(float)) ? __signbitf(x) : __signbitd(x))
#define isfinite(x) ((fpclassify(x) > FP_INFINITE))
#define isnan(x) (fpclassify(x) == FP_NAN)
@@ -37,6 +39,10 @@ extern int __float_huge[];
extern int __float_max[];
extern int __float_epsilon[];
#if !PLATFORM_GCN
extern int __double_huge[];
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -108,4 +114,15 @@ int __fpclassifyl(long double __value);
#define DBL_MAX_EXP 1024
#define DBL_MAX_10_EXP 308
#define LDBL_MANT_DIG 53
#define LDBL_DIG 15
#define LDBL_MIN_EXP (-1021)
#define LDBL_MIN_10_EXP (-308)
#define LDBL_MAX_EXP 1024
#define LDBL_MAX_10_EXP 308
#define LDBL_MAX 0x1.fffffffffffffP1023L
#define LDBL_EPSILON 0x1.0000000000000P-52L
#define LDBL_MIN 0x1.0000000000000P-1022L
#endif /* _MSL_COMMON_FLOAT_H */
@@ -0,0 +1,114 @@
#ifndef _MSL_LOCALE_H
#define _MSL_LOCALE_H
#include <cstddef.h>
typedef int (*__decode_mbyte) (wchar_t*, const char*, size_t);
typedef int (*__encode_mbyte) (char*, wchar_t);
struct lconv {
char* decimal_point;
char* thousands_sep;
char* grouping;
char* mon_decimal_point;
char* mon_thousands_sep;
char* mon_grouping;
char* positive_sign;
char* negative_sign;
char* currency_symbol;
char frac_digits;
char p_cs_precedes;
char n_cs_precedes;
char p_sep_by_space;
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
char* int_curr_symbol;
char int_frac_digits;
char int_p_cs_precedes;
char int_n_cs_precedes;
char int_p_sep_by_space;
char int_n_sep_by_space;
char int_p_sign_posn;
char int_n_sign_posn;
};
struct _loc_mon_cmpt {
char CmptName[8];
char* mon_decimal_point;
char* mon_thousands_sep;
char* mon_grouping;
char* positive_sign;
char* negative_sign;
char* currency_symbol;
char frac_digits;
char p_cs_precedes;
char n_cs_precedes;
char p_sep_by_space;
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
char* int_curr_symbol;
char int_frac_digits;
char int_p_cs_precedes;
char int_n_cs_precedes;
char int_p_sep_by_space;
char int_n_sep_by_space;
char int_p_sign_posn;
char int_n_sign_posn;
};
struct _loc_num_cmpt {
char CmptName[8];
char* decimal_point;
char* thousands_sep;
char* grouping;
};
struct _loc_time_cmpt {
char CmptName[8];
const char* am_pm;
const char* DateTime_Format;
const char* Twelve_hr_format;
const char* Date_Format;
const char* Time_Format;
const char* Day_Names;
const char* MonthNames;
char* TimeZone;
};
struct _loc_coll_cmpt {
char name[8];
int char_start;
int char_coll_tab_size;
short char_spec;
unsigned short* char_coll_table_ptr;
unsigned short* wchar_coll_seq_ptr;
};
struct _loc_ctype_cmpt {
char name[8]; // 0x0
const unsigned short* ctype_map_ptr; // 0x8
const unsigned char* upper_map_ptr; // 0xC
const unsigned char* lower_map_ptr; // 0x10
const unsigned short* wctype_map_ptr; // 0x14
const wchar_t* wupper_map_ptr; // 0x18
const wchar_t* wlower_map_ptr; // 0x1C
__decode_mbyte decode_mb;
__encode_mbyte encode_wc;
};
struct __locale {
struct __locale* next_locale; // 0x0
char name[0x30]; // 0x4
struct _loc_coll_cmpt* coll_cmpt_ptr; // 0x34
struct _loc_ctype_cmpt* ctype_cmpt_ptr; // 0x38
struct _loc_mon_cmpt* mon_cmpt_ptr; // 0x3C
struct _loc_num_cmpt* num_cmpt_ptr; // 0x40
struct _loc_time_cmpt* time_cmpt_ptr; // 0x44
};
extern struct __locale _current_locale;
extern struct lconv __lconv;
#endif
@@ -9,6 +9,9 @@ extern "C" {
size_t wcstombs(char* dst, const wchar_t* src, size_t n);
int __mbtowc_noconv(wchar_t*, const char*, size_t);
int __wctomb_noconv(char*, wchar_t);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,15 @@
#ifndef MSL_STRTOLD_H
#define MSL_STRTOLD_H
#ifdef __cplusplus
extern "C" {
#endif
long double __strtold(int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned,
int* overflow);
#ifdef __cplusplus
}
#endif
#endif
@@ -9,6 +9,8 @@ long strtol(const char* str, char** end, int base);
unsigned long strtoul(const char* str, char** end, int base);
unsigned long __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative,
int* overflow);
unsigned long long __strtoull(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg,
int* chars_scanned, int* negative, int* overflow);
int atoi(const char* str);
float atof(const char* str);
@@ -0,0 +1,32 @@
#ifndef _MSL_WCTYPE_H
#define _MSL_WCTYPE_H
#include <cstddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define wctype_alpha 0x0001
#define wctype_blank 0x0002
#define wctype_cntrl 0x0004
#define wctype_digit 0x0008
#define wctype_graph 0x0010
#define wctype_lower 0x0020
#define wctype_print 0x0040
#define wctype_punct 0x0080
#define wctype_space 0x0100
#define wctype_upper 0x0200
#define wctype_xdigit 0x0400
#define wctype_alnum (wctype_alpha | wctype_digit)
extern const unsigned short __wctype_mapC[256];
extern const wchar_t __wlower_mapC[256];
extern const wchar_t __wupper_mapC[256];
#ifdef __cplusplus
}
#endif
#endif /* _MSL_COMMON_CTYPE_H */
@@ -0,0 +1,21 @@
#ifndef MSL_WSTRING_H
#define MSL_WSTRING_H
#include <cstddef.h>
#ifdef __cplusplus
extern "C" {
#endif
size_t wcslen(const wchar_t*);
wchar_t* wcscpy(wchar_t*, const wchar_t*);
wchar_t* wcsncpy(wchar_t*, const wchar_t*, size_t);
wchar_t* wcscat(wchar_t*, const wchar_t*);
int wcscmp(const wchar_t*, const wchar_t*);
wchar_t* wcschr(const wchar_t*, wchar_t);
#ifdef __cplusplus
}
#endif
#endif
@@ -2,15 +2,6 @@
#include "critical_regions.h"
#include "errno.h"
long ftell(FILE* stream) {
int retval;
__begin_critical_region(stdin_access);
retval = (long)_ftell(stream);
__end_critical_region(stdin_access);
return retval;
}
int _ftell(FILE* file) {
int charsInUndoBuffer = 0;
int position;
@@ -43,12 +34,18 @@ int _ftell(FILE* file) {
return (position);
}
long ftell(FILE* stream) {
int retval;
__begin_critical_region(stdin_access);
retval = (long)_ftell(stream);
__end_critical_region(stdin_access);
return retval;
}
int _fseek(FILE* file, unsigned long offset, int whence) {
int bufferCode;
int pos;
int adjust;
unsigned long state;
int buffLen;
unsigned char* ptr;
@@ -68,38 +65,7 @@ int _fseek(FILE* file, unsigned long offset, int whence) {
if (whence == SEEK_CUR) {
whence = SEEK_SET;
adjust = 0;
if ((file->file_mode.file_kind != 1 && file->file_mode.file_kind != 2) ||
file->file_state.error != 0)
{
errno = 0x28;
pos = -1;
} else {
state = file->file_state.io_state;
if (state == 0) {
pos = file->position;
} else {
pos = file->buffer_position;
ptr = file->buffer;
buffLen = (file->buffer_ptr - ptr);
pos += buffLen;
if ((state >= 3)) {
adjust = (state - 2);
pos -= adjust;
}
if (file->file_mode.binary_io == 0) {
int i;
for (i = (buffLen - adjust); i != 0; i--) {
unsigned char c = *ptr;
ptr++;
if (c == 10) {
pos++;
}
}
}
}
}
pos = _ftell(file);
offset += pos;
}
@@ -2,6 +2,8 @@
#include "critical_regions.h"
#include <cstring.h>
#include "global.h"
typedef struct Block {
struct Block* prev;
struct Block* next;
@@ -124,7 +126,29 @@ static const unsigned long fix_pool_sizes[] = {4, 12, 20, 36, 52, 68};
void __sys_free();
static inline SubBlock* SubBlock_merge_prev(SubBlock* ths, SubBlock** start) {
void Block_link(Block* ths, SubBlock* sb) {
SubBlock** st;
SubBlock_set_free(sb);
st = &Block_start(ths);
if (*st != 0) {
sb->prev = (*st)->prev;
sb->prev->next = sb;
sb->next = *st;
(*st)->prev = sb;
*st = sb;
*st = SubBlock_merge_prev(*st, st);
SubBlock_merge_next(*st, st);
} else {
*st = sb;
sb->prev = sb;
sb->next = sb;
}
if (ths->max_size < SubBlock_size(*st))
ths->max_size = SubBlock_size(*st);
}
static SubBlock* SubBlock_merge_prev(SubBlock* ths, SubBlock** start) {
unsigned long prevsz;
SubBlock* p;
@@ -144,7 +168,7 @@ static inline SubBlock* SubBlock_merge_prev(SubBlock* ths, SubBlock** start) {
return ths;
}
static inline void SubBlock_merge_next(SubBlock* pBlock, SubBlock** pStart) {
static void SubBlock_merge_next(SubBlock* pBlock, SubBlock** pStart) {
SubBlock* next_sub_block;
unsigned long this_cur_size;
@@ -179,29 +203,7 @@ static inline void SubBlock_merge_next(SubBlock* pBlock, SubBlock** pStart) {
}
}
inline void Block_link(Block* ths, SubBlock* sb) {
SubBlock** st;
SubBlock_set_free(sb);
st = &Block_start(ths);
if (*st != 0) {
sb->prev = (*st)->prev;
sb->prev->next = sb;
sb->next = *st;
(*st)->prev = sb;
*st = sb;
*st = SubBlock_merge_prev(*st, st);
SubBlock_merge_next(*st, st);
} else {
*st = sb;
sb->prev = sb;
sb->next = sb;
}
if (ths->max_size < SubBlock_size(*st))
ths->max_size = SubBlock_size(*st);
}
static inline Block* __unlink(__mem_pool_obj* pool_obj, Block* bp) {
static Block* __unlink(__mem_pool_obj* pool_obj, Block* bp) {
Block* result = bp->next;
if (result == bp) {
result = 0;
@@ -1,6 +1,8 @@
#include "ansi_files.h"
#include "critical_regions.h"
#include "global.h"
static unsigned char stdin_buff[0x100];
static unsigned char stdout_buff[0x100];
@@ -7,6 +7,10 @@ int abs(int n) {
return (n);
}
long labs(long __x) {
return __x > 0 ? __x : -__x;
}
div_t div(int numerator, int denominator) {
div_t ret;
int i = 1;
@@ -3,6 +3,8 @@
#include "misc_io.h"
#include "wchar_io.h"
#include "global.h"
int __put_char(int c, FILE* stream) {
int ret;
@@ -18,8 +20,15 @@ int __put_char(int c, FILE* stream) {
}
if (stream->file_state.io_state == __neutral && (stream->file_mode.io_mode & __write)) {
if ((stream->file_mode.io_mode & __append) && fseek(stream, 0, 2) != 0) {
return 0;
if ((stream->file_mode.io_mode & __append)) {
#if PLATFORM_GCN
if (fseek(stream, 0, 2) != 0)
#else
if (_fseek(stream, 0, 2) != 0)
#endif
{
return 0;
}
}
stream->file_state.io_state = __writing;
@@ -61,31 +70,21 @@ exit:
return ret;
}
#if PLATFORM_GCN
#define __putc(c, file) \
((fwide(file, -1) >= 0) ? -1 : (file)->buffer_length-- ? (int) (*(file)->buffer_ptr++ = (unsigned char)(c)) : __put_char(c, file))
#else
#define __putc(c, file) \
((__fwide(file, -1) >= 0) ? -1 : (file)->buffer_length-- ? (int) (*(file)->buffer_ptr++ = (unsigned char)(c)) : __put_char(c, file))
#endif
int fputs(const char* s, FILE* stream) {
char c;
int var_r3;
unsigned long len;
int ret = 0;
__begin_critical_region(stdin_access);
while (c = *s++, c != 0) {
if (fwide(stream, -1) >= 0) {
var_r3 = -1;
} else {
len = stream->buffer_length;
stream->buffer_length = len - 1;
if (len != 0) {
char* buf = (char*)stream->buffer_ptr;
stream->buffer_ptr++;
*buf = var_r3 = c & 0xFF;
} else {
var_r3 = __put_char(c, stream);
}
}
if (var_r3 == -1) {
if (__putc(c, stream) == -1) {
ret = -1;
break;
}
@@ -1,5 +1,15 @@
#include "locale.h"
#include "global.h"
// necessary to generate symbols in this TU
#undef MSL_INLINE
#define MSL_INLINE __declspec(weak)
#include "ctype.h"
#if PLATFORM_GCN
#define ctrl __control_char
#define motn __motion_char
#define spac __space_char
@@ -46,16 +56,6 @@ unsigned char __lower_map[256] = {
// clang-format on
};
int tolower(int __c) {
{
if (__c == -1) {
return 0xffffffff;
}
return (unsigned int)__lower_map[__c & 0xff];
}
}
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,
@@ -75,3 +75,72 @@ unsigned char __upper_map[256] = {
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
// clang-format on
};
#else
#define alph ctype_alpha
#define blnk ctype_blank
#define cntl ctype_cntrl
#define digi ctype_digit | ctype_graph | ctype_print
#define grph ctype_graph
#define lowc ctype_lower | ctype_alpha | ctype_graph | ctype_print
#define prnt ctype_print
#define punc ctype_punct | ctype_graph | ctype_print
#define spac ctype_space
#define uppc ctype_upper | ctype_alpha | ctype_graph | ctype_print
#define hexd ctype_xdigit
#define dhex hexd | digi
#define uhex hexd | uppc
#define lhex hexd | lowc
#define ctbl cntl | blnk
#define ctsp cntl | spac
#define sblp spac | blnk | prnt
#define csbl cntl | spac | blnk
const unsigned short __ctype_mapC[256] = {
cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, csbl, ctsp, ctsp, ctsp, ctsp, cntl, cntl,
cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl, cntl,
sblp, 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, cntl
};
const unsigned char __lower_mapC[0x100] = {
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
};
const unsigned char __upper_mapC[0x100] = {
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
};
#endif
@@ -36,7 +36,11 @@ size_t __fwrite(const void* buffer, size_t size, size_t count, FILE* stream) {
if (stream->file_state.io_state == __neutral) {
if (stream->file_mode.io_mode & __write) {
if (stream->file_mode.io_mode & __append) {
#if PLATFORM_GCN
if (fseek(stream, 0, SEEK_END))
#else
if (_fseek(stream, 0, SEEK_END))
#endif
return 0;
}
stream->file_state.io_state = __writing;
@@ -63,6 +67,7 @@ size_t __fwrite(const void* buffer, size_t size, size_t count, FILE* stream) {
if (num_bytes > bytes_to_go)
num_bytes = bytes_to_go;
if (stream->file_mode.buffer_mode == _IOLBF && num_bytes)
if ((newline = (unsigned char*)__memrchr(write_ptr, '\n', num_bytes)) != NULL)
num_bytes = newline + 1 - write_ptr;
@@ -71,12 +76,15 @@ size_t __fwrite(const void* buffer, size_t size, size_t count, FILE* stream) {
memcpy(stream->buffer_ptr, write_ptr, num_bytes);
write_ptr += num_bytes;
#if PLATFORM_GCN
bytes_written += num_bytes;
#endif
bytes_to_go -= num_bytes;
stream->buffer_ptr += num_bytes;
stream->buffer_length -= num_bytes;
}
if (!stream->buffer_length || newline != NULL ||
(stream->file_mode.buffer_mode == _IONBF))
{
@@ -88,6 +96,9 @@ size_t __fwrite(const void* buffer, size_t size, size_t count, FILE* stream) {
break;
}
}
#if !PLATFORM_GCN
bytes_written += num_bytes;
#endif
} while (bytes_to_go && always_buffer);
}
@@ -99,10 +110,17 @@ size_t __fwrite(const void* buffer, size_t size, size_t count, FILE* stream) {
stream->buffer_size = bytes_to_go;
stream->buffer_ptr = write_ptr + bytes_to_go;
#if PLATFORM_GCN
if (__flush_buffer(stream, &num_bytes) != __no_io_error)
set_error(stream);
bytes_written += num_bytes;
#else
if (__flush_buffer(stream, &num_bytes) != __no_io_error)
set_error(stream);
else
bytes_written += num_bytes;
#endif
stream->buffer = save_buffer;
stream->buffer_size = save_size;
@@ -115,5 +133,9 @@ size_t __fwrite(const void* buffer, size_t size, size_t count, FILE* stream) {
if (stream->file_mode.buffer_mode != _IOFBF)
stream->buffer_length = 0;
#if PLATFORM_GCN
return ((bytes_written + size - 1) / size);
#else
return bytes_written / size;
#endif
}
@@ -6,8 +6,8 @@ int stricmp(const char* str1, const char* str2) {
char b_var;
do {
b_var = _tolower(*str1++);
a_var = _tolower(*str2++);
b_var = tolower(*str1++);
a_var = tolower(*str2++);
if (b_var < a_var) {
return -1;
@@ -72,8 +72,8 @@ int __msl_strnicmp(const char* str1, const char* str2, int n) {
char c1, c2;
for (i = 0; i < n; i++) {
c1 = _tolower(*str1++);
c2 = _tolower(*str2++);
c1 = tolower(*str1++);
c2 = tolower(*str2++);
if (c1 < c2) {
return -1;
@@ -1,15 +1,16 @@
#include "float.h"
#include "global.h"
int __float_nan[] = {0x7FFFFFFF};
int __float_huge[] = {0x7F800000};
#if !__REVOLUTION_SDK__
#if PLATFORM_GCN
int __float_max[] = {0x7F7FFFFF};
int __float_epsilon[] = {0x34000000};
#endif
#if DEBUG
unsigned long long __double_huge[] = {0x7ff0000000000000ULL};
#if !PLATFORM_GCN
int __double_huge[] = {0x7FF00000, 0};
#endif
@@ -0,0 +1,122 @@
#include <locale.h>
#include <ctype.h>
#include <wctype_api.h>
#include <mbstring.h>
#pragma options align=native
#pragma warn_padding off
struct lconv __lconv = {
".",
"",
"",
"",
"",
"",
"",
"",
"",
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
"",
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
0x7F
};
#pragma warn_padding reset
#pragma options align=reset
struct _loc_ctype_cmpt _loc_ctyp_C = {
"C",
&__ctype_mapC[0],
&__upper_mapC[0],
&__lower_mapC[0],
&__wctype_mapC[0],
&__wupper_mapC[0],
&__wlower_mapC[0],
__mbtowc_noconv,
__wctomb_noconv
};
unsigned short char_coll_tableC[] = {
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x11,0x12,0x13,0x14,0x15,0x16,
0x17,0x2B,0x2D,0x2F,0x31,0x33,0x35,0x37,0x39,0x3B,0x3D,0x3F,0x41,0x43,0x45,0x47,
0x49,0x4B,0x4D,0x4F,0x51,0x53,0x55,0x57,0x59,0x5B,0x5D,0x18,0x19,0x1A,0x1B,0x1C,
0x00,0x2C,0x2E,0x30,0x32,0x34,0x36,0x38,0x3A,0x3C,0x3E,0x40,0x42,0x44,0x46,0x48,
0x4A,0x4C,0x4E,0x50,0x52,0x54,0x56,0x58,0x5A,0x5C,0x5E,0x1D,0x1E,0x1F,0x20,0x00
};
struct _loc_coll_cmpt _loc_coll_C = {
"C",
0x20,
0x6E,
0,
char_coll_tableC,
NULL
};
struct _loc_mon_cmpt _loc_mon_C = {
"C",
"",
"",
"",
"",
"",
"",
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
"",
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
0x7F,
0x7F
};
struct _loc_num_cmpt _loc_num_C = {
"C",
".",
"",
"",
};
struct _loc_time_cmpt _loc_tim_C = {
"C",
"AM|PM",
"%a %b %e %T %Y",
"%I:%M:%S %p",
"%m/%d/%y",
"%T",
"Sun|Sunday|Mon|Monday|Tue|Tuesday|Wed|Wednesday|Thu|Thursday|Fri|Friday|Sat|Saturday",
"Jan|January|Feb|February|Mar|March|Apr|April|May|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December",
""
};
struct __locale _current_locale = {
NULL,
"C",
&_loc_coll_C,
&_loc_ctyp_C,
&_loc_mon_C,
&_loc_num_C,
&_loc_tim_C
};
@@ -0,0 +1,51 @@
// I think this TU didn't include the header or used a different header
// allowing for both the inline definition and these symbols to exist
#define __HI(x) *(int*)&x
#define __LO(x) *(1 + (int*)&x)
#define __HIp(x) *(int*)x
#define __LOp(x) *(1 + (int*)x)
int __fpclassifyf(float x) {
switch ((*(long*)&x) & 0x7f800000) {
case 0x7f800000: {
if ((*(long*)&x) & 0x007fffff)
return 1;
else
return 2;
break;
}
case 0: {
if ((*(long*)&x) & 0x007fffff)
return 5;
else
return 3;
break;
}
}
return 4;
}
int __signbitd(double x) {
return __HI(x) & 0x80000000;
}
int __fpclassifyd(double x) {
switch (__HI(x) & 0x7ff00000) {
case 0x7ff00000: {
if ((__HI(x) & 0x000fffff) || (__LO(x) & 0xffffffff))
return 1;
else
return 2;
break;
}
case 0: {
if ((__HI(x) & 0x000fffff) || (__LO(x) & 0xffffffff))
return 5;
else
return 3;
break;
}
}
return 4;
}
@@ -0,0 +1,7 @@
#include "global.h"
// necessary to generate symbols in this TU
#undef MSL_INLINE
#define MSL_INLINE __declspec(weak)
#include <cmath.h>
@@ -1,64 +1,103 @@
#include "mbstring.h"
#include "cstring.h"
#include <locale.h>
#include "global.h"
#if !PLATFORM_GCN
int mbtowc(wchar_t* pwc, const char* s, size_t n) {
return _current_locale.ctype_cmpt_ptr->decode_mb(pwc, s, n);
}
#endif
inline static int unicode_to_UTF8(char* s, wchar_t wchar) {
int number_of_bytes;
wchar_t wide_char;
char* target_ptr;
char first_byte_mark[4] = { 0x00, 0x00, 0xc0, 0xe0 };
int number_of_bytes;
wchar_t wide_char;
char* target_ptr;
char first_byte_mark[4] = { 0x00, 0x00, 0xc0, 0xe0 };
if (!s)
return (0);
if (!s)
return (0);
wide_char = wchar;
if (wide_char < 0x0080)
number_of_bytes = 1;
else if (wide_char < 0x0800)
number_of_bytes = 2;
else
number_of_bytes = 3;
wide_char = wchar;
if (wide_char < 0x0080)
number_of_bytes = 1;
else if (wide_char < 0x0800)
number_of_bytes = 2;
else
number_of_bytes = 3;
target_ptr = s + number_of_bytes;
target_ptr = s + number_of_bytes;
switch (number_of_bytes) {
case 3:
*--target_ptr = (wide_char & 0x003f) | 0x80;
wide_char >>= 6;
case 2:
*--target_ptr = (wide_char & 0x003f) | 0x80;
wide_char >>= 6;
case 1:
*--target_ptr = wide_char | first_byte_mark[number_of_bytes];
}
switch (number_of_bytes) {
case 3:
*--target_ptr = (wide_char & 0x003f) | 0x80;
wide_char >>= 6;
case 2:
*--target_ptr = (wide_char & 0x003f) | 0x80;
wide_char >>= 6;
case 1:
*--target_ptr = wide_char | first_byte_mark[number_of_bytes];
}
return number_of_bytes;
return number_of_bytes;
}
inline int wctomb(char* s, wchar_t wchar) { return (unicode_to_UTF8(s, wchar)); }
int __mbtowc_noconv(wchar_t* pwc, const char* s, size_t n) {
if (!s)
return 0;
if (!n)
return -1;
if (pwc)
*pwc = (unsigned char)*s;
if (!*s)
return(0);
return 1;
}
int __wctomb_noconv(char* s, wchar_t wchar) {
if (!s)
return 0;
*s = wchar;
return 1;
}
int wctomb(char* s, wchar_t wchar) {
#if PLATFORM_GCN
return (unicode_to_UTF8(s, wchar));
#else
return _current_locale.ctype_cmpt_ptr->encode_wc(s, wchar);
#endif
}
size_t wcstombs(char* s, const wchar_t* pwcs, size_t n) {
int chars_written = 0;
int result;
char temp[3];
wchar_t* source;
int chars_written = 0;
int result;
char temp[3];
wchar_t* source;
if (!s || !pwcs)
return (0);
if (!s || !pwcs)
return (0);
source = (wchar_t*)pwcs;
while (chars_written <= n) {
if (!*source) {
*(s + chars_written) = '\0';
break;
} else {
result = wctomb(temp, *source++);
if ((chars_written + result) <= n) {
strncpy(s + chars_written, temp, result);
chars_written += result;
} else
break;
}
}
source = (wchar_t*)pwcs;
while (chars_written <= n) {
if (!*source) {
*(s + chars_written) = '\0';
break;
} else {
result = wctomb(temp, *source++);
if ((chars_written + result) <= n) {
strncpy(s + chars_written, temp, result);
chars_written += result;
} else
break;
}
}
return chars_written;
return chars_written;
}
@@ -1,8 +1,8 @@
#include "cstring.h"
void* memmove(void* dst, const void* src, size_t n) {
unsigned char* csrc;
unsigned char* cdst;
const char* csrc;
char* cdst;
int reverse = (unsigned int)src < (unsigned int)dst;
@@ -24,19 +24,11 @@ void* memmove(void* dst, const void* src, size_t n) {
return dst;
} else {
if (!reverse) {
csrc = ((unsigned char*)src) - 1;
cdst = ((unsigned char*)dst) - 1;
n++;
while (--n > 0) {
for (csrc = (const char*)src - 1, cdst = (char*)dst - 1, n++; --n;){
*++cdst = *++csrc;
}
} else {
csrc = (unsigned char*)src + n;
cdst = (unsigned char*)dst + n;
n++;
while (--n > 0) {
for (csrc = (const char*)src + n, cdst = (char*)dst + n, n++; --n;){
*--cdst = *--csrc;
}
}
@@ -1,5 +1,7 @@
#include "mem_funcs.h"
#include "global.h"
#define cps ((unsigned char*)src)
#define cpd ((unsigned char*)dst)
#define lps ((unsigned long*)src)
@@ -188,6 +190,11 @@ void __copy_longs_rev_unaligned(void* dst, const void* src, size_t n) {
cps += 4 - src_offset;
#if !PLATFORM_GCN
cps = ((unsigned char *) lps);
cpd = ((unsigned char *) lpd);
#endif
i = n >> 3;
v1 = *--lps;
@@ -206,6 +213,11 @@ void __copy_longs_rev_unaligned(void* dst, const void* src, size_t n) {
n &= 3;
#if !PLATFORM_GCN
cps = ((unsigned char *) lps);
cpd = ((unsigned char *) lpd);
#endif
if (n) {
cps += src_offset;
do
@@ -3,10 +3,14 @@
#include "critical_regions.h"
#include "ctype.h"
#include "scanf.h"
#include "cmath.h"
#include "cstdio.h"
#include "cstring.h"
#include "cstdint.h"
#include "wchar_io.h"
#define LDBL_MANT_DIG 53
#define TARGET_FLOAT_BITS 64
#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS / 8)
#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP
@@ -28,8 +32,18 @@ enum argument_options {
short_argument,
long_argument,
long_long_argument,
#if PLATFORM_GCN
long_double_argument,
wchar_argument
#endif
wchar_argument,
intmax_argument,
size_t_argument,
ptrdiff_argument,
#if !PLATFORM_GCN
long_double_argument,
#endif
};
typedef struct {
@@ -154,12 +168,21 @@ static const char* parse_format(const char* format_string, va_list* arg, print_f
f.argument_options = long_long_argument;
c = *++s;
}
break;
case 'L':
f.argument_options = long_double_argument;
break;
#if !PLATFORM_GCN
case 'j':
f.argument_options = intmax_argument;
break;
case 't':
f.argument_options = ptrdiff_argument;
break;
case 'z':
f.argument_options = size_t_argument;
break;
#endif
default:
flag_found = 0;
break;
@@ -192,7 +215,14 @@ static const char* parse_format(const char* format_string, va_list* arg, print_f
case 'f':
case 'F':
if (f.argument_options == short_argument || f.argument_options == long_long_argument) {
if (f.argument_options == short_argument
#if !PLATFORM_GCN
|| f.argument_options == intmax_argument
|| f.argument_options == size_t_argument
|| f.argument_options == ptrdiff_argument
#endif
|| f.argument_options == long_long_argument)
{
f.conversion_char = 0xFF;
break;
}
@@ -208,8 +238,14 @@ static const char* parse_format(const char* format_string, va_list* arg, print_f
f.precision = 0xD;
}
if (f.argument_options == short_argument || f.argument_options == long_long_argument ||
f.argument_options == char_argument)
if (f.argument_options == short_argument
#if !PLATFORM_GCN
|| f.argument_options == intmax_argument
|| f.argument_options == size_t_argument
|| f.argument_options == ptrdiff_argument
#endif
|| f.argument_options == long_long_argument
|| f.argument_options == char_argument)
{
f.conversion_char = 0xFF;
}
@@ -224,8 +260,14 @@ static const char* parse_format(const char* format_string, va_list* arg, print_f
case 'e':
case 'E':
if (f.argument_options == short_argument || f.argument_options == long_long_argument ||
f.argument_options == char_argument)
if (f.argument_options == short_argument
#if !PLATFORM_GCN
|| f.argument_options == intmax_argument
|| f.argument_options == size_t_argument
|| f.argument_options == ptrdiff_argument
#endif
|| f.argument_options == long_long_argument
|| f.argument_options == char_argument)
{
f.conversion_char = 0xFF;
break;
@@ -303,7 +345,11 @@ static char* long2str(signed long num, char* buff, print_format format) {
base = 10;
if (num < 0) {
unsigned_num = -unsigned_num;
#if !PLATFORM_GCN
if (num != 0x8000000000000000L)
#endif
unsigned_num = -unsigned_num;
minus = 1;
}
break;
@@ -405,7 +451,11 @@ static char* longlong2str(signed long long num, char* pBuf, print_format fmt) {
base = 10;
if (num < 0) {
unsigned_num = -unsigned_num;
#if !PLATFORM_GCN
if (num != 0x8000000000000000LL)
#endif
unsigned_num = -unsigned_num;
minus = 1;
}
break;
@@ -486,6 +536,7 @@ static char* longlong2str(signed long long num, char* pBuf, print_format fmt) {
}
static char* double2hex(long double num, char* buff, print_format format) {
#if PLATFORM_GCN
int offset, what_nibble = 0;
char* wrk_byte_ptr;
char *p, *q;
@@ -611,6 +662,175 @@ static char* double2hex(long double num, char* buff, print_format format) {
}
return p;
#else
char *p;
unsigned char *q;
unsigned char working_byte;
long double ld;
int expbits, expmask;
unsigned snum;
long exp;
print_format exp_format;
int hex_precision;
int mantissa_bit;
decform form;
decimal dec;
int radix_marker;
radix_marker = *(unsigned char *)(__lconv).decimal_point;
p = buff;
ld = num;
if (format.precision > 509) {
return 0;
}
form.style = (char)0;
form.digits = 0x20;
__num2dec(&form, num, &dec);
switch(*dec.sig.text){
case '0':
dec.exp = 0;
break;
case 'I':
if (dec.sign) {
p = buff - 5;
if (format.conversion_char == 'A') strcpy(p, "-INF");
else strcpy(p, "-inf");
}
else {
p = buff - 4;
if (format.conversion_char == 'A') strcpy(p, "INF");
else strcpy(p, "inf");
}
return p;
case 'N':
if (dec.sign) {
p = buff - 5;
if (format.conversion_char == 'A') strcpy(p, "-NAN");
else strcpy(p, "-nan");
}
else {
p = buff - 4;
if (format.conversion_char == 'A') strcpy(p, "NAN");
else strcpy(p, "nan");
}
return p;
}
exp_format.justification_options = right_justification;
exp_format.sign_options = sign_always;
exp_format.precision_specified = 0;
exp_format.alternate_form = 0;
exp_format.argument_options = normal_argument;
exp_format.field_width = 0;
exp_format.precision = 1;
exp_format.conversion_char = 'd';
expbits = 11;
expmask = 0x7FF;
snum = ((unsigned char *)&num)[0] << 25;
if (TARGET_FLOAT_EXP_BITS > 7)
snum |= ((unsigned char *)&num)[1] << 17;
if (TARGET_FLOAT_EXP_BITS > 15)
snum |= ((unsigned char *)&num)[2] << 9;
if (TARGET_FLOAT_EXP_BITS > 23)
snum |= ((unsigned char *)&num)[3] << 1;
snum = (snum >> (32 - expbits)) & expmask;
if(snum != 0)
exp = snum - 0x3FF;
else
exp = 0;
p = long2str(exp, buff, exp_format);
if (format.conversion_char == 'a')
*--p = 'p';
else
*--p = 'P';
q = (unsigned char *)&num;
if (TARGET_FLOAT_IMPLICIT_J_BIT) {
mantissa_bit = (1 + expbits + format.precision * 4) - 1;
}
else {
mantissa_bit = (1 + expbits + format.precision * 4) - 4;
}
for (hex_precision = format.precision; hex_precision >= 1; hex_precision--) {
if (mantissa_bit < 64) {
int mantissa_byte;
mantissa_byte = mantissa_bit >> 3;
working_byte = (*(q + mantissa_byte)) >> (7 - (mantissa_bit & 7));
if ((mantissa_bit & ~7) != ((mantissa_bit - 4) & ~7)) {
working_byte |= (unsigned char)(((*(q + (mantissa_byte - 1))) << 8) >> (7 - ((mantissa_bit) & 7)));
}
if (!TARGET_FLOAT_IMPLICIT_J_BIT) {
if (mantissa_bit == 1 + expbits) {
*--p = radix_marker;
working_byte &= 0x1;
}
}
if ((working_byte &= 0xF) < 10) {
working_byte += (unsigned char)'0';
}
else
if (format.conversion_char == 'a') {
working_byte += (unsigned char)('a' - 10);
}
else {
working_byte += (unsigned char)('A' - 10);
}
}
else {
working_byte = '0';
}
*--p = working_byte;
mantissa_bit -= 4;
}
if (TARGET_FLOAT_IMPLICIT_J_BIT){
if (format.precision || format.alternate_form) {
*--p = radix_marker;
}
if(fabsl(ld) != 0.0)
*--p = '1';
else
*--p = '0';
}
if (format.conversion_char == 'a') {
*--p = 'x';
}
else {
*--p = 'X';
}
*--p = '0';
if (dec.sign) {
*--p = '-';
}
else if (format.sign_options == sign_always) {
*--p = '+';
}
else if (format.sign_options == space_holder) {
*--p = ' ';
}
return p;
#endif
}
static void round_decimal(decimal* dec, int new_length) {
@@ -675,7 +895,11 @@ static char* float2str(long double num, char* buff, print_format format) {
int int_digits, frac_digits;
int radix_marker;
#if PLATFORM_GCN
radix_marker = '.';
#else
radix_marker = *(unsigned char*)__lconv.decimal_point;
#endif
if (format.precision > 509) {
return 0;
@@ -736,7 +960,12 @@ static char* float2str(long double num, char* buff, print_format format) {
return p;
}
dec.exp += dec.sig.length - 1;
#if PLATFORM_GCN
dec.exp += (dec.sig.length - 1);
#else
dec.exp += (short)(dec.sig.length - 1);
#endif
p = buff;
*--p = 0;
@@ -888,7 +1117,12 @@ static char* float2str(long double num, char* buff, print_format format) {
}
static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* WriteProcArg,
const char* format_str, va_list arg) {
const char* format_str, va_list arg
#if !PLATFORM_GCN
,int is_secure
#endif
)
{
int num_chars, chars_written, field_width;
const char* format_ptr;
const char* curr_format;
@@ -933,7 +1167,19 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
long_num = va_arg(arg, signed long);
} else if (format.argument_options == long_long_argument) {
long_long_num = va_arg(arg, signed long long);
} else {
}
#if !PLATFORM_GCN
else if (format.argument_options == intmax_argument) {
long_long_num = va_arg(arg, intmax_t);
}
else if (format.argument_options == size_t_argument) {
long_num = va_arg(arg, size_t);
}
else if (format.argument_options == ptrdiff_argument) {
long_num = va_arg(arg, ptrdiff_t);
}
#endif
else {
long_num = va_arg(arg, int);
}
@@ -945,7 +1191,12 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
long_num = (signed char)long_num;
}
if ((format.argument_options == long_long_argument)) {
if ((format.argument_options == long_long_argument)
#if !PLATFORM_GCN
|| format.argument_options == intmax_argument
#endif
)
{
if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) {
goto conversion_error;
}
@@ -966,7 +1217,19 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
long_num = va_arg(arg, unsigned long);
} else if (format.argument_options == long_long_argument) {
long_long_num = va_arg(arg, signed long long);
} else {
}
#if !PLATFORM_GCN
else if (format.argument_options == intmax_argument) {
long_long_num = va_arg(arg, intmax_t);
}
else if (format.argument_options == size_t_argument) {
long_num = va_arg(arg, size_t);
}
else if (format.argument_options == ptrdiff_argument) {
long_num = va_arg(arg, ptrdiff_t);
}
#endif
else {
long_num = va_arg(arg, unsigned int);
}
@@ -978,7 +1241,12 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
long_num = (unsigned char)long_num;
}
if ((format.argument_options == long_long_argument)) {
if ((format.argument_options == long_long_argument)
#if !PLATFORM_GCN
|| format.argument_options == intmax_argument
#endif
)
{
if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) {
goto conversion_error;
}
@@ -1029,6 +1297,13 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
if (format.argument_options == wchar_argument) {
wchar_t* wcs_ptr = va_arg(arg, wchar_t*);
#if !PLATFORM_GCN
if (is_secure && wcs_ptr == NULL){
__msl_runtime_constraint_violation_s(0,0,-1);
return -1;
}
#endif
if (wcs_ptr == NULL) {
wcs_ptr = L"";
}
@@ -1042,6 +1317,13 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
buff_ptr = va_arg(arg, char*);
}
#if !PLATFORM_GCN
if (is_secure && buff_ptr == NULL){
__msl_runtime_constraint_violation_s(0,0,-1);
return -1;
}
#endif
if (buff_ptr == NULL) {
buff_ptr = "";
}
@@ -1067,6 +1349,13 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
case 'n':
buff_ptr = va_arg(arg, char*);
#if !PLATFORM_GCN
if (is_secure){
__msl_runtime_constraint_violation_s(0,0,-1);
return -1;
}
#endif
switch (format.argument_options) {
case normal_argument:
*(int*)buff_ptr = chars_written;
@@ -1077,6 +1366,17 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
case long_argument:
*(signed long*)buff_ptr = chars_written;
break;
#if !PLATFORM_GCN
case intmax_argument:
*(intmax_t*)buff_ptr = chars_written;
break;
case size_t_argument:
*(size_t*)buff_ptr = chars_written;
break;
case ptrdiff_argument:
*(ptrdiff_t*)buff_ptr = chars_written;
break;
#endif
case long_long_argument:
*(signed long long*)buff_ptr = chars_written;
break;
@@ -1126,6 +1426,18 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
num_chars--;
}
#if !PLATFORM_GCN
if ((format.justification_options == zero_fill) && ((format.conversion_char == 'a') || (format.conversion_char == 'A')))
{
if (num_chars < 2)
return(-1);
if ((*WriteProc)(WriteProcArg, buff_ptr, 2) == 0)
return(-1);
num_chars -= 2;
buff_ptr += 2;
}
#endif
while (field_width < format.field_width) {
if ((*WriteProc)(WriteProcArg, &fill_char, 1) == 0) {
return -1;
@@ -1158,7 +1470,11 @@ static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* Wr
}
static void* __FileWrite(void* pFile, const char* pBuffer, size_t char_num) {
#if PLATFORM_GCN
return (fwrite(pBuffer, 1, char_num, (FILE*)pFile) == char_num ? pFile : 0);
#else
return (__fwrite(pBuffer, 1, char_num, (FILE*)pFile) == char_num ? pFile : 0);
#endif
}
static void* __StringWrite(void* pCtrl, const char* pBuffer, size_t char_num) {
@@ -1185,7 +1501,11 @@ int printf(const char* format, ...) {
{
va_list args;
va_start(args, format);
#if PLATFORM_GCN
res = __pformatter(&__FileWrite, (void*)stdout, format, args);
#else
res = __pformatter(&__FileWrite, (void*)stdout, format, args, 0);
#endif
}
__end_critical_region(stdin_access);
return res;
@@ -1202,7 +1522,11 @@ int fprintf(FILE* file, const char* format, ...) {
{
va_list args;
va_start(args, format);
#if PLATFORM_GCN
res = __pformatter(&__FileWrite, (void*)file, format, args);
#else
res = __pformatter(&__FileWrite, (void*)file, format, args, 0);
#endif
}
__end_critical_region(stdin_access);
return res;
@@ -1216,7 +1540,11 @@ int vprintf(const char* format, va_list arg) {
}
__begin_critical_region(stdin_access);
#if PLATFORM_GCN
ret = __pformatter(&__FileWrite, (void*)stdout, format, arg);
#else
ret = __pformatter(&__FileWrite, (void*)stdout, format, arg, 0);
#endif
__end_critical_region(stdin_access);
return ret;
}
@@ -1228,15 +1556,33 @@ int vsnprintf(char* s, size_t n, const char* format, va_list arg) {
osc.MaxCharCount = n;
osc.CharsWritten = 0;
#if PLATFORM_GCN
end = __pformatter(&__StringWrite, &osc, format, arg);
#else
end = __pformatter(&__StringWrite, &osc, format, arg, 0);
#endif
if (s) {
#if PLATFORM_GCN
s[(end < n) ? end : n - 1] = '\0';
#else
if (end < n) {
s[end] = '\0';
} else {
if (n > 0) {
s[n - 1] = '\0';
}
}
#endif
}
return end;
}
int vsprintf(char *s, const char *format, va_list arg) {
return vsnprintf(s, 0xFFFFFFFF, format, arg);
}
int snprintf(char* s, size_t n, const char* format, ...) {
va_list args;
va_start(args, format);
@@ -1,4 +1,744 @@
#include "scanf.h"
#include <ctype.h>
#include <cmath.h>
#include <cstdio.h>
#include <cstdint.h>
#include <strtoul.h>
#include <strtold.h>
enum argument_options {
normal_argument,
char_argument,
short_argument,
long_argument,
intmax_argument,
size_t_argument,
ptrdiff_argument,
long_long_argument,
double_argument,
long_double_argument,
wchar_argument
};
typedef unsigned char char_map[32];
typedef struct {
unsigned char suppress_assignment;
unsigned char field_width_specified;
unsigned char argument_options;
unsigned char conversion_char;
int field_width;
char_map char_set;
} scan_format;
#define set_char_map(map, ch) map[(unsigned char)ch >> 3] |= (1 << (ch & 7))
#define tst_char_map(map, ch) (map[(unsigned char)ch >> 3] & (1 << (ch & 7)))
static const char* parse_format(const char* format_string, scan_format *format) {
const char* s = format_string;
int c;
int flag_found, invert;
scan_format f = { 0, 0, normal_argument, 0, 2147483647, { 0 } };
if (((c = *++s) == '%')) {
f.conversion_char = c;
*format = f;
return ((const char*)s + 1);
}
if (c == '*') {
f.suppress_assignment = 1;
c = *++s;
}
if (isdigit(c)) {
f.field_width = 0;
do {
f.field_width = (f.field_width * 10) + (c - '0');
c = *++s;
} while (isdigit(c));
if (f.field_width == 0) {
f.conversion_char = 0xFF;
*format = f;
return ((const char*)s + 1);
}
f.field_width_specified = 1;
}
flag_found = 1;
switch (c) {
case 'h':
f.argument_options = short_argument;
if (s[1] == 'h') {
f.argument_options = char_argument;
c = *++s;
}
break;
case 'l':
f.argument_options = long_argument;
if (s[1] == 'l') {
f.argument_options = long_long_argument;
c = *++s;
}
break;
case 'L':
f.argument_options = long_double_argument;
break;
case 'j':
f.argument_options = intmax_argument;
break;
case 'z':
f.argument_options = size_t_argument;
break;
case 't':
f.argument_options = ptrdiff_argument;
break;
default:
flag_found = 0;
}
if (flag_found) {
c = *++s;
}
f.conversion_char = c;
switch (c) {
case 'd':
case 'i':
case 'u':
case 'o':
case 'x':
case 'X':
if (f.argument_options == long_double_argument) {
f.conversion_char = 0xFF;
break;
}
break;
case 'a':
case 'A':
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
if (f.argument_options == char_argument || f.argument_options == short_argument || f.argument_options == intmax_argument || f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument || f.argument_options == long_long_argument) {
f.conversion_char = 0xFF;
break;
}
if (f.argument_options == long_argument) {
f.argument_options = double_argument;
}
break;
case 'p':
f.argument_options = long_argument;
f.conversion_char = 'x';
break;
case 'c':
if (f.argument_options == long_argument) {
f.argument_options = wchar_argument;
}
else {
if (f.argument_options != normal_argument) {
f.conversion_char = 0xFF;
}
}
break;
case 's':
if (f.argument_options == long_argument) {
f.argument_options = wchar_argument;
}
else {
if (f.argument_options != normal_argument) {
f.conversion_char = 0xFF;
}
}
{
int i;
unsigned char* p;
for (i = sizeof(f.char_set), p = f.char_set; i; --i) {
*p++ = 0xFF;
}
f.char_set[1] = 0xC1;
f.char_set[4] = 0xFE;
}
break;
case 'n':
break;
case '[':
if (f.argument_options == long_argument) {
f.argument_options = wchar_argument;
}
else {
if (f.argument_options != normal_argument) {
f.conversion_char = 0xFF;
}
}
c = *++s;
invert = 0;
if (c == '^') {
invert = 1;
c = *++s;
}
if (c == ']') {
set_char_map(f.char_set, ']');
c = *++s;
}
while (c && c != ']') {
int d;
set_char_map(f.char_set, c);
if (*(s + 1) == '-' && (d = *(s + 2)) != 0 && d != ']') {
while (++c <= d) {
set_char_map(f.char_set, c);
}
c = *(s += 3);
}
else {
c = *++s;
}
}
if (!c) {
f.conversion_char = 0xFF;
break;
}
if (invert) {
int i;
unsigned char* p;
for (i = sizeof(f.char_set), p = f.char_set; i; --i, ++p) {
*p = ~*p;
}
break;
}
break;
default:
f.conversion_char = 0xFF;
break;
}
*format = f;
return ((const char*)s + 1);
}
static int __sformatter(int (*ReadProc)(void *, int, int), void * ReadProcArg, const char * format_str, va_list arg, int is_secure)
{
int num_chars, chars_read, items_assigned, conversions;
int base, negative, overflow;
int rval;
const char* format_ptr;
char format_char;
char c;
scan_format format;
long long_num;
unsigned long u_long_num;
long long long_long_num = 0;
unsigned long long u_long_long_num;
long double long_double_num;
char * arg_ptr;
int elem_valid;
size_t elem_maxsize;
int match_failure = 0;
int terminate = 0;
format_ptr = format_str;
chars_read = 0;
items_assigned = 0;
conversions = 0;
while (!terminate && (format_char = *format_ptr) != 0)
{
if (isspace(format_char))
{
do{
format_char = *++format_ptr;
} while (isspace(format_char));
if (!match_failure)
{
while (isspace(c = (*ReadProc)(ReadProcArg, 0, __GetAChar)))
++chars_read;
(*ReadProc)(ReadProcArg, c, __UngetAChar);
}
continue;
}
if ((format_char != '%') && (!match_failure))
{
if ((c = (*ReadProc)(ReadProcArg, 0, __GetAChar)) != (unsigned char)format_char)
{
(*ReadProc)(ReadProcArg, c, __UngetAChar);
if (!is_secure)
goto exit;
else
{
match_failure = 1;
++format_ptr;
continue;
}
}
chars_read++;
format_ptr++;
continue;
}
format_ptr = parse_format(format_ptr, &format);
if (!format.suppress_assignment && format.conversion_char != '%')
{
arg_ptr = va_arg(arg, char *);
}
else
{
arg_ptr = 0;
}
if ((format.conversion_char != 'n') && (!match_failure) && (*ReadProc)(ReadProcArg, 0, __TestForError))
{
if (!is_secure)
goto exit;
else
match_failure = 1;
}
switch (format.conversion_char)
{
case 'd':
base = 10;
goto signed_int;
case 'i':
base = 0;
signed_int:
if (match_failure)
{
long_num = 0;
long_long_num = 0;
}
else
{
if ((format.argument_options == long_long_argument) || (format.argument_options == intmax_argument))
u_long_long_num = __strtoull(base, format.field_width, ReadProc, ReadProcArg, &num_chars, &negative, &overflow);
else
u_long_num = __strtoul(base, format.field_width, ReadProc, ReadProcArg, &num_chars, &negative, &overflow);
if (!num_chars)
{
if (!is_secure)
goto exit;
else
{
match_failure = 1;
long_num = 0;
long_long_num = 0;
goto signed_int_assign;
}
}
chars_read += num_chars;
if ((format.argument_options == long_long_argument) || (format.argument_options == intmax_argument))
long_long_num = (negative ? -u_long_long_num : u_long_long_num);
else
long_num = (negative ? -u_long_num : u_long_num);
}
signed_int_assign:
if (arg_ptr)
{
switch (format.argument_options)
{
case normal_argument: * (int *) arg_ptr = long_num; break;
case char_argument: * (signed char *) arg_ptr = long_num; break;
case short_argument: * (short *) arg_ptr = long_num; break;
case long_argument: * (long *) arg_ptr = long_num; break;
case intmax_argument: * (intmax_t *) arg_ptr = long_long_num; break;
case size_t_argument: * (size_t *) arg_ptr = long_num; break;
case ptrdiff_argument: * (ptrdiff_t *) arg_ptr = long_num; break;
case long_long_argument: * (long long *) arg_ptr = long_long_num; break;
}
if (!match_failure) items_assigned++;
}
conversions++;
break;
case 'o':
base = 8;
goto unsigned_int;
case 'u':
base = 10;
goto unsigned_int;
case 'x':
case 'X':
base = 16;
unsigned_int:
if (match_failure)
{
u_long_num = 0;
u_long_long_num = 0;
}
else
{
if ((format.argument_options == long_long_argument) || (format.argument_options == intmax_argument))
u_long_long_num = __strtoull(base, format.field_width, ReadProc, ReadProcArg, &num_chars, &negative, &overflow);
else
u_long_num = __strtoul(base, format.field_width, ReadProc, ReadProcArg, &num_chars, &negative, &overflow);
if (!num_chars)
{
if (!is_secure)
goto exit;
else
{
match_failure = 1;
u_long_num = 0;
u_long_long_num = 0;
goto unsigned_int_assign;
}
}
chars_read += num_chars;
if (negative)
if (format.argument_options == long_long_argument)
u_long_long_num = -u_long_long_num;
else
u_long_num = -u_long_num;
}
unsigned_int_assign:
if (arg_ptr)
{
switch (format.argument_options)
{
case normal_argument: * (unsigned int *)arg_ptr = u_long_num; break;
case char_argument: * (unsigned char *)arg_ptr = u_long_num; break;
case short_argument: * (unsigned short *)arg_ptr = u_long_num; break;
case long_argument: * (unsigned long *)arg_ptr = u_long_num; break;
case intmax_argument: * (intmax_t *) arg_ptr = u_long_long_num; break;
case size_t_argument: * (size_t *) arg_ptr = u_long_num; break;
case ptrdiff_argument: * (ptrdiff_t *) arg_ptr = u_long_num; break;
case long_long_argument: * (unsigned long long *) arg_ptr = u_long_long_num; break;
}
if (!match_failure) items_assigned++;
}
conversions++;
break;
case 'a':
case 'A':
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
flt:
if (match_failure) long_double_num = NAN;
else
{
long_double_num = __strtold(format.field_width, ReadProc, ReadProcArg, &num_chars, &overflow);
if (!num_chars)
{
if (!is_secure)
goto exit;
else
{
match_failure = 1;
long_double_num = NAN;
goto assign_float;
}
}
chars_read += num_chars;
}
assign_float:
if (arg_ptr)
{
switch (format.argument_options)
{
case normal_argument: * (float *) arg_ptr = long_double_num; break;
case double_argument: * (double *) arg_ptr = long_double_num; break;
case long_double_argument: * (long double *) arg_ptr = long_double_num; break;
}
if (!match_failure) items_assigned++;
}
conversions++;
break;
case 'c':
if (!format.field_width_specified) format.field_width = 1;
if (arg_ptr)
{
if (is_secure)
{
elem_valid = 1;
elem_maxsize = va_arg(arg, size_t);
}
num_chars = 0;
if (match_failure)
{
if (elem_maxsize > 0)
*arg_ptr = 0;
continue;
}
else
{
char * arg_start = arg_ptr;
while (format.field_width-- && (!is_secure || ((elem_valid = (elem_maxsize > num_chars)) != 0)) && ((rval = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != -1))
{
c = rval;
if (format.argument_options == wchar_argument)
{
mbtowc(((wchar_t*)arg_ptr), (char*)(&c), 1);
arg_ptr += sizeof(wchar_t);
}
else
*arg_ptr++ = c;
num_chars++;
}
c = rval;
if (!num_chars || (is_secure && !elem_valid))
{
if (!is_secure)
goto exit;
else
{
match_failure = 1;
if (elem_maxsize > 0)
*arg_start = 0;
continue;
}
}
chars_read += num_chars;
items_assigned++;
}
}
else
{
num_chars = 0;
while (format.field_width-- && ((rval = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != -1))
{
c = rval;
num_chars++;
}
c = rval;
if (!num_chars) goto exit;
}
conversions++;
break;
case '%':
if (match_failure)
continue;
else
{
while (isspace(c = (*ReadProc)(ReadProcArg, 0, __GetAChar)))
chars_read++;
if (c != '%')
{
(*ReadProc)(ReadProcArg, c, __UngetAChar);
if (!is_secure)
goto exit;
else
{
match_failure = 1;
continue;
}
}
chars_read++;
}
break;
case 's':
if (!match_failure)
{
c = (*ReadProc)(ReadProcArg, 0, __GetAChar);
while(isspace(c))
{
chars_read++;
c = (*ReadProc)(ReadProcArg, 0, __GetAChar);
}
(*ReadProc)(ReadProcArg, c, __UngetAChar);
}
case '[':
if (arg_ptr)
{
if (is_secure)
{
elem_valid = 1;
elem_maxsize = va_arg(arg, size_t) - 1;
}
num_chars = 0;
if (match_failure)
{
if (elem_maxsize > 0)
*arg_ptr = 0;
continue;
}
else
{
char * arg_start = arg_ptr;
while (format.field_width-- &&
(!is_secure || ((elem_valid = (elem_maxsize >= num_chars)) != 0)) &&
((rval = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != -1))
{
c = rval;
if (!tst_char_map(format.char_set, c))
break;
if (format.argument_options == wchar_argument)
{
mbtowc(((wchar_t*)arg_ptr), (char*)&c, 1);
arg_ptr = (char*)((wchar_t*)arg_ptr + 1);
}
else
*arg_ptr++ = c;
num_chars++;
}
c = rval;
if (!num_chars || (is_secure && !elem_valid))
{
(*ReadProc)(ReadProcArg, c, __UngetAChar);
if (!is_secure)
goto exit;
else
{
match_failure = 1;
if (elem_maxsize > 0)
*arg_start = 0;
continue;
}
}
chars_read += num_chars;
if (format.argument_options == wchar_argument)
*(wchar_t*)arg_ptr = L'\0';
else
*arg_ptr = 0;
items_assigned++;
}
}
else
{
num_chars = 0;
while (format.field_width-- &&
((rval = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != -1))
{
c = rval;
if (!tst_char_map(format.char_set, c))
break;
num_chars++;
}
c = rval;
if (!num_chars)
{
(*ReadProc)(ReadProcArg, c, __UngetAChar);
break;
}
chars_read += num_chars;
}
if (format.field_width >= 0)
(*ReadProc)(ReadProcArg, c, __UngetAChar);
conversions++;
break;
case 'n':
if (arg_ptr)
switch (format.argument_options)
{
case normal_argument: * (int *) arg_ptr = chars_read; break;
case short_argument: * (short *) arg_ptr = chars_read; break;
case long_argument: * (long *) arg_ptr = chars_read; break;
case char_argument: * (char *) arg_ptr = chars_read; break;
case long_long_argument: * (long long *) arg_ptr = chars_read; break;
}
continue;
case 0xFF:
default:
goto exit;
}
}
exit:
if ((*ReadProc)(ReadProcArg, 0, __TestForError) && conversions == 0)
return -1;
return items_assigned;
}
int __StringRead(void* pPtr, int ch, int act) {
char ret;
@@ -31,3 +771,32 @@ int __StringRead(void* pPtr, int ch, int act) {
return 0;
}
int isspace_string(const char *s) {
int i = 0;
while(s[i] != '\0'){
if(!isspace(s[i++])) return 0;
}
return 1;
}
int vsscanf(const char *s, const char *format, va_list arg) {
__InStrCtrl isc;
isc.NextChar = (char*)s;
if ((s == 0) || (*isc.NextChar == '\0') || isspace_string(s)) {
return -1;
}
isc.NullCharDetected = 0;
return __sformatter(&__StringRead, (void*)&isc, format, arg, 0);
}
int sscanf(const char *s, const char *pFormat, ...) {
int ret;
va_list args;
va_start(args, pFormat);
return vsscanf(s, pFormat, args);
}
@@ -0,0 +1,16 @@
#include <cstdio.h>
typedef void (*constraint_handler_t)(const char*, void*, int);
static constraint_handler_t __msl_constraint_handler = NULL;
void ignore_handler_s(const char* msg, void* ptr, int error);
void __msl_runtime_constraint_violation_s(const char* msg, void* ptr, int error) {
if (__msl_constraint_handler)
(*__msl_constraint_handler)(msg, ptr, error);
else
ignore_handler_s(msg, ptr, error);
}
void ignore_handler_s(const char* msg, void* ptr, int error) {}
@@ -1,14 +1,20 @@
#include "signal.h"
#include "critical_regions.h"
#if PLATFORM_GCN
#define SIGNAL_NUM 6
#else
#define SIGNAL_NUM 7
#endif
#define __std(ref) ref
__signal_func_ptr signal_funcs[6];
__signal_func_ptr signal_funcs[SIGNAL_NUM];
int raise(int sig) {
__signal_func_ptr signal_func;
if (sig < 1 || sig > 6) {
if (sig < 1 || sig > SIGNAL_NUM) {
return -1;
}
@@ -1,4 +1,5 @@
#include "cstring.h"
#include "global.h"
#define K1 0x80808080
#define K2 0xFEFEFEFF
@@ -42,7 +43,9 @@ char* strcpy(char* dst, const char* src) {
w = *((int*)(fromb));
t = w + K2;
#if !PLATFORM_GCN
t &= ~w;
#endif
t &= K1;
if (t) {
goto bytecopy;
@@ -54,6 +57,9 @@ char* strcpy(char* dst, const char* src) {
w = *(++((int*)(fromb)));
t = w + K2;
#if !PLATFORM_GCN
t &= ~w;
#endif
t &= K1;
if (t) {
goto adjust;
@@ -145,6 +151,9 @@ int strcmp(const char* str1, const char* str2) {
l1 = *(int*)left;
r1 = *(int*)right;
x = l1 + K2;
#if !PLATFORM_GCN
x &= ~l1;
#endif
if (x & K1) {
goto adjust;
}
@@ -158,10 +167,12 @@ int strcmp(const char* str1, const char* str2) {
}
}
#if PLATFORM_GCN
if (l1 > r1) {
return 1;
}
return -1;
#endif
adjust:
l1 = *left;
@@ -0,0 +1,663 @@
#include "strtold.h"
#include "cstdio.h"
#include "ansi_fp.h"
#include "locale.h"
#include "ctype.h"
#include "float.h"
#include "cmath.h"
#include "climits.h"
#include <errno.h>
extern double nan(const char*);
extern double __dec2num(const decimal* d);
#define TARGET_FLOAT_BITS 64
#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS / 8)
#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP
#define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG
#define TARGET_FLOAT_IMPLICIT_J_BIT 1
#define TARGET_FLOAT_MANT_BITS (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT)
#define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1)
enum scan_states {
start = 0x0001,
sig_start = 0x0002,
leading_sig_zeroes = 0x0004,
int_digit_loop = 0x0008,
frac_start = 0x0010,
frac_digit_loop = 0x0020,
sig_end = 0x0040,
exp_start = 0x0080,
leading_exp_digit = 0x0100,
leading_exp_zeroes = 0x0200,
exp_digit_loop = 0x0400,
finished = 0x0800,
failure = 0x1000,
nan_state = 0x2000,
infin_state = 0x4000,
hex_state = 0x8000
};
enum hex_scan_states {
not_hex = 0x0000,
hex_start = 0x0001,
hex_leading_sig_zeroes = 0x0002,
hex_int_digit_loop = 0x0004,
hex_frac_digit_loop = 0x0008,
hex_sig_end = 0x0010,
hex_exp_start = 0x0020,
hex_leading_exp_digit = 0x0040,
hex_leading_exp_zeroes = 0x0080,
hex_exp_digit_loop = 0x0100
};
#define final_state(scan_state) (scan_state & (finished | failure))
#define success(scan_state) \
(scan_state & \
(leading_sig_zeroes | int_digit_loop | frac_digit_loop | leading_exp_zeroes | exp_digit_loop | finished))
#define hex_success(count, scan_state) \
(count - 1 > 2 && scan_state & (hex_leading_sig_zeroes | hex_int_digit_loop | hex_frac_digit_loop | \
hex_leading_exp_zeroes | hex_exp_digit_loop))
#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar))
#define unfetch(c) (*ReadProc)(ReadProcArg, c, __UngetAChar)
long double __strtold(int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned,
int* overflow) {
int scan_state = start;
int hex_scan_state = not_hex;
int count = 0;
int spaces = 0;
int c;
decimal d = {0, 0, 0, {0, ""}};
int sig_negative = 0;
int exp_negative = 0;
long exp_value = 0;
int exp_adjust = 0;
register long double result = 0.0;
int sign_detected = 0;
int radix_marker = *(unsigned char*)(__lconv).decimal_point;
unsigned char* chptr;
unsigned char mantissa[TARGET_FLOAT_BYTES];
unsigned mantissa_digits;
unsigned long exponent = 0;
int ui;
unsigned char uch, uch1;
int NibbleIndex;
int expsign = 0;
int exp_digits = 0;
unsigned intdigits = 0;
*overflow = 0;
c = fetch();
while (count <= max_width && c != -1 && !final_state(scan_state)) {
switch (scan_state) {
case start:
if (isspace(c)) {
c = fetch();
count--;
spaces++;
break;
}
switch (toupper(c)) {
case '-':
sig_negative = 1;
case '+':
c = fetch();
sign_detected = 1;
break;
case 'I':
c = fetch();
scan_state = infin_state;
break;
case 'N':
c = fetch();
scan_state = nan_state;
break;
default:
scan_state = sig_start;
break;
}
break;
case infin_state: {
int i = 1;
char model[] = "INFINITY";
while ((i < 8) && (toupper(c) == model[i])) {
i++;
c = fetch();
}
if ((i == 3) || (i == 8)) {
if (sig_negative) {
result = (float)-HUGE_VALF;
} else {
result = HUGE_VALF;
}
*chars_scanned = spaces + i + sign_detected;
return result;
} else {
scan_state = failure;
}
break;
}
case nan_state: {
int i = 1, j = 0;
char model[] = "NAN(";
char nan_arg[32] = "";
while ((i < 4) && (toupper(c) == model[i])) {
i++;
c = fetch();
}
if ((i == 3) || (i == 4)) {
if (i == 4) {
while ((j < 32) && (isdigit(c) || isalpha(c) || (c == radix_marker))) {
nan_arg[j++] = (char)c;
c = fetch();
}
if (c != ')') {
scan_state = failure;
break;
} else {
j++;
}
}
nan_arg[j] = '\0';
if (sig_negative) {
result = -nan(nan_arg);
} else {
result = nan(nan_arg);
}
*chars_scanned = spaces + i + j + sign_detected;
return result;
} else {
scan_state = failure;
}
break;
}
case sig_start:
if (c == radix_marker) {
scan_state = frac_start;
c = fetch();
break;
}
if (!isdigit(c)) {
scan_state = failure;
break;
}
if (c == '0') {
c = fetch();
if (toupper(c) == 'X') {
scan_state = hex_state;
hex_scan_state = hex_start;
} else {
scan_state = leading_sig_zeroes;
}
break;
}
scan_state = int_digit_loop;
break;
case leading_sig_zeroes:
if (c == '0') {
c = fetch();
break;
}
scan_state = int_digit_loop;
break;
case int_digit_loop:
if (!isdigit(c)) {
if (c == radix_marker) {
scan_state = frac_digit_loop;
c = fetch();
} else {
scan_state = sig_end;
}
break;
}
if (d.sig.length < 20) {
d.sig.text[d.sig.length++] = (unsigned char)c;
} else {
exp_adjust++;
}
c = fetch();
break;
case frac_start:
if (!isdigit(c)) {
scan_state = failure;
break;
}
scan_state = frac_digit_loop;
break;
case frac_digit_loop:
if (!isdigit(c)) {
scan_state = sig_end;
break;
}
if (d.sig.length < 20) {
if (c != '0' || d.sig.length) {
d.sig.text[d.sig.length++] = (unsigned char)c;
}
exp_adjust--;
}
c = fetch();
break;
case sig_end:
if (toupper(c) == 'E') {
scan_state = exp_start;
c = fetch();
break;
}
scan_state = finished;
break;
case exp_start:
if (c == '+') {
c = fetch();
} else if (c == '-') {
c = fetch();
exp_negative = 1;
}
scan_state = leading_exp_digit;
break;
case leading_exp_digit:
if (!isdigit(c)) {
scan_state = failure;
break;
}
if (c == '0') {
scan_state = leading_exp_zeroes;
c = fetch();
break;
}
scan_state = exp_digit_loop;
break;
case leading_exp_zeroes:
if (c == '0') {
c = fetch();
break;
}
scan_state = exp_digit_loop;
break;
case exp_digit_loop:
if (!isdigit(c)) {
scan_state = finished;
break;
}
exp_value = exp_value * 10 + (c - '0');
if (exp_value > DBL_MAX_10_EXP) {
*overflow = 1;
}
c = fetch();
break;
case hex_state: {
switch (hex_scan_state) {
case hex_start:
memset(mantissa, 0, sizeof(mantissa));
chptr = mantissa;
mantissa_digits = (53 + 3) / 4;
intdigits = 0;
NibbleIndex = 0;
hex_scan_state = hex_leading_sig_zeroes;
c = fetch();
break;
case hex_leading_sig_zeroes:
if (c == '0') {
c = fetch();
break;
}
hex_scan_state = hex_int_digit_loop;
break;
case hex_int_digit_loop:
if (!isxdigit(c)) {
if (c == radix_marker) {
hex_scan_state = hex_frac_digit_loop;
c = fetch();
}
else {
hex_scan_state = hex_sig_end;
}
break;
}
if (intdigits < mantissa_digits) {
intdigits++;
uch = *(chptr + NibbleIndex / 2);
ui = toupper(c);
if (ui >= 'A') {
ui = ui - 'A' + 10;
} else {
ui -= '0';
}
uch1 = (unsigned char)ui;
if ((NibbleIndex % 2) != 0) {
uch |= uch1;
} else {
uch |= (unsigned char)(uch1 << 4);
}
*(chptr + NibbleIndex++ / 2) = uch;
c = fetch();
}
else {
c = fetch();
}
break;
case hex_frac_digit_loop:
if (!isxdigit(c)) {
hex_scan_state = hex_sig_end;
break;
}
if (intdigits < mantissa_digits) {
uch = *(chptr + NibbleIndex / 2);
ui = toupper(c);
if (ui >= 'A') {
ui = ui - 'A' + 10;
} else {
ui -= '0';
}
uch1 = (unsigned char)ui;
if ((NibbleIndex % 2) != 0) {
uch |= uch1;
} else {
uch |= (unsigned char)(uch1 << 4);
}
*(chptr + NibbleIndex++ / 2) = uch;
c = fetch();
} else {
c = fetch();
}
break;
case hex_sig_end:
if (toupper(c) == 'P') {
hex_scan_state = hex_exp_start;
exp_digits++;
c = fetch();
} else {
scan_state = finished;
}
break;
case hex_exp_start:
exp_digits++;
if (c == '-') {
expsign = 1;
} else if (c != '+') {
c = unfetch(c);
count--;
exp_digits--;
}
hex_scan_state = hex_leading_exp_digit;
c = fetch();
break;
case hex_leading_exp_digit:
if (!isdigit(c)) {
scan_state = failure;
break;
}
if (c == '0') {
exp_digits++;
hex_scan_state = hex_leading_exp_zeroes;
c = fetch();
break;
}
hex_scan_state = hex_exp_digit_loop;
break;
case hex_leading_exp_zeroes:
if (c == '0') {
c = fetch();
break;
}
hex_scan_state = hex_exp_digit_loop;
break;
case hex_exp_digit_loop:
if (!isdigit(c)) {
scan_state = finished;
break;
}
exponent = exponent * 10 + (c - '0');
if (exp_value > SHRT_MAX) {
*overflow = 1;
}
exp_digits++;
c = fetch();
break;
}
} break;
}
}
if (scan_state != 32768 ? !success(scan_state) : !hex_success(count, hex_scan_state)) {
count = 0;
*chars_scanned = 0;
} else {
count--;
*chars_scanned = count + spaces;
}
unfetch(c);
if (hex_scan_state == not_hex) {
if (exp_negative) {
exp_value = -exp_value;
}
{
int n = d.sig.length;
unsigned char* p = &d.sig.text[n];
while (n-- && *--p == '0') {
exp_adjust++;
}
d.sig.length = (unsigned char)(n + 1);
if (d.sig.length == 0) {
d.sig.text[d.sig.length++] = '0';
}
}
if (exp_value < DBL_MIN_10_EXP || exp_value > DBL_MAX_10_EXP) {
if (!*overflow && d.sig.text[0] == '0' && d.sig.text[1] == 0) {
return 0.0;
}
*overflow = 1;
}
exp_value += exp_adjust;
if (*overflow) {
if (exp_negative) {
return 0.0;
} else {
return sig_negative ? -HUGE_VAL : HUGE_VAL;
}
}
d.exp = (short)exp_value;
result = __dec2num(&d);
if (result != 0.0 && result < LDBL_MIN) {
*overflow = 1;
} else if (result > LDBL_MAX) {
*overflow = 1;
result = HUGE_VAL;
}
if (sig_negative && success(scan_state)) {
result = -result;
}
return result;
} else {
unsigned mantissa_bit, dbl_bit;
unsigned one_bit;
long double dbl_bits_storage;
unsigned char* dbl_bits = (unsigned char*)&dbl_bits_storage;
if (expsign) {
exponent = -exponent;
}
exponent += intdigits * 4;
one_bit = 0;
while (one_bit < 4 && !(mantissa[0] & (0x80 >> one_bit))) {
one_bit++;
exponent--;
}
exponent--;
if (TARGET_FLOAT_IMPLICIT_J_BIT) {
one_bit++;
}
if (one_bit) {
unsigned char carry = 0;
for (chptr = mantissa + sizeof(mantissa) - 1; chptr >= mantissa; chptr--) {
unsigned char a = *chptr;
*chptr = (unsigned char)((a << one_bit) | carry);
carry = (unsigned char)(a >> (8 - one_bit));
}
}
memset(dbl_bits, 0, sizeof(dbl_bits_storage));
dbl_bit = (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS);
for (mantissa_bit = 0; mantissa_bit < TARGET_FLOAT_MANT_BITS; mantissa_bit += 8) {
unsigned char ui = mantissa[mantissa_bit >> 3];
int halfbits;
if (mantissa_bit + 8 > TARGET_FLOAT_MANT_BITS) {
ui &= 0xff << (TARGET_FLOAT_MANT_BITS - mantissa_bit);
}
halfbits = (dbl_bit & 7);
dbl_bits[dbl_bit >> 3] |= (unsigned char)(ui >> halfbits);
dbl_bit += 8;
dbl_bits[dbl_bit >> 3] |= (unsigned char)(ui << (8 - halfbits));
}
exponent += (TARGET_FLOAT_MAX_EXP - 1) + exp_value;
if ((exponent & ~(TARGET_FLOAT_MAX_EXP * 2 - 1))) {
*overflow = 1;
return 0.0;
}
exponent <<= 32 - TARGET_FLOAT_EXP_BITS;
dbl_bits[0] |= exponent >> 25;
if (TARGET_FLOAT_EXP_BITS > 7) {
dbl_bits[1] |= exponent >> 17;
}
if (TARGET_FLOAT_EXP_BITS > 15) {
dbl_bits[2] |= exponent >> 9;
}
if (TARGET_FLOAT_EXP_BITS > 23) {
dbl_bits[3] |= exponent >> 1;
}
if (sig_negative) {
dbl_bits[0] |= 0x80;
}
result = *(long double*)dbl_bits;
return result;
}
}
double strtod(const char* str, char** end) {
double value, abs_value;
int count, overflow;
__InStrCtrl isc;
isc.NextChar = (char *)str;
isc.NullCharDetected = 0;
value = __strtold(INT_MAX, &__StringRead, (void *)&isc, &count, &overflow);
if (end)
*end = (char*)str + count;
abs_value = fabs(value);
if (overflow)
errno = ERANGE;
return value;
}
double atof(const char* str) {
return strtod(str, NULL);
}
@@ -150,6 +150,138 @@ unsigned long __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int
return value;
}
unsigned long long __strtoull(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg,
int* chars_scanned, int* negative, int* overflow) {
int scan_state = start;
int count = 0;
int spaces = 0;
unsigned long long value = 0;
unsigned long long value_max = 0;
unsigned long long ullmax = ULLONG_MAX;
int c;
*negative = *overflow = 0;
if (base < 0 || base == 1 || base > 36 || max_width < 1) {
scan_state = failure;
} else {
c = fetch();
}
if (base != 0) {
value_max = ullmax / base;
}
while (count <= max_width && c != -1 && !final_state(scan_state)) {
switch (scan_state) {
case start:
if (isspace(c)) {
c = fetch();
count--;
spaces++;
break;
}
if (c == '+') {
c = fetch();
} else if (c == '-') {
c = fetch();
*negative = 1;
}
scan_state = check_for_zero;
break;
case check_for_zero:
if (base == 0 || base == 16) {
if (c == '0') {
scan_state = leading_zero;
c = fetch();
break;
}
}
scan_state = need_digit;
break;
case leading_zero:
if (c == 'X' || c == 'x') {
base = 16;
scan_state = need_digit;
c = fetch();
break;
}
if (base == 0) {
base = 8;
}
scan_state = digit_loop;
break;
case need_digit:
case digit_loop:
if (base == 0) {
base = 10;
}
if (!value_max) {
value_max = ullmax / base;
}
if (isdigit(c)) {
if ((c -= '0') >= base) {
if (scan_state == digit_loop) {
scan_state = finished;
} else {
scan_state = failure;
}
c += '0';
break;
}
} else if (!isalpha(c) || (toupper(c) - 'A' + 10) >= base) {
if (scan_state == digit_loop) {
scan_state = finished;
} else {
scan_state = failure;
}
break;
} else {
c = toupper(c) - 'A' + 10;
}
if (value > value_max) {
*overflow = 1;
}
value *= base;
if (c > (ullmax - value)) {
*overflow = 1;
}
value += c;
scan_state = digit_loop;
c = fetch();
break;
}
}
if (!success(scan_state)) {
count = 0;
value = 0;
*chars_scanned = 0;
} else {
count--;
*chars_scanned = count + spaces;
}
unfetch(c);
return value;
}
unsigned long strtoul(const char* str, char** end, int base) {
unsigned long value;
int count, negative, overflow;
@@ -198,3 +330,7 @@ long strtol(const char* str, char** end, int base) {
return svalue;
}
int atoi(const char* str) {
return strtol(str, NULL, 10);
}
@@ -1,21 +1,32 @@
#include "wchar_io.h"
int fwide(FILE* file, int mode) {
if (file == NULL || file->file_mode.file_kind == __closed_file) {
int __fwide(FILE* stream, int mode) {
return fwide(stream, mode);
}
int fwide(FILE* stream, int mode) {
int orientation;
int result;
if (stream == NULL || stream->file_mode.file_kind == __closed_file)
return 0;
orientation = stream->file_mode.file_orientation;
switch (orientation) {
case __unoriented:
if (mode > 0)
stream->file_mode.file_orientation = __wide_oriented;
else if (mode < 0)
stream->file_mode.file_orientation = __char_oriented;
result = mode;
break;
case __wide_oriented:
result = 1;
break;
case __char_oriented:
result = -1;
break;
}
switch (file->file_mode.file_orientation) {
case UNORIENTED:
if (mode > 0) {
file->file_mode.file_orientation = WIDE_ORIENTED;
} else if (mode < 0) {
file->file_mode.file_orientation = CHAR_ORIENTED;
}
return mode;
case WIDE_ORIENTED:
return 1;
case CHAR_ORIENTED:
return -1;
}
return result;
}
@@ -0,0 +1,166 @@
#include "ctype.h"
const unsigned short __wctype_mapC[256] = {
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_blank | ctype_cntrl | ctype_space,
ctype_cntrl | ctype_space,
ctype_cntrl | ctype_space,
ctype_cntrl | ctype_space,
ctype_cntrl | ctype_space,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_cntrl,
ctype_blank | ctype_print | ctype_space,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_digit | ctype_graph | ctype_print | ctype_xdigit,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_alpha | ctype_graph | ctype_print | ctype_upper | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_upper | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_upper | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_upper | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_upper | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_upper | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_alpha | ctype_graph | ctype_print | ctype_upper,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_alpha | ctype_graph | ctype_print | ctype_lower | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_lower | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_lower | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_lower | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_lower | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_lower | ctype_xdigit,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_alpha | ctype_graph | ctype_print | ctype_lower,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_graph | ctype_print | ctype_punct,
ctype_cntrl,
};
const wchar_t __wlower_mapC[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, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E,
0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 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,
};
const wchar_t __wupper_mapC[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, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B,
0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E,
0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 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,
};
@@ -0,0 +1,44 @@
#include "wstring.h"
size_t wcslen(const wchar_t* str) {
size_t len = -1;
wchar_t* p = (wchar_t*)str - 1;
do {
len++;
} while (*++p);
return len;
}
wchar_t* wcsncpy(wchar_t* dest, const wchar_t* src, size_t num) {
const wchar_t* p = (const wchar_t*)src - 1;
wchar_t* q = (wchar_t*)dest - 1;
wchar_t zero = 0;
num++;
while (--num) {
if (!(*++q = *++p)) {
while (--num) {
*++q = 0;
}
break;
}
}
return dest;
}
int wcscmp(const wchar_t* str1, const wchar_t* str2) {
const wchar_t* p1 = (wchar_t*)str1 - 1;
const wchar_t* p2 = (wchar_t*)str2 - 1;
wchar_t c1, c2;
while ((c1 = *++p1) == (c2 = *++p2))
if (!c1)
return 0;
return c1 - c2;
}
@@ -72,6 +72,11 @@ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
if(hx>0) return 0.0; /* acos(1) = 0 */
else return pi+2.0*pio2_lo; /* acos(-1)= pi */
}
#if PLATFORM_SHIELD
errno = EDOM;
#endif
return NAN; /* acos(|x|>1) is NaN */
}
if(ix<0x3fe00000) { /* |x| < 0.5 */
@@ -78,6 +78,11 @@ double __ieee754_asin(x) double x;
if (((ix - 0x3ff00000) | __LO(x)) == 0)
/* asin(1)=+-pi/2 with inexact */
return x * pio2_hi + x * pio2_lo;
#if PLATFORM_SHIELD
errno = EDOM;
#endif
return NAN; /* asin(|x|>1) is NaN */
} else if (ix < 0x3fe00000) { /* |x|<0.5 */
if (ix < 0x3e400000) { /* if |x| < 2**-27 */
@@ -37,6 +37,9 @@ double __ieee754_fmod(x, y) double x, y;
#endif
{
int n, hx, hy, hz, ix, iy, sx, i;
#if !PLATFORM_GCN
int diff;
#endif
unsigned lx, ly, lz;
hx = __HI(x); /* high word of x */
@@ -110,9 +113,19 @@ double __ieee754_fmod(x, y) double x, y;
/* fix point fmod */
n = ix - iy;
#if !PLATFORM_GCN
diff = n + 2;
#endif
while (n--) {
hz = hx - hy;
lz = lx - ly;
#if PLATFORM_SHIELD
if (!hz)
if((lx >> diff) == (ly >> diff))
return Zero[(unsigned)sx>>31];
#endif
if (lx < ly)
hz -= 1;
if (hz < 0) {
@@ -127,6 +140,12 @@ double __ieee754_fmod(x, y) double x, y;
}
hz = hx - hy;
lz = lx - ly;
#if PLATFORM_SHIELD
if (!hz)
if((lx >> diff) == (ly >> diff))
return Zero[(unsigned)sx>>31];
#endif
if (lx < ly)
hz -= 1;
if (hz >= 0) {
@@ -163,4 +182,4 @@ double __ieee754_fmod(x, y) double x, y;
x *= one; /* create necessary signal */
}
return x; /* exact output */
}
}
@@ -0,0 +1,161 @@
/* @(#)e_log.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.
* ====================================================
*/
/* __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;
int k, hx, i, j;
unsigned lx;
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) {
errno = EDOM;
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);
}
}
}
@@ -0,0 +1,99 @@
/* @(#)e_log10.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.
* ====================================================
*/
/* __ieee754_log10(x)
* Return the base 10 logarithm of x
*
* Method :
* Let log10_2hi = leading 40 bits of log10(2) and
* log10_2lo = log10(2) - log10_2hi,
* ivln10 = 1/log(10) rounded.
* Then
* n = ilogb(x),
* if(n<0) n = n+1;
* x = scalbn(x,-n);
* log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
*
* Note 1:
* To guarantee log10(10**n)=n, where 10**n is normal, the rounding
* mode must set to Round-to-Nearest.
* Note 2:
* [1/log(10)] rounded to 53 bits has error .198 ulps;
* log10 is monotonic at all binary break points.
*
* Special cases:
* log10(x) is NaN with signal if x < 0;
* log10(+INF) is +INF with no signal; log10(0) is -INF with signal;
* log10(NaN) is that NaN with no signal;
* log10(10**N) = N for N=0,1,...,22.
*
* 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
two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
static double zero = 0.0;
#ifdef __STDC__
double __ieee754_log10(double x)
#else
double __ieee754_log10(x)
double x;
#endif
{
double y, z;
int i, k, hx;
unsigned lx;
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) {
errno = EDOM;
return -two54 / zero;
} /* log(+-0)=-inf */
if (hx < 0) {
errno = EDOM;
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;
i = ((unsigned)k & 0x80000000) >> 31;
hx = (hx & 0x000fffff) | ((0x3ff - i) << 20);
y = (double)(k + i);
__HI(x) = hx;
z = y * log10_2lo + ivln10 * __ieee754_log(x);
return z + y * log10_2hi;
}
@@ -1,59 +1,4 @@
//========================================================================
//
// e_pow.c
//
// Part of the standard mathematical function library
//
//========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jlarmour
// Contributors:
// Date: 2001-07-20
// Purpose:
// Description:
// Usage:
//
//####DESCRIPTIONEND####
//
//========================================================================
// CONFIGURATION
/* @(#)e_pow.c 5.1 93/09/24 */
/* @(#)e_pow.c 1.2 95/01/04 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
@@ -110,298 +55,322 @@
* to produce the hexadecimal values shown.
*/
#include "types.h"
#include "errno.h"
#include "cmath.h"
#ifndef _DOUBLE_IS_32BITS
#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 */
huge = 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*/
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;
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;
double qqq; // necessary temp
int i0, i1, i, j, k, yisint, n;
int hx, hy, ix, iy;
u32 lx, ly;
double z, ax, z_h, z_l, p_h, p_l;
double y1, t1, t2, r, s, t, u, v, w;
int i, j, k, yisint, n;
int hx, hy, ix, iy;
unsigned lx, ly;
i0 = ((*(int*)&one) >> 29) ^ 1;
i1 = 1 - i0;
hx = __HI(x);
lx = __LO(x);
hy = __HI(y);
ly = __LO(y);
ix = hx & 0x7fffffff;
iy = hy & 0x7fffffff;
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;
/* 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;
/* +-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);
}
}
}
/* 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);
}
}
/* special value of y */
if (ly == 0) {
if (iy == 0x7ff00000) {
ax = __fabs(x);
qqq = ax; /*x is +-0,+-inf,+-1*/
/* special value of x */
if (lx == 0) {
if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) {
z = qqq; /*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;
}
}
/* 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);
}
}
}
/* (x<0)**(non-int) is NaN */
/* CYGNUS LOCAL: This used to be
if((((hx>>31)+1)|yisint)==0) return (x-x)/(x-x);
but ANSI C says a right shift of a signed negative quantity is
implementation defined. */
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;
}
}
if (((((int)hx >> 31) + 1) | yisint) == 0) {
errno = 33;
return (double)NAN;
};
/* (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 huge */
if (iy > 0x41e00000) { /* if |y| > 2**31 */
if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */
if (ix <= 0x3fefffff)
return (hy < 0) ? huge * huge : tiny * tiny;
if (ix >= 0x3ff00000)
return (hy > 0) ? huge * huge : tiny * tiny;
}
/* over/underflow if x is not close to one */
if (ix < 0x3fefffff)
return (hy < 0) ? huge * huge : tiny * tiny;
if (ix > 0x3ff00000)
return (hy > 0) ? huge * huge : 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;
/* |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);
}
/* 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 (((((int)hx >> 31) + 1) | (yisint - 1)) == 0)
s = -one; /* (-ve)**(odd int) */
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 * huge * huge; /* overflow */
else {
if (p_l + ovt > z - p_h)
return s * huge * huge; /* 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 = ldexp(z, n); /* subnormal output */
else
__HI(z) += (n << 20);
return s * z;
/* 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) {
#if PLATFORM_GCN
z = ldexp(z, n); /* subnormal output */
#else
z = scalbn(z, n); /* subnormal output */
#endif
} else {
__HI(z) += (n << 20);
}
return s * z;
}
#endif /* defined(_DOUBLE_IS_32BITS) */
// EOF e_pow.c
@@ -1,3 +1,4 @@
/* @(#)e_rem_pio2.c 1.4 95/01/18 */
/*
* ====================================================
@@ -17,7 +18,7 @@
* use __kernel_rem_pio2()
*/
#include "cmath.h"
#include "fdlibm.h"
/*
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
@@ -27,12 +28,12 @@ static const int two_over_pi[] = {
#else
static int 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,
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__
@@ -40,9 +41,10 @@ static const int npio2_hw[] = {
#else
static int 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,
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,
};
/*
@@ -60,120 +62,128 @@ 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 */
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_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
#ifdef __STDC__
int __ieee754_rem_pio2(double x, double* y)
#else
int __ieee754_rem_pio2(x, y) double x, y[];
int __ieee754_rem_pio2(x, y)
double x, y[];
#endif
{
double z, w, t, r, fn;
double tx[3];
int e0, i, j, nx, n, ix, hx;
double z, w, t, r, fn;
double tx[3];
int e0, i, j, nx, n, ix, hx;
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 = (int)(t * invpio2 + half);
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;
r = t - fn * pio2_2;
w = fn * pio2_2t - ((t - r) - fn * pio2_2);
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)((int)(z));
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;
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 = (int)(t * invpio2 + half);
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;
#if PLATFORM_WII || PLATFORM_SHIELD
w = fn * pio2_2;
r = t - w;
w = fn * pio2_2t - ((t - r) - w);
#else
r = t - fn * pio2_2;
w = fn * pio2_2t - ((t - r) - fn * pio2_2);
#endif
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)((int)(z));
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;
}
@@ -349,4 +349,4 @@ recompute:
}
}
return n & 7;
}
}
@@ -11,7 +11,15 @@
* ====================================================
*/
#include "global.h"
#if PLATFORM_GCN
#include "cmath.h" /* for isfinite macro */
#else
#include <fdlibm.h>
#define isfinite(x) ((__fpclassifyd(x) > 2))
#endif
static const double
two54
@@ -0,0 +1,28 @@
/* @(#)w_log10.c 1.2 95/01/04 */
/* $Id: w_log10.c,v 1.3 2004/02/26 17:03:30 ceciliar Exp $ */
/*
* ====================================================
* 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 log10(X)
*/
#include "fdlibm.h"
#ifdef __STDC__
double log10(double x) /* wrapper log10 */
#else
double log10(x) /* wrapper log10 */
double x;
#endif
{
return __ieee754_log10(x);
}
@@ -1,6 +1,8 @@
#ifndef FDLIBM_H
#define FDLIBM_H
#include <errno.h>
/* @(#)fdlibm.h 1.5 04/04/22 */
/*
* ====================================================
@@ -225,4 +227,4 @@ extern int __kernel_rem_pio2 __P((double*, double*, int, int, int, const int*));
};
#endif
#endif /* FDLIBM_H */
#endif /* FDLIBM_H */
@@ -1,7 +1,7 @@
#include "ansi_fp.h"
#include "ansi_fp.h"
#include "climits.h"
#include "float.h"
#include "cmath.h"
static int __count_trailing_zerol(unsigned long x) {
int result = 0;
@@ -101,6 +101,7 @@ static void __rounddec(decimal* d, int digits) {
void __ull2dec(decimal* result, unsigned long long val) {
result->sign = 0;
#if PLATFORM_GCN
if (val == 0) {
result->exp = 0;
result->sig.length = 1;
@@ -112,6 +113,7 @@ void __ull2dec(decimal* result, unsigned long long val) {
val = -val;
result->sign = 1;
}
#endif
result->sig.length = 0;
@@ -345,6 +347,7 @@ int __equals_dec(const decimal* x, const decimal* y) {
}
}
#if PLATFORM_GCN
if (l == x->sig.length) {
for (; i < y->sig.length; ++i) {
if (y->sig.text[i] != 0) {
@@ -358,6 +361,17 @@ int __equals_dec(const decimal* x, const decimal* y) {
}
}
}
#else
if (l == x->sig.length) {
x = y;
}
for (; i < x->sig.length; ++i) {
if (x->sig.text[i] != 0) {
return 0;
}
}
#endif
return 1;
}
@@ -563,7 +577,157 @@ void __num2dec(const decform* form, double x, decimal* d) {
d->exp -= d->sig.length - 1;
for (i = 0; i < d->sig.length; i++) {
for (i = 0; i < d->sig.length; ++i) {
d->sig.text[i] += '0';
}
}
#if !PLATFORM_GCN
double __dec2num(const decimal* d) {
if (d->sig.length <= 0) {
return copysign(0.0, d->sign == 0 ? 1.0 : -1.0);
}
switch (d->sig.text[0]) {
case '0':
return copysign(0.0, d->sign == 0 ? 1.0 : -1.0);
case 'I':
return copysign((double)HUGE_VALF, d->sign == 0 ? 1.0 : -1.0);
case 'N': {
double result;
unsigned long long* ll = (unsigned long long*)&result;
*ll = 0x7FF0000000000000;
if (d->sign)
*ll |= 0x8000000000000000;
*ll |= 0x8000000000000;
return result;
}
}
{
static double pow_10[8] = {1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8};
decimal dec = *d;
unsigned char* i = dec.sig.text;
unsigned char* e = i + dec.sig.length;
double first_guess;
int exponent;
for (; i < e; ++i)
*i -= '0';
dec.exp += dec.sig.length - 1;
exponent = dec.exp;
{
decimal max;
__str2dec(&max, "179769313486231580793728714053034151", 308);
if (__less_dec(&max, &dec)) {
return copysign((double)HUGE_VALF, d->sign == 0 ? 1.0 : -1.0);
}
}
i = dec.sig.text;
first_guess = *i++;
while (i < e) {
unsigned long ival = 0;
int j;
double temp1, temp2;
int ndig = (int)(e - i) % 8;
if (ndig == 0)
ndig = 8;
for (j = 0; j < ndig; ++j, ++i) {
ival = ival * 10 + *i;
}
temp1 = first_guess * pow_10[ndig - 1];
temp2 = temp1 + ival;
if (ival != 0 && temp1 == temp2)
break;
first_guess = temp2;
exponent -= ndig;
}
if (exponent < 0) {
first_guess /= pow(5.0, -exponent);
} else {
first_guess *= pow(5.0, exponent);
}
first_guess = ldexp(first_guess, exponent);
if (fpclassify(first_guess) == 2) {
first_guess = LDBL_MAX;
}
{
decimal feedback1, feedback2, difflow, diffhigh;
double next_guess;
unsigned long long* ull = (unsigned long long*)&next_guess;
int guessed_low = 0;
__num2dec_internal(&feedback1, first_guess);
if (__equals_dec(&feedback1, &dec)) {
goto done;
}
if (__less_dec(&feedback1, &dec)) {
guessed_low = 1;
}
next_guess = first_guess;
while (1) {
if (guessed_low) {
++*ull;
if (fpclassify(next_guess) == 2) {
goto done;
}
} else {
--*ull;
}
__num2dec_internal(&feedback2, next_guess);
if (guessed_low && !__less_dec(&feedback2, &dec)) {
break;
} else if (!guessed_low && !__less_dec(&dec, &feedback2)) {
difflow = feedback1;
feedback1 = feedback2;
feedback2 = difflow;
{
double temp = first_guess;
first_guess = next_guess;
next_guess = temp;
}
break;
}
feedback1 = feedback2;
first_guess = next_guess;
}
__minus_dec(&difflow, &dec, &feedback1);
__minus_dec(&diffhigh, &feedback2, &dec);
if (__equals_dec(&difflow, &diffhigh)) {
if (*(unsigned long long*)&first_guess & 1) {
first_guess = next_guess;
}
} else if (!__less_dec(&difflow, &diffhigh)) {
first_guess = next_guess;
}
}
done:
if (dec.sign) {
first_guess = -first_guess;
}
return first_guess;
}
}
#endif
@@ -0,0 +1,13 @@
#include <cmath.h>
double scalbn(double x, int n) {
double mant;
int exp;
double result;
mant = frexp(x, &exp);
exp += n;
result = ldexp(mant, exp);
return result;
}
@@ -14,6 +14,8 @@
#endif
#endif
double nan(const char* arg) {}
DECL_WEAK float acosf(float x) {
return acos(x);
}