/programs/develop/libraries/newlib/Makefile |
---|
0,0 → 1,386 |
CC = gcc |
CFLAGS = -c -O2 -fomit-frame-pointer |
LDFLAGS = -nostdlib -shared -s -T libcdll.lds --out-implib libcimp.a --image-base 0 |
LIBC_TOPDIR = . |
LIBC_INCLUDES = $(LIBC_TOPDIR)/include |
NAME:= libc |
DEFINES:= |
INCLUDES:= -I $(LIBC_INCLUDES) |
AMZ_SRCS:= \ |
crt/crt_amz.S \ |
crt/chkstk.S \ |
crt/exit.S \ |
crt/pseudo-reloc.S \ |
crt/setjmp.S |
STATIC_SRCS:= \ |
crt/start.S \ |
crt/crt1.c \ |
crt/chkstk.S \ |
crt/exit.S \ |
crt/setjmp.S |
DLL_SRCS:= \ |
crt/crtdll.c \ |
crt/chkstk.S \ |
crt/exit.S \ |
crt/setjmp.S \ |
pe/loader.c |
CORE_SRCS:= \ |
argz/buf_findstr.c \ |
argz/envz_get.c \ |
crt/emutls.c \ |
crt/thread.S \ |
crt/tls.S \ |
crt/assert.c \ |
crt/cpu_features.c \ |
ctype/ctype_.c \ |
ctype/isascii.c \ |
ctype/isblank.c \ |
ctype/isalnum.c \ |
ctype/isalpha.c \ |
ctype/iscntrl.c \ |
ctype/isdigit.c \ |
ctype/islower.c \ |
ctype/isupper.c \ |
ctype/isprint.c \ |
ctype/ispunct.c \ |
ctype/isspace.c \ |
ctype/iswctype.c \ |
ctype/iswalnum.c \ |
ctype/iswalpha.c \ |
ctype/iswblank.c \ |
ctype/iswcntrl.c \ |
ctype/iswdigit.c \ |
ctype/iswgraph.c \ |
ctype/iswlower.c \ |
ctype/iswprint.c \ |
ctype/iswpunct.c \ |
ctype/iswspace.c \ |
ctype/iswupper.c \ |
ctype/iswxdigit.c \ |
ctype/isxdigit.c \ |
ctype/toascii.c \ |
ctype/tolower.c \ |
ctype/toupper.c \ |
ctype/towctrans.c \ |
ctype/towlower.c \ |
ctype/towupper.c \ |
ctype/wctrans.c \ |
ctype/wctype.c \ |
errno/errno.c \ |
locale/locale.c \ |
locale/lctype.c \ |
reent/impure.c \ |
reent/getreent.c \ |
reent/gettimeofdayr.c \ |
reent/hdlman.c \ |
reent/isattyr.c \ |
reent/openr.c \ |
reent/closer.c \ |
reent/readr.c \ |
reent/lseekr.c \ |
reent/fstatr.c \ |
reent/writer.c \ |
search/qsort.c \ |
search/bsearch.c \ |
signal/signal.c \ |
sys/create.c \ |
sys/delete.c \ |
sys/finfo.c \ |
sys/read.c \ |
sys/write.c \ |
sys/fsize.c \ |
sys/fload.c \ |
time/asctime.c \ |
time/asctime_r.c \ |
time/clock.c \ |
time/ctime.c \ |
time/ctime_r.c \ |
time/difftime.c \ |
time/gettzinfo.c \ |
time/gmtime.c \ |
time/gmtime_r.c \ |
time/mktime.c \ |
time/mktm_r.c \ |
time/lcltime.c \ |
time/lcltime_r.c \ |
time/strftime.c \ |
time/time.c \ |
time/tzlock.c \ |
time/tzvars.c \ |
unpack/unpacker.asm |
STDLIB_SRCS= \ |
__atexit.c \ |
__call_atexit.c \ |
abort.c \ |
abs.c \ |
atof.c \ |
atoi.c \ |
div.c \ |
dtoa.c \ |
dtoastub.c \ |
exit.c \ |
gdtoa-gethex.c \ |
gdtoa-hexnan.c \ |
getenv.c \ |
mprec.c \ |
mbtowc.c \ |
mbtowc_r.c \ |
mbrtowc.c \ |
mlock.c \ |
calloc.c \ |
malloc.c \ |
mallocr.c \ |
rand.c \ |
rand_r.c \ |
rand48.c \ |
realloc.c \ |
seed48.c \ |
srand48.c \ |
strtod.c \ |
strtol.c \ |
strtold.c \ |
strtoll.c \ |
strtoll_r.c \ |
strtoul.c \ |
strtoull.c \ |
strtoull_r.c \ |
system.c \ |
wcrtomb.c \ |
wctomb_r.c |
STRING_SRCS= memcpy.c \ |
memcmp.c \ |
memmove.c \ |
memset.c \ |
memchr.c \ |
strcat.c \ |
strchr.c \ |
strcmp.c \ |
strcoll.c \ |
strcasecmp.c \ |
strncasecmp.c \ |
strncat.c \ |
strncmp.c \ |
strncpy.c \ |
strndup.c \ |
strndup_r.c \ |
strnlen.c \ |
strcasestr.c \ |
strdup.c \ |
strdup_r.c \ |
strerror.c \ |
strlen.c \ |
strrchr.c \ |
strpbrk.c \ |
strsep.c \ |
strstr.c \ |
strtok.c \ |
strtok_r.c \ |
strupr.c \ |
strcspn.c \ |
strspn.c \ |
strcpy.c \ |
u_strerr.c |
STDIO_SRCS= \ |
printf.c \ |
putchar.c \ |
fgets.c \ |
fopen.c \ |
fclose.c \ |
fdopen.c \ |
fflush.c \ |
flags.c \ |
findfp.c \ |
fiprintf.c \ |
fiscanf.c \ |
fprintf.c \ |
fputc.c \ |
fputs.c \ |
fputwc.c \ |
fread.c \ |
freopen.c \ |
fscanf.c \ |
fseek.c \ |
fseeko.c \ |
ftell.c \ |
ftello.c \ |
fwrite.c \ |
fvwrite.c \ |
fwalk.c \ |
putc.c \ |
puts.c \ |
refill.c \ |
rget.c \ |
remove.c \ |
rename.c \ |
setvbuf.c \ |
stdio.c \ |
tmpfile.c \ |
tmpnam.c \ |
ungetc.c \ |
vscanf.c \ |
vsprintf.c \ |
vsnprintf.c \ |
vsscanf.c \ |
makebuf.c \ |
wsetup.c \ |
wbuf.c \ |
sccl.c \ |
snprintf.c \ |
sprintf.c \ |
sscanf.c |
MATH_SRCS = acosf.c acosh.c acoshf.c acoshl.c acosl.c asinf.c asinh.c asinhf.c asinhl.c \ |
asinl.c atan2f.c atan2l.c atanf.c atanh.c atanhf.c atanhl.c atanl.c cbrt.c \ |
cbrtf.c cbrtl.c coshf.c coshl.c erfl.c expf.c expl.c expm1.c expm1f.c expm1l.c\ |
fabs.c fabsf.c fabsl.c fdim.c fdimf.c fdiml.c fmal.c fmax.c fmaxf.c fmaxl.c\ |
fmin.c fminf.c fminl.c fmodf.c fmodl.c fp_consts.c fp_constsf.c fp_constsl.c\ |
fpclassify.c fpclassifyf.c fpclassifyl.c frexpf.c fucom.c hypotf.c isnan.c \ |
isnanf.c isnanl.c ldexp.c ldexpf.c ldexpl.c lgamma.c lgammaf.c lgammal.c \ |
llrint.c llrintf.c llrintl.c logb.c logbf.c logbl.c lrint.c lrintf.c lrintl.c\ |
lround_generic.c modff.c modfl.c nextafterf.c nextafterl.c nexttoward.c \ |
nexttowardf.c pow.c powf.c powi.c powif.c powil.c powl.c rint.c rintf.c \ |
rintl.c round_generic.c s_erf.c sf_erf.c signbit.c signbitf.c signbitl.c \ |
sinhf.c sinhl.c sqrtf.c sqrtl.c tanhf.c tanhl.c tgamma.c tgammaf.c tgammal.c \ |
trunc.c truncf.c truncl.c e_sqrt.c e_sinh.c e_cosh.c e_hypot.c s_tanh.c \ |
s_roundf.c s_fpclassify.c s_isnand.c w_hypot.c s_modf.c e_atan2.c w_atan2.c\ |
ceil.S ceilf.S ceill.S copysign.S copysignf.S copysignl.S cos.S cosf.S cosl.S exp.S exp2.S \ |
exp2f.S exp2l.S floor.S floorf.S floorl.S fma.S fmaf.S frexp.S frexpl.S ilogb.S ilogbf.S \ |
ilogbl.S log10.S log10f.S log10l.S log1p.S log1pf.S log1pl.S log2.S log2f.S log2l.S \ |
log.S logf.S logl.S nearbyint.S nearbyintf.S nearbyintl.S remainder.S remainderf.S \ |
remainderl.S remquo.S remquof.S remquol.S scalbn.S scalbnf.S scalbnl.S sin.S \ |
sinf.S sinl.S tan.S tanf.S tanl.S s_expm1.S |
AMZ_OBJS = $(patsubst %.S, %.o, $(AMZ_SRCS)) |
STATIC_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(STATIC_SRCS))) |
DLL_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(DLL_SRCS))) |
CORE_OBJS = $(patsubst %.S, %.o, $(patsubst %.asm, %.obj,\ |
$(patsubst %.c, %.o, $(CORE_SRCS)))) |
STDIO_OBJS = $(patsubst %.c, stdio/%.o,$(STDIO_SRCS)) |
STRING_OBJS = $(patsubst %.S, string/%.o, $(patsubst %.asm, string/%.o,\ |
$(patsubst %.c, string/%.o, $(STRING_SRCS)))) |
STDLIB_OBJS = $(patsubst %.S, stdlib/%.o, $(patsubst %.asm, stdlib/%.o,\ |
$(patsubst %.c, stdlib/%.o, $(STDLIB_SRCS)))) |
MATH_OBJS = $(patsubst %.S, math/%.o, $(patsubst %.asm, math/%.o,\ |
$(patsubst %.c, math/%.o, $(MATH_SRCS)))) |
PRINTF_OBJS= stdio/vfprintf.o \ |
stdio/vfiprintf.o \ |
stdio/svfprintf.o \ |
stdio/svfiprintf.o \ |
stdio/vfscanf.o \ |
stdio/vfiscanf.o \ |
stdio/svscanf.o \ |
stdio/svfiscanf.o |
ifeq ($(findstring static,$(MAKECMDGOALS)),static) |
LIB_SRCS:= $(STATIC_SRCS) |
LIB_OBJS:= $(STATIC_OBJS) |
else |
LIB_SRCS:= $(DLL_SRCS) |
LIB_OBJS:= $(DLL_OBJS) |
endif |
LIB_SRCS+= \ |
$(CORE_SRCS) \ |
$(STDIO_SRCS) \ |
$(STRING_SRCS) \ |
$(STDLIB_SRCS) |
LIB_OBJS+= \ |
$(CORE_OBJS) \ |
$(STRING_OBJS) \ |
$(STDLIB_OBJS) \ |
$(STDIO_OBJS) \ |
$(PRINTF_OBJS) \ |
$(MATH_OBJS) |
shared: $(NAME).dll libamz.a |
$(NAME).dll: $(LIB_OBJS) $(SRC_DEP) Makefile |
ld $(LDFLAGS) -L. -o $@ $(LIB_OBJS) -lgcc |
libamz.a: $(AMZ_OBJS) Makefile |
ar rc libamz.a $(AMZ_OBJS) |
static: $(NAME).a |
$(NAME).a: $(LIB_OBJS) $(SRC_DEP) Makefile |
ar rc $(NAME).a $(LIB_OBJS) |
stdio/vfprintf.o: stdio/vfprintf.c |
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DFLOATING_POINT -c stdio/vfprintf.c -o $@ |
stdio/vfiprintf.o: stdio/vfprintf.c |
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DINTEGER_ONLY -c stdio/vfprintf.c -o $@ |
stdio/svfprintf.o: stdio/vfprintf.c |
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DSTRING_ONLY -c stdio/vfprintf.c -o $@ |
stdio/svfiprintf.o: stdio/vfprintf.c |
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -fshort-enums -DINTEGER_ONLY -DSTRING_ONLY -c stdio/vfprintf.c -o $@ |
stdio/vfscanf.o: stdio/vfscanf.c |
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) stdio/vfscanf.c -o $@ |
stdio/vfiscanf.o: stdio/vfscanf.c |
$(CC) $(CFLAGS) $(DEFINES) -DINTEGER_ONLY $(INCLUDES) stdio/vfscanf.c -o $@ |
stdio/svscanf.o: stdio/vfscanf.c |
$(CC) $(CFLAGS) $(DEFINES) -DSTRING_ONLY $(INCLUDES) stdio/vfscanf.c -o $@ |
stdio/svfiscanf.o: stdio/vfscanf.c |
$(CC) $(CFLAGS) $(DEFINES) -DINTEGER_ONLY -DSTRING_ONLY $(INCLUDES) stdio/vfscanf.c -o $@ |
%.obj : %.asm Makefile |
fasm $< $@ |
%.o : %.c Makefile |
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< |
clean: |
-rm -f */*.o |
/programs/develop/libraries/newlib/argz/buf_findstr.c |
---|
0,0 → 1,44 |
/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. |
* |
* Permission to use, copy, modify, and distribute this software |
* is freely granted, provided that this notice is preserved. |
*/ |
#include <errno.h> |
#include <sys/types.h> |
#include <string.h> |
#include <stdlib.h> |
#include "buf_findstr.h" |
/* Find string str in buffer buf of length buf_len. Point buf to character after string, |
or set it to NULL if end of buffer is reached. Return 1 if found, 0 if not. */ |
int |
_buf_findstr(const char *str, char **buf, size_t *buf_len) |
{ |
int i = 0; |
int j = 0; |
for (i = 0; i < *buf_len; i++) |
{ |
if (str[0] == (*buf)[i]) |
{ |
j = i; |
while (str[j - i] && (str[j - i] == (*buf)[j])) j++; |
if(str[j - i] == '\0') |
{ |
*buf += j; |
*buf_len -= j; |
return 1; |
} |
} |
} |
if (i == *buf_len) |
{ |
*buf += *buf_len; |
*buf_len = 0; |
} |
return 0; |
} |
/programs/develop/libraries/newlib/argz/buf_findstr.h |
---|
0,0 → 1,12 |
/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. |
* |
* Permission to use, copy, modify, and distribute this software |
* is freely granted, provided that this notice is preserved. |
*/ |
#include <sys/types.h> |
/* Find string str in buffer buf of length buf_len. Point buf to |
character after string, or set it to NULL if end of buffer is |
reached. Return 1 if found, 0 if not. */ |
int _buf_findstr(const char *str, char **buf, size_t *buf_len); |
/programs/develop/libraries/newlib/argz/envz_get.c |
---|
0,0 → 1,43 |
/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. |
* |
* Permission to use, copy, modify, and distribute this software |
* is freely granted, provided that this notice is preserved. |
*/ |
#include <errno.h> |
#include <sys/types.h> |
#include <string.h> |
#include <stdlib.h> |
#include <envz.h> |
#include "buf_findstr.h" |
char * |
_DEFUN (envz_get, (envz, envz_len, name), |
const char *envz _AND |
size_t envz_len _AND |
const char *name) |
{ |
char *buf_ptr = (char *)envz; |
size_t buf_len = envz_len; |
while(buf_len) |
{ |
if (_buf_findstr(name, &buf_ptr, &buf_len)) |
{ |
if (*buf_ptr == '=') |
{ |
buf_ptr++; |
return (char *)buf_ptr; |
} |
else |
{ |
if (*buf_ptr == '\0') |
/* NULL entry. */ |
return NULL; |
} |
} |
} |
/* No matching entries found. */ |
return NULL; |
} |
/programs/develop/libraries/newlib/argz |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/newlib/crt/assert.c |
---|
0,0 → 1,74 |
/* |
FUNCTION |
<<assert>>---macro for debugging diagnostics |
INDEX |
assert |
ANSI_SYNOPSIS |
#include <assert.h> |
void assert(int <[expression]>); |
DESCRIPTION |
Use this macro to embed debuggging diagnostic statements in |
your programs. The argument <[expression]> should be an |
expression which evaluates to true (nonzero) when your program |
is working as you intended. |
When <[expression]> evaluates to false (zero), <<assert>> |
calls <<abort>>, after first printing a message showing what |
failed and where: |
. Assertion failed: <[expression]>, file <[filename]>, line <[lineno]>, function: <[func]> |
If the name of the current function is not known (for example, |
when using a C89 compiler that does not understand __func__), |
the function location is omitted. |
The macro is defined to permit you to turn off all uses of |
<<assert>> at compile time by defining <<NDEBUG>> as a |
preprocessor variable. If you do this, the <<assert>> macro |
expands to |
. (void(0)) |
RETURNS |
<<assert>> does not return a value. |
PORTABILITY |
The <<assert>> macro is required by ANSI, as is the behavior |
when <<NDEBUG>> is defined. |
Supporting OS subroutines required (only if enabled): <<close>>, <<fstat>>, |
<<getpid>>, <<isatty>>, <<kill>>, <<lseek>>, <<read>>, <<sbrk>>, <<write>>. |
*/ |
#include <assert.h> |
#include <stdlib.h> |
#include <stdio.h> |
/* func can be NULL, in which case no function information is given. */ |
void |
_DEFUN (__assert_func, (file, line, func, failedexpr), |
const char *file _AND |
int line _AND |
const char *func _AND |
const char *failedexpr) |
{ |
fiprintf(stderr, |
"assertion \"%s\" failed: file \"%s\", line %d%s%s\n", |
failedexpr, file, line, |
func ? ", function: " : "", func ? func : ""); |
abort(); |
/* NOTREACHED */ |
} |
void |
_DEFUN (_assert, (file, line, failedexpr), |
const char *file _AND |
int line _AND |
const char *failedexpr) |
{ |
__assert_func (file, line, NULL, failedexpr); |
/* NOTREACHED */ |
} |
/programs/develop/libraries/newlib/crt/chkstk.S |
---|
4,7 → 4,6 |
.section .text |
.align 4 |
___chkstk: |
__alloca: |
pushl %ecx /* save temp */ |
27,3 → 26,4 |
int3 #trap to debugger |
.ascii "Stack overflow" |
/programs/develop/libraries/newlib/crt/crt1.c |
---|
16,6 → 16,9 |
#include <stdint.h> |
#include <stdlib.h> |
#include <string.h> |
#include <stdio.h> |
#include <sys/kos_io.h> |
#include "cpu_features.h" |
51,8 → 54,6 |
} |
void __main (){}; |
void init_reent(); |
void __attribute__((noreturn)) |
73,11 → 74,26 |
_exit(retval); |
}; |
struct app_hdr |
{ |
char banner[8]; |
int version; |
int start; |
int iend; |
int memsize; |
int stacktop; |
char *cmdline; |
char *path; |
}; |
void __attribute__((noreturn)) |
__crt_startup (void) |
{ |
int nRet; |
struct app_hdr *header; |
init_reent(); |
/* |
89,12 → 105,12 |
__initPOSIXHandles(); |
__appcwdlen = strrchr(&__pgmname, '/') - &__pgmname + 1; |
__appcwdlen = __appcwdlen > 1023 ? 1023 : __appcwdlen; |
strncpy(__appcwd, &__pgmname, __appcwdlen); |
memcpy(__appcwd, &__pgmname, __appcwdlen); |
__appcwd[__appcwdlen] = 0; |
set_cwd(__appcwd); |
arg[0] = &__pgmname; |
if( __cmdline != 0) |
113,6 → 129,7 |
*/ |
// _mingw32_init_fmode (); |
nRet = main (_argc, _argv, NULL); |
/* |
119,7 → 136,7 |
* Perform exit processing for the C library. This means |
* flushing output and calling 'atexit' registered functions. |
*/ |
_exit (nRet); |
exit (nRet); |
} |
/programs/develop/libraries/newlib/crt/crt_amz.S |
---|
0,0 → 1,15 |
.section .text |
.global __start |
.global ___main |
.align 4 |
__start: |
jmp _main |
.align 4 |
___main: |
ret |
/programs/develop/libraries/newlib/crt/crtdll.c |
---|
0,0 → 1,144 |
#include <_ansi.h> |
#include <reent.h> |
#include <stdint.h> |
#include <stdlib.h> |
#include <string.h> |
#include <stdio.h> |
#include <unistd.h> |
#include <setjmp.h> |
#include <sys/kos_io.h> |
struct app_hdr |
{ |
char banner[8]; |
int version; |
int start; |
int iend; |
int memsize; |
int stacktop; |
char *cmdline; |
char *path; |
}; |
int _argc; |
char **_argv; |
void __fastcall init_loader(void *libc_image); |
void* __fastcall create_image(void *raw); |
int __fastcall link_image(void *img_base); |
void* get_entry_point(void *raw); |
int (*entry)(int, char **, char **); |
void init_reent(); |
jmp_buf loader_env; |
void __attribute__((noreturn)) |
__thread_startup (int (*entry)(void*), void *param, |
void *stacklow, void *stackhigh) |
{ |
int retval; |
asm volatile ( "xchgw %bx, %bx"); |
__asm__ __volatile__( // save stack limits |
"movl %0, %%fs:4 \n\t" // use TLS |
"movl %1, %%fs:8 \n\t" |
::"r"(stacklow), "r"(stackhigh)); |
init_reent(); // initialize thread reentry structure |
retval = entry(param); // call user thread function |
_exit(retval); |
}; |
char * __libc_getenv(const char *name) |
{ |
return NULL; |
} |
char __appcwd[1024]; |
int __appcwdlen; |
char* __appenv; |
int __appenv_size; |
void __attribute__((noreturn)) |
crt_startup (void *libc_base, void *obj_base, uint32_t *params) |
{ |
struct app_hdr *header; |
char *arg[2]; |
int len; |
char *p; |
void *my_app; |
int retval = 0; |
// user_free(obj_base); |
init_reent(); |
__initPOSIXHandles(); |
__appenv = load_file("/sys/system.env", &__appenv_size); |
init_loader(libc_base); |
my_app = create_image((void*)(params[0])); |
if( link_image(my_app)==0) |
goto done; |
header = (struct app_hdr*)NULL; |
__appcwdlen = strrchr(header->path, '/') - header->path; |
__appcwdlen = __appcwdlen > 1022 ? 1022 : __appcwdlen; |
memcpy(__appcwd, header->path, __appcwdlen); |
set_cwd(__appcwd); |
#ifdef BRAVE_NEW_WORLD |
len = strlen(header->path); |
p = alloca(len+1); |
memcpy(p, header->path, len); |
p[len]=0; |
arg[0] = p; |
#else |
arg[0] = header->path; |
#endif |
_argc = 1; |
if( header->cmdline != 0) |
{ |
#ifdef BRAVE_NEW_WORLD |
len = strlen(header->cmdline); |
if(len) |
{ |
p = alloca(len+1); |
memcpy(p, header->cmdline, len); |
p[len]=0; |
_argc = 2; |
arg[1] = p; |
}; |
#else |
_argc = 2; |
arg[1] = header->cmdline; |
#endif |
}; |
_argv = arg; |
entry = get_entry_point(my_app); |
// __asm__ __volatile__("int3"); |
retval = entry(_argc, _argv, NULL); |
done: |
exit (retval); |
} |
/programs/develop/libraries/newlib/crt/emutls.c |
---|
0,0 → 1,218 |
/* TLS emulation. |
Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc. |
Contributed by Jakub Jelinek <jakub@redhat.com>. |
This file is part of GCC. |
GCC is free software; you can redistribute it and/or modify it under |
the terms of the GNU General Public License as published by the Free |
Software Foundation; either version 3, or (at your option) any later |
version. |
GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
WARRANTY; without even the implied warranty of MERCHANTABILITY or |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
for more details. |
Under Section 7 of GPL version 3, you are granted additional |
permissions described in the GCC Runtime Library Exception, version |
3.1, as published by the Free Software Foundation. |
You should have received a copy of the GNU General Public License and |
a copy of the GCC Runtime Library Exception along with this program; |
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
<http://www.gnu.org/licenses/>. */ |
#include <stdlib.h> |
#include <memory.h> |
#include <malloc.h> |
#include <errno.h> |
#include <gthr.h> |
void *tls_alloc(void); |
void __mutex_lock(volatile int *val); |
static inline void yield(void) |
{ |
__asm__ __volatile__( |
"int $0x40" |
::"a"(68), "b"(1)); |
}; |
int __gthread_once (__gthread_once_t *once, void (*func) (void)) |
{ |
if (once == NULL || func == NULL) |
return EINVAL; |
if (! once->done) |
{ |
if(++once->started == 0) |
{ |
(*func) (); |
once->done = 1; |
} |
else |
{ |
/* Another thread is currently executing the code, so wait for it |
to finish; yield the CPU in the meantime. If performance |
does become an issue, the solution is to use an Event that |
we wait on here (and set above), but that implies a place to |
create the event before this routine is called. */ |
while (! once->done) |
yield(); |
} |
} |
return 0; |
} |
#define __GTHREAD_ONCE_INIT {0, -1} |
typedef unsigned int word __attribute__((mode(word))); |
typedef unsigned int pointer __attribute__((mode(pointer))); |
struct __emutls_object |
{ |
word size; |
word align; |
union { |
pointer offset; |
void *ptr; |
} loc; |
void *templ; |
}; |
struct __emutls_array |
{ |
pointer size; |
void **data[]; |
}; |
void *__emutls_get_address (struct __emutls_object *); |
void __emutls_register_common (struct __emutls_object *, word, word, void *); |
static __gthread_mutex_t emutls_mutex; |
static __gthread_key_t emutls_key; |
static pointer emutls_size; |
static void emutls_destroy (void *ptr) |
{ |
struct __emutls_array *arr = ptr; |
pointer size = arr->size; |
pointer i; |
for (i = 0; i < size; ++i) |
{ |
if (arr->data[i]) |
free (arr->data[i][-1]); |
} |
free (ptr); |
}; |
static void emutls_init (void) |
{ |
if (__gthread_key_create (&emutls_key, emutls_destroy) != 0) |
abort (); |
} |
static void *emutls_alloc (struct __emutls_object *obj) |
{ |
void *ptr; |
void *ret; |
/* We could use here posix_memalign if available and adjust |
emutls_destroy accordingly. */ |
if (obj->align <= sizeof (void *)) |
{ |
ptr = malloc (obj->size + sizeof (void *)); |
if (ptr == NULL) |
abort (); |
((void **) ptr)[0] = ptr; |
ret = ptr + sizeof (void *); |
} |
else |
{ |
ptr = malloc (obj->size + sizeof (void *) + obj->align - 1); |
if (ptr == NULL) |
abort (); |
ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1)) |
& ~(pointer)(obj->align - 1)); |
((void **) ret)[-1] = ptr; |
} |
if (obj->templ) |
memcpy (ret, obj->templ, obj->size); |
else |
memset (ret, 0, obj->size); |
return ret; |
} |
void * __emutls_get_address (struct __emutls_object *obj) |
{ |
pointer offset = obj->loc.offset; |
if (__builtin_expect (offset == 0, 0)) |
{ |
static __gthread_once_t once = __GTHREAD_ONCE_INIT; |
__gthread_once (&once, emutls_init); |
__gthread_mutex_lock (&emutls_mutex); |
offset = obj->loc.offset; |
if (offset == 0) |
{ |
offset = ++emutls_size; |
obj->loc.offset = offset; |
} |
__gthread_mutex_unlock (&emutls_mutex); |
} |
struct __emutls_array *arr = __gthread_getspecific (emutls_key); |
if (__builtin_expect (arr == NULL, 0)) |
{ |
pointer size = offset + 32; |
arr = calloc (size + 1, sizeof (void *)); |
if (arr == NULL) |
abort (); |
arr->size = size; |
__gthread_setspecific (emutls_key, (void *) arr); |
} |
else if (__builtin_expect (offset > arr->size, 0)) |
{ |
pointer orig_size = arr->size; |
pointer size = orig_size * 2; |
if (offset > size) |
size = offset + 32; |
arr = realloc (arr, (size + 1) * sizeof (void *)); |
if (arr == NULL) |
abort (); |
arr->size = size; |
memset (arr->data + orig_size, 0, |
(size - orig_size) * sizeof (void *)); |
__gthread_setspecific (emutls_key, (void *) arr); |
} |
void *ret = arr->data[offset - 1]; |
if (__builtin_expect (ret == NULL, 0)) |
{ |
ret = emutls_alloc (obj); |
arr->data[offset - 1] = ret; |
} |
return ret; |
} |
void __emutls_register_common (struct __emutls_object *obj, |
word size, word align, void *templ) |
{ |
if (obj->size < size) |
{ |
obj->size = size; |
obj->templ = NULL; |
} |
if (obj->align < align) |
obj->align = align; |
if (templ && size == obj->size) |
obj->templ = templ; |
} |
/programs/develop/libraries/newlib/crt/exit.S |
---|
0,0 → 1,20 |
.section .text |
.global __exit |
.global __Exit |
.align 4 |
__exit: |
__Exit: |
movl 4(%esp), %edx #store exit code |
movl $68, %eax |
movl $13, %ebx |
movl %fs:4, %ecx |
int $0x40 #destroy stack |
movl $-1, %eax |
int $0x40 #terminate thread |
/programs/develop/libraries/newlib/crt/i386mach.h |
---|
0,0 → 1,76 |
/* This file was based on the modified setjmp.S performed by |
* Joel Sherill (joel@OARcorp.com) which specified the use |
* of the __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ macros. |
** |
** This file is distributed WITHOUT ANY WARRANTY; without even the implied |
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* These are predefined by new versions of GNU cpp. */ |
#ifndef __USER_LABEL_PREFIX__ |
#define __USER_LABEL_PREFIX__ _ |
#endif |
#define __REG_PREFIX__ % |
/* ANSI concatenation macros. */ |
#define CONCAT1(a, b) CONCAT2(a, b) |
#define CONCAT2(a, b) a##b |
/* Use the right prefix for global labels. */ |
#define SYM(x) CONCAT1(__USER_LABEL_PREFIX__, x) |
/* Use the right prefix for registers. */ |
#define REG(x) CONCAT1(__REG_PREFIX__, x) |
#define eax REG(eax) |
#define ebx REG(ebx) |
#define ecx REG(ecx) |
#define edx REG(edx) |
#define esi REG(esi) |
#define edi REG(edi) |
#define ebp REG(ebp) |
#define esp REG(esp) |
#define st0 REG(st) |
#define st1 REG(st(1)) |
#define st2 REG(st(2)) |
#define st3 REG(st(3)) |
#define st4 REG(st(4)) |
#define st5 REG(st(5)) |
#define st6 REG(st(6)) |
#define st7 REG(st(7)) |
#define ax REG(ax) |
#define bx REG(bx) |
#define cx REG(cx) |
#define dx REG(dx) |
#define ah REG(ah) |
#define bh REG(bh) |
#define ch REG(ch) |
#define dh REG(dh) |
#define al REG(al) |
#define bl REG(bl) |
#define cl REG(cl) |
#define dl REG(dl) |
#define mm1 REG(mm1) |
#define mm2 REG(mm2) |
#define mm3 REG(mm3) |
#define mm4 REG(mm4) |
#define mm5 REG(mm5) |
#define mm6 REG(mm6) |
#define mm7 REG(mm7) |
#ifdef _I386MACH_NEED_SOTYPE_FUNCTION |
#define SOTYPE_FUNCTION(sym) .type SYM(sym),@function |
#else |
#define SOTYPE_FUNCTION(sym) |
#endif |
/programs/develop/libraries/newlib/crt/pseudo-reloc.S |
---|
0,0 → 1,26 |
.global __pei386_runtime_relocator |
.text |
__pei386_runtime_relocator: |
# movl $___RUNTIME_PSEUDO_RELOC_LIST__, %ecx |
# pushl %ebp |
# cmpl $___RUNTIME_PSEUDO_RELOC_LIST_END__, %ecx |
# movl %esp, %ebp |
# jnb .L2 |
#.L1: |
# movl (%ecx), %eax |
# movl 4(%ecx), %edx |
# addl $8, %ecx |
# addl %eax, __image_base__(%edx) |
# cmpl $___RUNTIME_PSEUDO_RELOC_LIST_END__, %ecx |
# jb .L1 |
#.L2: |
# popl %ebp |
ret |
/programs/develop/libraries/newlib/crt/setjmp.S |
---|
0,0 → 1,89 |
/* This is file is a merger of SETJMP.S and LONGJMP.S */ |
/* |
* This file was modified to use the __USER_LABEL_PREFIX__ and |
* __REGISTER_PREFIX__ macros defined by later versions of GNU cpp by |
* Joel Sherrill (joel@OARcorp.com) |
* Slight change: now includes i386mach.h for this (Werner Almesberger) |
* |
* Copyright (C) 1991 DJ Delorie |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms is permitted |
* provided that the above copyright notice and following paragraph are |
* duplicated in all such forms. |
* |
* This file is distributed WITHOUT ANY WARRANTY; without even the implied |
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
** jmp_buf: |
** eax ebx ecx edx esi edi ebp esp eip |
** 0 4 8 12 16 20 24 28 32 |
*/ |
#include "i386mach.h" |
.global SYM (setjmp) |
.global SYM (longjmp) |
SOTYPE_FUNCTION(setjmp) |
SOTYPE_FUNCTION(longjmp) |
.def _setjmp; .scl 2; .type 32; .endef |
SYM (setjmp): |
pushl ebp |
movl esp,ebp |
pushl edi |
movl 8 (ebp),edi |
movl eax,0 (edi) |
movl ebx,4 (edi) |
movl ecx,8 (edi) |
movl edx,12 (edi) |
movl esi,16 (edi) |
movl -4 (ebp),eax |
movl eax,20 (edi) |
movl 0 (ebp),eax |
movl eax,24 (edi) |
movl esp,eax |
addl $12,eax |
movl eax,28 (edi) |
movl 4 (ebp),eax |
movl eax,32 (edi) |
popl edi |
movl $0,eax |
leave |
ret |
.def _longjmp; .scl 2; .type 32; .endef |
SYM (longjmp): |
pushl ebp |
movl esp,ebp |
movl 8(ebp),edi /* get jmp_buf */ |
movl 12(ebp),eax /* store retval in j->eax */ |
movl eax,0(edi) |
movl 24(edi),ebp |
movl 28(edi),esp |
pushl 32(edi) |
movl 0(edi),eax |
movl 4(edi),ebx |
movl 8(edi),ecx |
movl 12(edi),edx |
movl 16(edi),esi |
movl 20(edi),edi |
ret |
/programs/develop/libraries/newlib/crt/start.S |
---|
2,8 → 2,6 |
.section .init |
.global __start |
.global __exit |
.global __Exit |
.align 4 |
__start: |
20,21 → 18,30 |
movl %eax, %fs:4 |
movl %ecx, %fs:8 #save stack base - low limit |
#save stack top - high limit |
movl %ecx, %esp |
jmp ___crt_startup #reload stack |
movl %ecx, %esp #reload stack |
subl $1024, %esp |
movl $9, %eax |
movl %esp, %ebx |
movl $-1, %ecx |
int $0x40 |
movl 30(%ebx), %eax |
movl %eax, %fs:0 #save pid |
movl $__tls_map, %edi #init TLS |
movl $32, %ecx |
xorl %eax, %eax |
notl %eax |
rep |
stosl |
movb $0xF0, __tls_map |
jmp ___crt_startup |
1: |
int3 #trap to debugger |
.ascii "No enough memory for stack allocation" |
.align 4 |
__exit: |
__Exit: |
movl 4(%esp), %edx #store exit code |
movl $68, %eax |
movl $13, %ebx |
movl %fs:4, %ecx |
int $0x40 #destroy stack |
movl $-1, %eax |
int $0x40 #terminate thread |
/programs/develop/libraries/newlib/crt/tls.S |
---|
0,0 → 1,48 |
.section .text |
.global _tls_alloc |
.global __tls_map |
.align 4 |
_tls_alloc: |
pushl $tls_mutex |
call ___mutex_lock |
popl %eax |
movl tls_map_start, %edx |
.align 4 |
.test: |
bsfl (%edx), %eax |
jnz .done |
add $4, %edx |
cmpl $128+__tls_map, %edx |
jb .test |
xorl %eax, %eax |
mov %eax, tls_mutex |
ret |
.done: |
btrl %eax, (%edx) |
movl %edx, tls_map_start |
movl $0, tls_mutex |
subl $__tls_map, %edx |
leal (%eax, %edx, 8), %eax |
shll $2, %eax |
ret |
.section .data |
tls_mutex: .long(0) |
tls_map_start: .long(__tls_map) |
.section .bss |
.align 16 |
__tls_map: .space 128 |
/programs/develop/libraries/newlib/ctype/isascii.c |
---|
0,0 → 1,43 |
/* |
FUNCTION |
<<isascii>>---ASCII character predicate |
INDEX |
isascii |
ANSI_SYNOPSIS |
#include <ctype.h> |
int isascii(int <[c]>); |
TRAD_SYNOPSIS |
#include <ctype.h> |
int isascii(<[c]>); |
DESCRIPTION |
<<isascii>> is a macro which returns non-zero when <[c]> is an ASCII |
character, and 0 otherwise. It is defined for all integer values. |
You can use a compiled subroutine instead of the macro definition by |
undefining the macro using `<<#undef isascii>>'. |
RETURNS |
<<isascii>> returns non-zero if the low order byte of <[c]> is in the range |
0 to 127 (<<0x00>>--<<0x7F>>). |
PORTABILITY |
<<isascii>> is ANSI C. |
No supporting OS subroutines are required. |
*/ |
#include <_ansi.h> |
#include <ctype.h> |
#undef isascii |
int |
_DEFUN(isascii,(c),int c) |
{ |
return c >= 0 && c< 128; |
} |
/programs/develop/libraries/newlib/ctype/isblank.c |
---|
0,0 → 1,41 |
/* |
FUNCTION |
<<isblank>>---blank character predicate |
INDEX |
isblank |
ANSI_SYNOPSIS |
#include <ctype.h> |
int isblank(int <[c]>); |
TRAD_SYNOPSIS |
#include <ctype.h> |
int isblank(<[c]>); |
DESCRIPTION |
<<isblank>> is a function which classifies ASCII integer values by table |
lookup. It is a predicate returning non-zero for blank characters, and 0 |
for other characters. |
RETURNS |
<<isblank>> returns non-zero if <[c]> is a blank character. |
PORTABILITY |
<<isblank>> is C99. |
No supporting OS subroutines are required. |
*/ |
#include <_ansi.h> |
#include <ctype.h> |
#undef isblank |
int |
_DEFUN(isblank,(c),int c) |
{ |
return ((__ctype_ptr__[c+1] & _B) || (c == '\t')); |
} |
/programs/develop/libraries/newlib/ctype/toascii.c |
---|
0,0 → 1,41 |
/* |
FUNCTION |
<<toascii>>---force integers to ASCII range |
INDEX |
toascii |
ANSI_SYNOPSIS |
#include <ctype.h> |
int toascii(int <[c]>); |
TRAD_SYNOPSIS |
#include <ctype.h> |
int toascii(<[c]>); |
int (<[c]>); |
DESCRIPTION |
<<toascii>> is a macro which coerces integers to the ASCII range (0--127) by zeroing any higher-order bits. |
You can use a compiled subroutine instead of the macro definition by |
undefining this macro using `<<#undef toascii>>'. |
RETURNS |
<<toascii>> returns integers between 0 and 127. |
PORTABILITY |
<<toascii>> is not ANSI C. |
No supporting OS subroutines are required. |
*/ |
#include <_ansi.h> |
#include <ctype.h> |
#undef toascii |
int |
_DEFUN(toascii,(c),int c) |
{ |
return (c)&0177; |
} |
/programs/develop/libraries/newlib/ctype/towctrans.c |
---|
0,0 → 1,97 |
/* Copyright (c) 2002 Red Hat Incorporated. |
All rights reserved. |
Redistribution and use in source and binary forms, with or without |
modification, are permitted provided that the following conditions are met: |
Redistributions of source code must retain the above copyright |
notice, this list of conditions and the following disclaimer. |
Redistributions in binary form must reproduce the above copyright |
notice, this list of conditions and the following disclaimer in the |
documentation and/or other materials provided with the distribution. |
The name of Red Hat Incorporated may not be used to endorse |
or promote products derived from this software without specific |
prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
ARE DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* |
FUNCTION |
<<towctrans>>---extensible wide-character translation |
INDEX |
towctrans |
ANSI_SYNOPSIS |
#include <wctype.h> |
wint_t towctrans(wint_t <[c]>, wctrans_t <[w]>); |
TRAD_SYNOPSIS |
#include <wctype.h> |
wint_t towctrans(<[c]>, <[w]>) |
wint_t <[c]>; |
wctrans_t <[w]>; |
DESCRIPTION |
<<towctrans>> is a function which converts wide characters based on |
a specified translation type <[w]>. If the translation type is |
invalid or cannot be applied to the current character, no change |
to the character is made. |
RETURNS |
<<towctrans>> returns the translated equivalent of <[c]> when it is a |
valid for the given translation, otherwise, it returns the input character. |
When the translation type is invalid, <<errno>> is set <<EINVAL>>. |
PORTABILITY |
<<towctrans>> is C99. |
No supporting OS subroutines are required. |
*/ |
#include <_ansi.h> |
#include <string.h> |
#include <reent.h> |
#include <wctype.h> |
#include <errno.h> |
#include "local.h" |
wint_t |
_DEFUN (_towctrans_r, (r, c, w), |
struct _reent *r _AND |
wint_t c _AND |
wctrans_t w) |
{ |
if (w == WCT_TOLOWER) |
return towlower (c); |
else if (w == WCT_TOUPPER) |
return towupper (c); |
else |
{ |
r->_errno = EINVAL; |
return c; |
} |
} |
#ifndef _REENT_ONLY |
wint_t |
_DEFUN (towctrans, (c, w), |
wint_t c _AND |
wctrans_t w) |
{ |
return _towctrans_r (_REENT, c, w); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/ctype/wctrans.c |
---|
0,0 → 1,94 |
/* Copyright (c) 2002 Red Hat Incorporated. |
All rights reserved. |
Redistribution and use in source and binary forms, with or without |
modification, are permitted provided that the following conditions are met: |
Redistributions of source code must retain the above copyright |
notice, this list of conditions and the following disclaimer. |
Redistributions in binary form must reproduce the above copyright |
notice, this list of conditions and the following disclaimer in the |
documentation and/or other materials provided with the distribution. |
The name of Red Hat Incorporated may not be used to endorse |
or promote products derived from this software without specific |
prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
ARE DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* |
FUNCTION |
<<wctrans>>---get wide-character translation type |
INDEX |
wctrans |
ANSI_SYNOPSIS |
#include <wctype.h> |
wctrans_t wctrans(const char *<[c]>); |
TRAD_SYNOPSIS |
#include <wctype.h> |
wctrans_t wctrans(<[c]>) |
const char * <[c]>; |
DESCRIPTION |
<<wctrans>> is a function which takes a string <[c]> and gives back |
the appropriate wctrans_t type value associated with the string, |
if one exists. The following values are guaranteed to be recognized: |
"tolower" and "toupper". |
RETURNS |
<<wctrans>> returns 0 and sets <<errno>> to <<EINVAL>> if the |
given name is invalid. Otherwise, it returns a valid non-zero wctrans_t |
value. |
PORTABILITY |
<<wctrans>> is C99. |
No supporting OS subroutines are required. |
*/ |
#include <_ansi.h> |
#include <string.h> |
#include <reent.h> |
#include <wctype.h> |
#include <errno.h> |
#include "local.h" |
wctrans_t |
_DEFUN (_wctrans_r, (r, c), |
struct _reent *r _AND |
const char *c) |
{ |
if (!strcmp (c, "tolower")) |
return WCT_TOLOWER; |
else if (!strcmp (c, "toupper")) |
return WCT_TOUPPER; |
else |
{ |
r->_errno = EINVAL; |
return 0; |
} |
} |
#ifndef _REENT_ONLY |
wctrans_t |
_DEFUN (wctrans, (c), |
const char *c) |
{ |
return _wctrans_r (_REENT, c); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/ctype/wctype.c |
---|
0,0 → 1,137 |
/* Copyright (c) 2002 Red Hat Incorporated. |
All rights reserved. |
Redistribution and use in source and binary forms, with or without |
modification, are permitted provided that the following conditions are met: |
Redistributions of source code must retain the above copyright |
notice, this list of conditions and the following disclaimer. |
Redistributions in binary form must reproduce the above copyright |
notice, this list of conditions and the following disclaimer in the |
documentation and/or other materials provided with the distribution. |
The name of Red Hat Incorporated may not be used to endorse |
or promote products derived from this software without specific |
prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
ARE DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* |
FUNCTION |
<<wctype>>---get wide-character classification type |
INDEX |
wctype |
ANSI_SYNOPSIS |
#include <wctype.h> |
wctype_t wctype(const char *<[c]>); |
TRAD_SYNOPSIS |
#include <wctype.h> |
wctype_t wctype(<[c]>) |
const char * <[c]>; |
DESCRIPTION |
<<wctype>> is a function which takes a string <[c]> and gives back |
the appropriate wctype_t type value associated with the string, |
if one exists. The following values are guaranteed to be recognized: |
"alnum", "alpha", "blank", "cntrl", "digit", "graph", "lower", "print", |
"punct", "space", "upper", and "xdigit". |
RETURNS |
<<wctype>> returns 0 and sets <<errno>> to <<EINVAL>> if the |
given name is invalid. Otherwise, it returns a valid non-zero wctype_t |
value. |
PORTABILITY |
<<wctype>> is C99. |
No supporting OS subroutines are required. |
*/ |
#include <_ansi.h> |
#include <string.h> |
#include <reent.h> |
#include <wctype.h> |
#include <errno.h> |
#include "local.h" |
wctype_t |
_DEFUN (_wctype_r, (r, c), |
struct _reent *r _AND |
const char *c) |
{ |
switch (*c) |
{ |
case 'a': |
if (!strcmp (c, "alnum")) |
return WC_ALNUM; |
else if (!strcmp (c, "alpha")) |
return WC_ALPHA; |
break; |
case 'b': |
if (!strcmp (c, "blank")) |
return WC_BLANK; |
break; |
case 'c': |
if (!strcmp (c, "cntrl")) |
return WC_CNTRL; |
break; |
case 'd': |
if (!strcmp (c, "digit")) |
return WC_DIGIT; |
break; |
case 'g': |
if (!strcmp (c, "graph")) |
return WC_GRAPH; |
break; |
case 'l': |
if (!strcmp (c, "lower")) |
return WC_LOWER; |
break; |
case 'p': |
if (!strcmp (c, "print")) |
return WC_PRINT; |
else if (!strcmp (c, "punct")) |
return WC_PUNCT; |
break; |
case 's': |
if (!strcmp (c, "space")) |
return WC_SPACE; |
break; |
case 'u': |
if (!strcmp (c, "upper")) |
return WC_UPPER; |
break; |
case 'x': |
if (!strcmp (c, "xdigit")) |
return WC_XDIGIT; |
break; |
} |
/* otherwise invalid */ |
r->_errno = EINVAL; |
return 0; |
} |
#ifndef _REENT_ONLY |
wctype_t |
_DEFUN (wctype, (c), |
const char *c) |
{ |
return _wctype_r (_REENT, c); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/dll.lds |
---|
0,0 → 1,126 |
OUTPUT_FORMAT(pei-i386) |
ENTRY("__start") |
SECTIONS |
{ |
. = SIZEOF_HEADERS; |
. = ALIGN(__section_alignment__); |
.text __image_base__ + . : |
{ |
*(.init) |
*(.text) |
*(SORT(.text$*)) |
*(.text.*) |
*(.glue_7t) |
*(.glue_7) |
___CTOR_LIST__ = .; __CTOR_LIST__ = . ; |
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0); |
___DTOR_LIST__ = .; __DTOR_LIST__ = . ; |
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0); |
*(.fini) |
/* ??? Why is .gcc_exc here? */ |
*(.gcc_exc) |
PROVIDE (etext = .); |
*(.gcc_except_table) |
} |
.rdata ALIGN(__section_alignment__): |
{ |
*(.rdata) |
*(SORT(.rdata$*)) |
___RUNTIME_PSEUDO_RELOC_LIST__ = .; |
__RUNTIME_PSEUDO_RELOC_LIST__ = .; |
*(.rdata_runtime_pseudo_reloc) |
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .; |
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .; |
} |
.CRT ALIGN(__section_alignment__): |
{ |
___crt_xc_start__ = . ; |
*(SORT(.CRT$XC*)) /* C initialization */ |
___crt_xc_end__ = . ; |
___crt_xi_start__ = . ; |
*(SORT(.CRT$XI*)) /* C++ initialization */ |
___crt_xi_end__ = . ; |
___crt_xl_start__ = . ; |
*(SORT(.CRT$XL*)) /* TLS callbacks */ |
/* ___crt_xl_end__ is defined in the TLS Directory support code */ |
___crt_xp_start__ = . ; |
*(SORT(.CRT$XP*)) /* Pre-termination */ |
___crt_xp_end__ = . ; |
___crt_xt_start__ = . ; |
*(SORT(.CRT$XT*)) /* Termination */ |
___crt_xt_end__ = . ; |
} |
.data ALIGN(__section_alignment__): |
{ |
PROVIDE ( __data_start__ = .) ; |
*(.data) |
*(.data2) |
*(SORT(.data$*)) |
*(.jcr) |
__CRT_MT = .; |
LONG(0); |
PROVIDE ( __data_end__ = .) ; |
*(.data_cygwin_nocopy) |
} |
.eh_frame ALIGN(__section_alignment__): |
{ |
*(.eh_frame) |
___iend = . ; |
} |
.bss ALIGN(__section_alignment__): |
{ |
*(.bss) |
*(COMMON) |
} |
.edata ALIGN(__section_alignment__): |
{ |
*(.edata) |
} |
/DISCARD/ : |
{ |
*(.debug$S) |
*(.debug$T) |
*(.debug$F) |
*(.drectve) |
*(.note.GNU-stack) |
*(.comment) |
*(.debug_abbrev) |
*(.debug_info) |
*(.debug_line) |
*(.debug_frame) |
*(.debug_loc) |
*(.debug_pubnames) |
*(.debug_aranges) |
*(.debug_ranges) |
} |
.idata ALIGN(__section_alignment__): |
{ |
SORT(*)(.idata$2) |
SORT(*)(.idata$3) |
/* These zeroes mark the end of the import list. */ |
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); |
SORT(*)(.idata$4) |
SORT(*)(.idata$5) |
SORT(*)(.idata$6) |
SORT(*)(.idata$7) |
} |
.reloc ALIGN(__section_alignment__) : |
{ |
*(.reloc) |
} |
} |
/programs/develop/libraries/newlib/include/gthr.h |
---|
0,0 → 1,103 |
/* Threads compatibility routines for libgcc2. */ |
/* Compile this one with gcc. */ |
/* Copyright (C) 1997, 1998, 2004, 2008, 2009 Free Software Foundation, Inc. |
This file is part of GCC. |
GCC is free software; you can redistribute it and/or modify it under |
the terms of the GNU General Public License as published by the Free |
Software Foundation; either version 3, or (at your option) any later |
version. |
GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
WARRANTY; without even the implied warranty of MERCHANTABILITY or |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
for more details. |
Under Section 7 of GPL version 3, you are granted additional |
permissions described in the GCC Runtime Library Exception, version |
3.1, as published by the Free Software Foundation. |
You should have received a copy of the GNU General Public License and |
a copy of the GCC Runtime Library Exception along with this program; |
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
<http://www.gnu.org/licenses/>. */ |
#ifndef GCC_GTHR_H |
#define GCC_GTHR_H |
typedef unsigned int __gthread_key_t; |
typedef struct { |
volatile int done; |
int started; |
} __gthread_once_t; |
typedef struct { |
volatile int counter; |
} __gthread_mutex_t; |
void *tls_alloc(void); |
static int __gthread_mutex_lock (__gthread_mutex_t *mutex) |
{ |
__mutex_lock(&mutex->counter); |
return 0; |
}; |
static int __gthread_mutex_unlock (__gthread_mutex_t *mutex) |
{ |
mutex->counter = 0; |
return 0; |
}; |
static inline int __gthread_key_create (__gthread_key_t *__key, |
void (*__dtor) (void *) __attribute__((unused))) |
{ |
int __status = 0; |
void *__tls_index = tls_alloc(); |
if (__tls_index != NULL) |
{ |
*__key = (unsigned int)__tls_index; |
#ifdef MINGW32_SUPPORTS_MT_EH /* FIXME */ |
/* Mingw runtime will run the dtors in reverse order for each thread |
when the thread exits. */ |
// __status = __mingwthr_key_dtor (*__key, __dtor); |
#endif |
} |
else |
__status = (int) ENOMEM; |
return __status; |
} |
static inline void * |
__gthread_getspecific (__gthread_key_t __key) |
{ |
void *val; |
__asm__ __volatile__( |
"movl %%fs:(%1), %0" |
:"=r"(val) |
:"r"(__key)); |
return val; |
}; |
static inline int |
__gthread_setspecific (__gthread_key_t __key, const void *__ptr) |
{ |
if(!(__key & 3)) |
{ |
__asm__ __volatile__( |
"movl %0, %%fs:(%1)" |
::"r"(__ptr),"r"(__key)); |
return 0; |
} |
else return EINVAL; |
} |
#endif |
/programs/develop/libraries/newlib/include/newlib.h |
---|
5,16 → 5,6 |
#ifndef _NEWLIB_H_ |
#define _NEWLIB_H_ |
/* |
#ifdef __LIBC_DLL__ |
#ifdef __LIBC_EXPORT__ |
#define API __attribute__ ((dllexport)) |
#else |
#define API __attribute__ ((dllimport)) |
#endif |
#else |
#define API |
#endif |
*/ |
#define __DYNAMIC_REENT__ |
#endif /* _NEWLIB_H_ */ |
/programs/develop/libraries/newlib/include/sys/lock.h |
---|
27,9 → 27,13 |
#define __LOCK_INIT(class,lock) \ |
__libc_lock_define_initialized(class, lock) |
#define __LOCK_INIT_RECURSIVE(class, lock) \ |
__libc_lock_define_initialized_recursive(class, lock) |
#define __libc_lock_define_initialized(CLASS,NAME) \ |
CLASS __libc_lock_t NAME; |
#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ |
CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; |
/programs/develop/libraries/newlib/include/sys/reent.h |
---|
822,19 → 822,17 |
/* #define _REENT_ONLY define this to get only reentrant routines */ |
#ifndef _REENT_ONLY |
#if defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__) |
#ifndef __getreent |
struct _reent * _EXFUN(__getreent, (void)); |
#endif |
static inline struct _reent *__getreent(void) |
{ |
struct _reent *ent; |
__asm__ __volatile__( |
"movl %%fs:12, %0" |
:"=r"(ent)); |
return ent; |
}; |
# define _REENT (__getreent()) |
#else /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */ |
# define _REENT _impure_ptr |
#endif /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */ |
#endif /* !_REENT_ONLY */ |
#define _GLOBAL_REENT _global_impure_ptr |
#ifdef __cplusplus |
/programs/develop/libraries/newlib/libcdll.lds |
---|
0,0 → 1,82 |
OUTPUT_FORMAT(pei-i386) |
ENTRY("_crt_startup") |
SECTIONS |
{ |
. = SIZEOF_HEADERS; |
. = ALIGN(__section_alignment__); |
.text __image_base__ + . : |
{ |
*(.text) *(.rdata) |
. = ALIGN(16); |
___RUNTIME_PSEUDO_RELOC_LIST__ = .; |
__RUNTIME_PSEUDO_RELOC_LIST__ = .; |
*(.rdata_runtime_pseudo_reloc) |
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .; |
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .; |
__pei386_runtime_relocator = .; |
} |
.data ALIGN(__section_alignment__): |
{ |
PROVIDE ( __data_start__ = .) ; |
*(.data) |
*(.data2) |
*(SORT(.data$*)) |
*(.jcr) |
PROVIDE ( __data_end__ = .) ; |
*(.data_cygwin_nocopy) |
} |
.bss ALIGN(__section_alignment__): |
{ |
*(.bss) |
*(COMMON) |
} |
.edata ALIGN(__section_alignment__): |
{ |
*(.edata) |
} |
/DISCARD/ : |
{ |
*(.debug$S) |
*(.debug$T) |
*(.debug$F) |
*(.drectve) |
*(.note.GNU-stack) |
*(.comment) |
*(.debug_abbrev) |
*(.debug_info) |
*(.debug_line) |
*(.debug_frame) |
*(.debug_loc) |
*(.debug_pubnames) |
*(.debug_aranges) |
*(.debug_ranges) |
} |
.idata ALIGN(__section_alignment__): |
{ |
SORT(*)(.idata$2) |
SORT(*)(.idata$3) |
/* These zeroes mark the end of the import list. */ |
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); |
SORT(*)(.idata$4) |
SORT(*)(.idata$5) |
SORT(*)(.idata$6) |
SORT(*)(.idata$7) |
} |
.reloc ALIGN(__section_alignment__) : |
{ |
*(.reloc) |
} |
} |
/programs/develop/libraries/newlib/locale/lctype.c |
---|
0,0 → 1,111 |
/* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <limits.h> |
#include <string.h> |
#include "lctype.h" |
#include "ldpart.h" |
#include "setlocale.h" |
#define LCCTYPE_SIZE (sizeof(struct lc_ctype_T) / sizeof(char *)) |
static char numone[] = { '\1', '\0'}; |
static const struct lc_ctype_T _C_ctype_locale = { |
"ASCII", /* codeset */ |
numone /* mb_cur_max */ |
#ifdef __HAVE_LOCALE_INFO_EXTENDED__ |
, |
{ "0", "1", "2", "3", "4", /* outdigits */ |
"5", "6", "7", "8", "9" }, |
{ L"0", L"1", L"2", L"3", L"4", /* woutdigits */ |
L"5", L"6", L"7", L"8", L"9" } |
#endif |
}; |
static struct lc_ctype_T _ctype_locale; |
static int _ctype_using_locale; |
#ifdef __HAVE_LOCALE_INFO_EXTENDED__ |
static char *_ctype_locale_buf; |
#else |
/* Max encoding_len + NUL byte + 1 byte mb_cur_max plus trailing NUL byte */ |
#define _CTYPE_BUF_SIZE (ENCODING_LEN + 3) |
static char _ctype_locale_buf[_CTYPE_BUF_SIZE]; |
#endif |
int |
__ctype_load_locale(const char *name, void *f_wctomb, const char *charset, |
int mb_cur_max) |
{ |
int ret; |
#ifdef __CYGWIN__ |
extern int __set_lc_ctype_from_win (const char *, |
const struct lc_ctype_T *, |
struct lc_ctype_T *, char **, |
void *, const char *, int); |
int old_ctype_using_locale = _ctype_using_locale; |
_ctype_using_locale = 0; |
ret = __set_lc_ctype_from_win (name, &_C_ctype_locale, &_ctype_locale, |
&_ctype_locale_buf, f_wctomb, charset, |
mb_cur_max); |
/* ret == -1: error, ret == 0: C/POSIX, ret > 0: valid */ |
if (ret < 0) |
_ctype_using_locale = old_ctype_using_locale; |
else |
{ |
_ctype_using_locale = ret; |
ret = 0; |
} |
#elif !defined (__HAVE_LOCALE_INFO_EXTENDED__) |
if (!strcmp (name, "C")) |
_ctype_using_locale = 0; |
else |
{ |
_ctype_locale.codeset = strcpy (_ctype_locale_buf, charset); |
char *mbc = _ctype_locale_buf + _CTYPE_BUF_SIZE - 2; |
mbc[0] = mb_cur_max; |
mbc[1] = '\0'; |
_ctype_locale.mb_cur_max = mbc; |
_ctype_using_locale = 1; |
} |
ret = 0; |
#else |
ret = __part_load_locale(name, &_ctype_using_locale, |
_ctype_locale_buf, "LC_CTYPE", |
LCCTYPE_SIZE, LCCTYPE_SIZE, |
(const char **)&_ctype_locale); |
if (ret == 0 && _ctype_using_locale) |
_ctype_locale.grouping = |
__fix_locale_grouping_str(_ctype_locale.grouping); |
#endif |
return ret; |
} |
struct lc_ctype_T * |
__get_current_ctype_locale(void) { |
return (_ctype_using_locale |
? &_ctype_locale |
: (struct lc_ctype_T *)&_C_ctype_locale); |
} |
/programs/develop/libraries/newlib/math/acosf.c |
---|
0,0 → 1,40 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
#include <math.h> |
float |
acosf (float x) |
{ |
float res; |
/* acosl = atanl (sqrtl(1 - x^2) / x) */ |
asm ( "fld %%st\n\t" |
"fmul %%st(0)\n\t" /* x^2 */ |
"fld1\n\t" |
"fsubp\n\t" /* 1 - x^2 */ |
"fsqrt\n\t" /* sqrtl (1 - x^2) */ |
"fxch %%st(1)\n\t" |
"fpatan" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
double |
acos (double x) |
{ |
double res; |
/* acosl = atanl (sqrtl(1 - x^2) / x) */ |
asm ( "fld %%st\n\t" |
"fmul %%st(0)\n\t" /* x^2 */ |
"fld1\n\t" |
"fsubp\n\t" /* 1 - x^2 */ |
"fsqrt\n\t" /* sqrtl (1 - x^2) */ |
"fxch %%st(1)\n\t" |
"fpatan" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
/programs/develop/libraries/newlib/math/acosh.c |
---|
0,0 → 1,26 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* acosh(x) = log (x + sqrt(x * x - 1)) */ |
double acosh (double x) |
{ |
if (isnan (x)) |
return x; |
if (x < 1.0) |
{ |
errno = EDOM; |
return nan(""); |
} |
if (x > 0x1p32) |
/* Avoid overflow (and unnecessary calculation when |
sqrt (x * x - 1) == x). GCC optimizes by replacing |
the long double M_LN2 const with a fldln2 insn. */ |
return __fast_log (x) + 6.9314718055994530941723E-1L; |
/* Since x >= 1, the arg to log will always be greater than |
the fyl2xp1 limit (approx 0.29) so just use logl. */ |
return __fast_log (x + __fast_sqrt((x + 1.0) * (x - 1.0))); |
} |
/programs/develop/libraries/newlib/math/acoshf.c |
---|
0,0 → 1,25 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* acosh(x) = log (x + sqrt(x * x - 1)) */ |
float acoshf (float x) |
{ |
if (isnan (x)) |
return x; |
if (x < 1.0f) |
{ |
errno = EDOM; |
return nan(""); |
} |
if (x > 0x1p32f) |
/* Avoid overflow (and unnecessary calculation when |
sqrt (x * x - 1) == x). GCC optimizes by replacing |
the long double M_LN2 const with a fldln2 insn. */ |
return __fast_log (x) + 6.9314718055994530941723E-1L; |
/* Since x >= 1, the arg to log will always be greater than |
the fyl2xp1 limit (approx 0.29) so just use logl. */ |
return __fast_log (x + __fast_sqrt((x + 1.0) * (x - 1.0))); |
} |
/programs/develop/libraries/newlib/math/acoshl.c |
---|
0,0 → 1,27 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* acosh(x) = log (x + sqrt(x * x - 1)) */ |
long double acoshl (long double x) |
{ |
if (isnan (x)) |
return x; |
if (x < 1.0L) |
{ |
errno = EDOM; |
return nanl(""); |
} |
if (x > 0x1p32L) |
/* Avoid overflow (and unnecessary calculation when |
sqrt (x * x - 1) == x). |
The M_LN2 define doesn't have enough precison for |
long double so use this one. GCC optimizes by replacing |
the const with a fldln2 insn. */ |
return __fast_logl (x) + 6.9314718055994530941723E-1L; |
/* Since x >= 1, the arg to log will always be greater than |
the fyl2xp1 limit (approx 0.29) so just use logl. */ |
return __fast_logl (x + __fast_sqrtl((x + 1.0L) * (x - 1.0L))); |
} |
/programs/develop/libraries/newlib/math/acosl.c |
---|
0,0 → 1,25 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
*/ |
#include <math.h> |
long double |
acosl (long double x) |
{ |
long double res; |
/* acosl = atanl (sqrtl(1 - x^2) / x) */ |
asm ( "fld %%st\n\t" |
"fmul %%st(0)\n\t" /* x^2 */ |
"fld1\n\t" |
"fsubp\n\t" /* 1 - x^2 */ |
"fsqrt\n\t" /* sqrtl (1 - x^2) */ |
"fxch %%st(1)\n\t" |
"fpatan" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
/programs/develop/libraries/newlib/math/asinf.c |
---|
0,0 → 1,34 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
/* asin = atan (x / sqrt(1 - x^2)) */ |
float asinf (float x) |
{ |
float res; |
asm ( "fld %%st\n\t" |
"fmul %%st(0)\n\t" /* x^2 */ |
"fld1\n\t" |
"fsubp\n\t" /* 1 - x^2 */ |
"fsqrt\n\t" /* sqrt (1 - x^2) */ |
"fpatan" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
double asin (double x) |
{ |
double res; |
asm ( "fld %%st\n\t" |
"fmul %%st(0)\n\t" /* x^2 */ |
"fld1\n\t" |
"fsubp\n\t" /* 1 - x^2 */ |
"fsqrt\n\t" /* sqrt (1 - x^2) */ |
"fpatan" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
/programs/develop/libraries/newlib/math/asinh.c |
---|
0,0 → 1,28 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */ |
double asinh(double x) |
{ |
double z; |
if (!isfinite (x)) |
return x; |
z = fabs (x); |
/* Avoid setting FPU underflow exception flag in x * x. */ |
#if 0 |
if ( z < 0x1p-32) |
return x; |
#endif |
/* Use log1p to avoid cancellation with small x. Put |
x * x in denom, so overflow is harmless. |
asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0) |
= log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */ |
z = __fast_log1p (z + z * z / (__fast_sqrt (z * z + 1.0) + 1.0)); |
return ( x > 0.0 ? z : -z); |
} |
/programs/develop/libraries/newlib/math/asinhf.c |
---|
0,0 → 1,28 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */ |
float asinhf(float x) |
{ |
float z; |
if (!isfinite (x)) |
return x; |
z = fabsf (x); |
/* Avoid setting FPU underflow exception flag in x * x. */ |
#if 0 |
if ( z < 0x1p-32) |
return x; |
#endif |
/* Use log1p to avoid cancellation with small x. Put |
x * x in denom, so overflow is harmless. |
asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0) |
= log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */ |
z = __fast_log1p (z + z * z / (__fast_sqrt (z * z + 1.0) + 1.0)); |
return ( x > 0.0 ? z : -z); |
} |
/programs/develop/libraries/newlib/math/asinhl.c |
---|
0,0 → 1,28 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */ |
long double asinhl(long double x) |
{ |
long double z; |
if (!isfinite (x)) |
return x; |
z = fabsl (x); |
/* Avoid setting FPU underflow exception flag in x * x. */ |
#if 0 |
if ( z < 0x1p-32) |
return x; |
#endif |
/* Use log1p to avoid cancellation with small x. Put |
x * x in denom, so overflow is harmless. |
asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0) |
= log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */ |
z = __fast_log1pl (z + z * z / (__fast_sqrtl (z * z + 1.0L) + 1.0L)); |
return ( x > 0.0 ? z : -z); |
} |
/programs/develop/libraries/newlib/math/asinl.c |
---|
0,0 → 1,21 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Adapted for long double type by Danny Smith <dannysmith@users.sourceforge.net>. |
*/ |
/* asin = atan (x / sqrt(1 - x^2)) */ |
long double asinl (long double x) |
{ |
long double res; |
asm ( "fld %%st\n\t" |
"fmul %%st(0)\n\t" /* x^2 */ |
"fld1\n\t" |
"fsubp\n\t" /* 1 - x^2 */ |
"fsqrt\n\t" /* sqrt (1 - x^2) */ |
"fpatan" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
/programs/develop/libraries/newlib/math/atan2f.c |
---|
0,0 → 1,15 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
*/ |
#include <math.h> |
float |
atan2f (float y, float x) |
{ |
float res; |
asm ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)"); |
return res; |
} |
/programs/develop/libraries/newlib/math/atan2l.c |
---|
0,0 → 1,16 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
*/ |
#include <math.h> |
long double |
atan2l (long double y, long double x) |
{ |
long double res; |
asm ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)"); |
return res; |
} |
/programs/develop/libraries/newlib/math/atanf.c |
---|
0,0 → 1,28 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
*/ |
#include <math.h> |
float |
atanf (float x) |
{ |
float res; |
asm ("fld1\n\t" |
"fpatan" : "=t" (res) : "0" (x)); |
return res; |
} |
double |
atan (double x) |
{ |
double res; |
asm ("fld1 \n\t" |
"fpatan" : "=t" (res) : "0" (x)); |
return res; |
} |
/programs/develop/libraries/newlib/math/atanh.c |
---|
0,0 → 1,31 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* atanh (x) = 0.5 * log ((1.0 + x)/(1.0 - x)) */ |
double atanh(double x) |
{ |
double z; |
if isnan (x) |
return x; |
z = fabs (x); |
if (z == 1.0) |
{ |
errno = ERANGE; |
return (x > 0 ? INFINITY : -INFINITY); |
} |
if (z > 1.0) |
{ |
errno = EDOM; |
return nan(""); |
} |
/* Rearrange formula to avoid precision loss for small x. |
atanh(x) = 0.5 * log ((1.0 + x)/(1.0 - x)) |
= 0.5 * log1p ((1.0 + x)/(1.0 - x) - 1.0) |
= 0.5 * log1p ((1.0 + x - 1.0 + x) /(1.0 - x)) |
= 0.5 * log1p ((2.0 * x ) / (1.0 - x)) */ |
z = 0.5 * __fast_log1p ((z + z) / (1.0 - z)); |
return x >= 0 ? z : -z; |
} |
/programs/develop/libraries/newlib/math/atanhf.c |
---|
0,0 → 1,30 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* atanh (x) = 0.5 * log ((1.0 + x)/(1.0 - x)) */ |
float atanhf (float x) |
{ |
float z; |
if isnan (x) |
return x; |
z = fabsf (x); |
if (z == 1.0) |
{ |
errno = ERANGE; |
return (x > 0 ? INFINITY : -INFINITY); |
} |
if ( z > 1.0) |
{ |
errno = EDOM; |
return nanf(""); |
} |
/* Rearrange formula to avoid precision loss for small x. |
atanh(x) = 0.5 * log ((1.0 + x)/(1.0 - x)) |
= 0.5 * log1p ((1.0 + x)/(1.0 - x) - 1.0) |
= 0.5 * log1p ((1.0 + x - 1.0 + x) /(1.0 - x)) |
= 0.5 * log1p ((2.0 * x ) / (1.0 - x)) */ |
z = 0.5 * __fast_log1p ((z + z) / (1.0 - z)); |
return x >= 0 ? z : -z; |
} |
/programs/develop/libraries/newlib/math/atanhl.c |
---|
0,0 → 1,29 |
#include <math.h> |
#include <errno.h> |
#include "fastmath.h" |
/* atanh (x) = 0.5 * log ((1.0 + x)/(1.0 - x)) */ |
long double atanhl (long double x) |
{ |
long double z; |
if isnan (x) |
return x; |
z = fabsl (x); |
if (z == 1.0L) |
{ |
errno = ERANGE; |
return (x > 0 ? INFINITY : -INFINITY); |
} |
if ( z > 1.0L) |
{ |
errno = EDOM; |
return nanl(""); |
} |
/* Rearrange formula to avoid precision loss for small x. |
atanh(x) = 0.5 * log ((1.0 + x)/(1.0 - x)) |
= 0.5 * log1p ((1.0 + x)/(1.0 - x) - 1.0) |
= 0.5 * log1p ((1.0 + x - 1.0 + x) /(1.0 - x)) |
= 0.5 * log1p ((2.0 * x ) / (1.0 - x)) */ |
z = 0.5L * __fast_log1pl ((z + z) / (1.0L - z)); |
return x >= 0 ? z : -z; |
} |
/programs/develop/libraries/newlib/math/atanl.c |
---|
0,0 → 1,19 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
*/ |
#include <math.h> |
long double |
atanl (long double x) |
{ |
long double res; |
asm ("fld1\n\t" |
"fpatan" |
: "=t" (res) : "0" (x)); |
return res; |
} |
/programs/develop/libraries/newlib/math/cbrt.c |
---|
0,0 → 1,162 |
/* cbrt.c |
* |
* Cube root |
* |
* |
* |
* SYNOPSIS: |
* |
* double x, y, cbrt(); |
* |
* y = cbrt( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns the cube root of the argument, which may be negative. |
* |
* Range reduction involves determining the power of 2 of |
* the argument. A polynomial of degree 2 applied to the |
* mantissa, and multiplication by the cube root of 1, 2, or 4 |
* approximates the root to within about 0.1%. Then Newton's |
* iteration is used three times to converge to an accurate |
* result. |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* DEC -10,10 200000 1.8e-17 6.2e-18 |
* IEEE 0,1e308 30000 1.5e-16 5.0e-17 |
* |
*/ |
/* cbrt.c */ |
/* |
Cephes Math Library Release 2.2: January, 1991 |
Copyright 1984, 1991 by Stephen L. Moshier |
Direct inquiries to 30 Frost Street, Cambridge, MA 02140 |
*/ |
/* |
Modified for mingwex.a |
2002-07-01 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include <math.h> |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
#endif |
static const double CBRT2 = 1.2599210498948731647672; |
static const double CBRT4 = 1.5874010519681994747517; |
static const double CBRT2I = 0.79370052598409973737585; |
static const double CBRT4I = 0.62996052494743658238361; |
#ifndef __MINGW32__ |
#ifdef ANSIPROT |
extern double frexp ( double, int * ); |
extern double ldexp ( double, int ); |
extern int isnan ( double ); |
extern int isfinite ( double ); |
#else |
double frexp(), ldexp(); |
int isnan(), isfinite(); |
#endif |
#endif |
double cbrt(x) |
double x; |
{ |
int e, rem, sign; |
double z; |
#ifdef __MINGW32__ |
if (!isfinite (x) || x == 0 ) |
return x; |
#else |
#ifdef NANS |
if( isnan(x) ) |
return x; |
#endif |
#ifdef INFINITIES |
if( !isfinite(x) ) |
return x; |
#endif |
if( x == 0 ) |
return( x ); |
#endif /* __MINGW32__ */ |
if( x > 0 ) |
sign = 1; |
else |
{ |
sign = -1; |
x = -x; |
} |
z = x; |
/* extract power of 2, leaving |
* mantissa between 0.5 and 1 |
*/ |
x = frexp( x, &e ); |
/* Approximate cube root of number between .5 and 1, |
* peak relative error = 9.2e-6 |
*/ |
x = (((-1.3466110473359520655053e-1 * x |
+ 5.4664601366395524503440e-1) * x |
- 9.5438224771509446525043e-1) * x |
+ 1.1399983354717293273738e0 ) * x |
+ 4.0238979564544752126924e-1; |
/* exponent divided by 3 */ |
if( e >= 0 ) |
{ |
rem = e; |
e /= 3; |
rem -= 3*e; |
if( rem == 1 ) |
x *= CBRT2; |
else if( rem == 2 ) |
x *= CBRT4; |
} |
/* argument less than 1 */ |
else |
{ |
e = -e; |
rem = e; |
e /= 3; |
rem -= 3*e; |
if( rem == 1 ) |
x *= CBRT2I; |
else if( rem == 2 ) |
x *= CBRT4I; |
e = -e; |
} |
/* multiply by power of 2 */ |
x = ldexp( x, e ); |
/* Newton iteration */ |
x -= ( x - (z/(x*x)) )*0.33333333333333333333; |
#ifdef DEC |
x -= ( x - (z/(x*x)) )/3.0; |
#else |
x -= ( x - (z/(x*x)) )*0.33333333333333333333; |
#endif |
if( sign < 0 ) |
x = -x; |
return(x); |
} |
/programs/develop/libraries/newlib/math/cbrtf.c |
---|
0,0 → 1,147 |
/* cbrtf.c |
* |
* Cube root |
* |
* |
* |
* SYNOPSIS: |
* |
* float x, y, cbrtf(); |
* |
* y = cbrtf( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns the cube root of the argument, which may be negative. |
* |
* Range reduction involves determining the power of 2 of |
* the argument. A polynomial of degree 2 applied to the |
* mantissa, and multiplication by the cube root of 1, 2, or 4 |
* approximates the root to within about 0.1%. Then Newton's |
* iteration is used to converge to an accurate result. |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE 0,1e38 100000 7.6e-8 2.7e-8 |
* |
*/ |
/* cbrt.c */ |
/* |
Cephes Math Library Release 2.2: June, 1992 |
Copyright 1984, 1987, 1988, 1992 by Stephen L. Moshier |
Direct inquiries to 30 Frost Street, Cambridge, MA 02140 |
*/ |
/* |
Modified for mingwex.a |
2002-07-01 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include <math.h> |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
#endif |
static const float CBRT2 = 1.25992104989487316477; |
static const float CBRT4 = 1.58740105196819947475; |
#ifndef __MINGW32__ |
#ifdef ANSIC |
float frexpf(float, int *), ldexpf(float, int); |
float cbrtf( float xx ) |
#else |
float frexpf(), ldexpf(); |
float cbrtf(xx) |
double xx; |
#endif |
{ |
int e, rem, sign; |
float x, z; |
x = xx; |
#else /* __MINGW32__ */ |
float cbrtf (float x) |
{ |
int e, rem, sign; |
float z; |
#endif /* __MINGW32__ */ |
#ifdef __MINGW32__ |
if (!isfinite (x) || x == 0.0F ) |
return x; |
#else |
if( x == 0 ) |
return( 0.0 ); |
#endif |
if( x > 0 ) |
sign = 1; |
else |
{ |
sign = -1; |
x = -x; |
} |
z = x; |
/* extract power of 2, leaving |
* mantissa between 0.5 and 1 |
*/ |
x = frexpf( x, &e ); |
/* Approximate cube root of number between .5 and 1, |
* peak relative error = 9.2e-6 |
*/ |
x = (((-0.13466110473359520655053 * x |
+ 0.54664601366395524503440 ) * x |
- 0.95438224771509446525043 ) * x |
+ 1.1399983354717293273738 ) * x |
+ 0.40238979564544752126924; |
/* exponent divided by 3 */ |
if( e >= 0 ) |
{ |
rem = e; |
e /= 3; |
rem -= 3*e; |
if( rem == 1 ) |
x *= CBRT2; |
else if( rem == 2 ) |
x *= CBRT4; |
} |
/* argument less than 1 */ |
else |
{ |
e = -e; |
rem = e; |
e /= 3; |
rem -= 3*e; |
if( rem == 1 ) |
x /= CBRT2; |
else if( rem == 2 ) |
x /= CBRT4; |
e = -e; |
} |
/* multiply by power of 2 */ |
x = ldexpf( x, e ); |
/* Newton iteration */ |
x -= ( x - (z/(x*x)) ) * 0.333333333333; |
if( sign < 0 ) |
x = -x; |
return(x); |
} |
/programs/develop/libraries/newlib/math/cbrtl.c |
---|
0,0 → 1,161 |
/* cbrtl.c |
* |
* Cube root, long double precision |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, cbrtl(); |
* |
* y = cbrtl( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns the cube root of the argument, which may be negative. |
* |
* Range reduction involves determining the power of 2 of |
* the argument. A polynomial of degree 2 applied to the |
* mantissa, and multiplication by the cube root of 1, 2, or 4 |
* approximates the root to within about 0.1%. Then Newton's |
* iteration is used three times to converge to an accurate |
* result. |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE .125,8 80000 7.0e-20 2.2e-20 |
* IEEE exp(+-707) 100000 7.0e-20 2.4e-20 |
* |
*/ |
/* |
Cephes Math Library Release 2.2: January, 1991 |
Copyright 1984, 1991 by Stephen L. Moshier |
Direct inquiries to 30 Frost Street, Cambridge, MA 02140 |
*/ |
/* |
Modified for mingwex.a |
2002-07-01 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
#endif |
static const long double CBRT2 = 1.2599210498948731647672L; |
static const long double CBRT4 = 1.5874010519681994747517L; |
static const long double CBRT2I = 0.79370052598409973737585L; |
static const long double CBRT4I = 0.62996052494743658238361L; |
#ifndef __MINGW32__ |
#ifdef ANSIPROT |
extern long double frexpl ( long double, int * ); |
extern long double ldexpl ( long double, int ); |
extern int isnanl ( long double ); |
#else |
long double frexpl(), ldexpl(); |
extern int isnanl(); |
#endif |
#ifdef INFINITIES |
extern long double INFINITYL; |
#endif |
#endif /* __MINGW32__ */ |
long double cbrtl(x) |
long double x; |
{ |
int e, rem, sign; |
long double z; |
#ifdef __MINGW32__ |
if (!isfinite (x) || x == 0.0L) |
return(x); |
#else |
#ifdef NANS |
if(isnanl(x)) |
return(x); |
#endif |
#ifdef INFINITIES |
if( x == INFINITYL) |
return(x); |
if( x == -INFINITYL) |
return(x); |
#endif |
if( x == 0 ) |
return( x ); |
#endif /* __MINGW32__ */ |
if( x > 0 ) |
sign = 1; |
else |
{ |
sign = -1; |
x = -x; |
} |
z = x; |
/* extract power of 2, leaving |
* mantissa between 0.5 and 1 |
*/ |
x = frexpl( x, &e ); |
/* Approximate cube root of number between .5 and 1, |
* peak relative error = 1.2e-6 |
*/ |
x = (((( 1.3584464340920900529734e-1L * x |
- 6.3986917220457538402318e-1L) * x |
+ 1.2875551670318751538055e0L) * x |
- 1.4897083391357284957891e0L) * x |
+ 1.3304961236013647092521e0L) * x |
+ 3.7568280825958912391243e-1L; |
/* exponent divided by 3 */ |
if( e >= 0 ) |
{ |
rem = e; |
e /= 3; |
rem -= 3*e; |
if( rem == 1 ) |
x *= CBRT2; |
else if( rem == 2 ) |
x *= CBRT4; |
} |
else |
{ /* argument less than 1 */ |
e = -e; |
rem = e; |
e /= 3; |
rem -= 3*e; |
if( rem == 1 ) |
x *= CBRT2I; |
else if( rem == 2 ) |
x *= CBRT4I; |
e = -e; |
} |
/* multiply by power of 2 */ |
x = ldexpl( x, e ); |
/* Newton iteration */ |
x -= ( x - (z/(x*x)) )*0.3333333333333333333333L; |
x -= ( x - (z/(x*x)) )*0.3333333333333333333333L; |
if( sign < 0 ) |
x = -x; |
return(x); |
} |
/programs/develop/libraries/newlib/math/ceil.S |
---|
0,0 → 1,31 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "ceil.s" |
.text |
.align 4 |
.globl _ceil |
.def _ceil; .scl 2; .type 32; .endef |
_ceil: |
fldl 4(%esp) |
subl $8,%esp |
fstcw 4(%esp) /* store fpu control word */ |
/* We use here %edx although only the low 1 bits are defined. |
But none of the operations should care and they are faster |
than the 16 bit operations. */ |
movl $0x0800,%edx /* round towards +oo */ |
orl 4(%esp),%edx |
andl $0xfbff,%edx |
movl %edx,(%esp) |
fldcw (%esp) /* load modified control word */ |
frndint /* round */ |
fldcw 4(%esp) /* restore original control word */ |
addl $8,%esp |
ret |
/programs/develop/libraries/newlib/math/ceilf.S |
---|
0,0 → 1,31 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "ceilf.S" |
.text |
.align 4 |
.globl _ceilf |
.def _ceilf; .scl 2; .type 32; .endef |
_ceilf: |
flds 4(%esp) |
subl $8,%esp |
fstcw 4(%esp) /* store fpu control word */ |
/* We use here %edx although only the low 1 bits are defined. |
But none of the operations should care and they are faster |
than the 16 bit operations. */ |
movl $0x0800,%edx /* round towards +oo */ |
orl 4(%esp),%edx |
andl $0xfbff,%edx |
movl %edx,(%esp) |
fldcw (%esp) /* load modified control word */ |
frndint /* round */ |
fldcw 4(%esp) /* restore original control word */ |
addl $8,%esp |
ret |
/programs/develop/libraries/newlib/math/ceill.S |
---|
0,0 → 1,33 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
*/ |
.file "ceill.S" |
.text |
.align 4 |
.globl _ceill |
.def _ceill; .scl 2; .type 32; .endef |
_ceill: |
fldt 4(%esp) |
subl $8,%esp |
fstcw 4(%esp) /* store fpu control word */ |
/* We use here %edx although only the low 1 bits are defined. |
But none of the operations should care and they are faster |
than the 16 bit operations. */ |
movl $0x0800,%edx /* round towards +oo */ |
orl 4(%esp),%edx |
andl $0xfbff,%edx |
movl %edx,(%esp) |
fldcw (%esp) /* load modified control word */ |
frndint /* round */ |
fldcw 4(%esp) /* restore original control word */ |
addl $8,%esp |
ret |
/programs/develop/libraries/newlib/math/cephes_mconf.h |
---|
0,0 → 1,395 |
#include <math.h> |
#include <errno.h> |
#define IBMPC 1 |
#define ANSIPROT 1 |
#define MINUSZERO 1 |
#define INFINITIES 1 |
#define NANS 1 |
#define DENORMAL 1 |
#define VOLATILE |
#define mtherr(fname, code) |
#define XPD 0, |
//#define _CEPHES_USE_ERRNO |
#ifdef _CEPHES_USE_ERRNO |
#define _SET_ERRNO(x) errno = (x) |
#else |
#define _SET_ERRNO(x) |
#endif |
/* constants used by cephes functions */ |
/* double */ |
#define MAXNUM 1.7976931348623158E308 |
#define MAXLOG 7.09782712893383996843E2 |
#define MINLOG -7.08396418532264106224E2 |
#define LOGE2 6.93147180559945309417E-1 |
#define LOG2E 1.44269504088896340736 |
#define PI 3.14159265358979323846 |
#define PIO2 1.57079632679489661923 |
#define PIO4 7.85398163397448309616E-1 |
#define NEGZERO (-0.0) |
#undef NAN |
#undef INFINITY |
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)) |
#define INFINITY __builtin_huge_val() |
#define NAN __builtin_nan("") |
#else |
extern double __INF; |
#define INFINITY (__INF) |
extern double __QNAN; |
#define NAN (__QNAN) |
#endif |
/*long double*/ |
#define MAXNUML 1.189731495357231765021263853E4932L |
#define MAXLOGL 1.1356523406294143949492E4L |
#define MINLOGL -1.13994985314888605586758E4L |
#define LOGE2L 6.9314718055994530941723E-1L |
#define LOG2EL 1.4426950408889634073599E0L |
#define PIL 3.1415926535897932384626L |
#define PIO2L 1.5707963267948966192313L |
#define PIO4L 7.8539816339744830961566E-1L |
#define isfinitel isfinite |
#define isinfl isinf |
#define isnanl isnan |
#define signbitl signbit |
#define NEGZEROL (-0.0L) |
#undef NANL |
#undef INFINITYL |
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)) |
#define INFINITYL __builtin_huge_vall() |
#define NANL __builtin_nanl("") |
#else |
extern long double __INFL; |
#define INFINITYL (__INFL) |
extern long double __QNANL; |
#define NANL (__QNANL) |
#endif |
/* float */ |
#define MAXNUMF 3.4028234663852885981170418348451692544e38F |
#define MAXLOGF 88.72283905206835F |
#define MINLOGF -103.278929903431851103F /* log(2^-149) */ |
#define LOG2EF 1.44269504088896341F |
#define LOGE2F 0.693147180559945309F |
#define PIF 3.141592653589793238F |
#define PIO2F 1.5707963267948966192F |
#define PIO4F 0.7853981633974483096F |
#define isfinitef isfinite |
#define isinff isinf |
#define isnanf isnan |
#define signbitf signbit |
#define NEGZEROF (-0.0F) |
#undef NANF |
#undef INFINITYF |
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)) |
#define INFINITYF __builtin_huge_valf() |
#define NANF __builtin_nanf("") |
#else |
extern float __INFF; |
#define INFINITYF (__INFF) |
extern float __QNANF; |
#define NANF (__QNANF) |
#endif |
/* double */ |
/* |
Cephes Math Library Release 2.2: July, 1992 |
Copyright 1984, 1987, 1988, 1992 by Stephen L. Moshier |
Direct inquiries to 30 Frost Street, Cambridge, MA 02140 |
*/ |
/* polevl.c |
* p1evl.c |
* |
* Evaluate polynomial |
* |
* |
* |
* SYNOPSIS: |
* |
* int N; |
* double x, y, coef[N+1], polevl[]; |
* |
* y = polevl( x, coef, N ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Evaluates polynomial of degree N: |
* |
* 2 N |
* y = C + C x + C x +...+ C x |
* 0 1 2 N |
* |
* Coefficients are stored in reverse order: |
* |
* coef[0] = C , ..., coef[N] = C . |
* N 0 |
* |
* The function p1evl() assumes that coef[N] = 1.0 and is |
* omitted from the array. Its calling arguments are |
* otherwise the same as polevl(). |
* |
* |
* SPEED: |
* |
* In the interest of speed, there are no checks for out |
* of bounds arithmetic. This routine is used by most of |
* the functions in the library. Depending on available |
* equipment features, the user may wish to rewrite the |
* program in microcode or assembly language. |
* |
*/ |
/* Polynomial evaluator: |
* P[0] x^n + P[1] x^(n-1) + ... + P[n] |
*/ |
static __inline__ double polevl( x, p, n ) |
double x; |
const void *p; |
int n; |
{ |
register double y; |
register double *P = (double *)p; |
y = *P++; |
do |
{ |
y = y * x + *P++; |
} |
while( --n ); |
return(y); |
} |
/* Polynomial evaluator: |
* x^n + P[0] x^(n-1) + P[1] x^(n-2) + ... + P[n] |
*/ |
static __inline__ double p1evl( x, p, n ) |
double x; |
const void *p; |
int n; |
{ |
register double y; |
register double *P = (double *)p; |
n -= 1; |
y = x + *P++; |
do |
{ |
y = y * x + *P++; |
} |
while( --n ); |
return( y ); |
} |
/* long double */ |
/* |
Cephes Math Library Release 2.2: July, 1992 |
Copyright 1984, 1987, 1988, 1992 by Stephen L. Moshier |
Direct inquiries to 30 Frost Street, Cambridge, MA 02140 |
*/ |
/* polevll.c |
* p1evll.c |
* |
* Evaluate polynomial |
* |
* |
* |
* SYNOPSIS: |
* |
* int N; |
* long double x, y, coef[N+1], polevl[]; |
* |
* y = polevll( x, coef, N ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Evaluates polynomial of degree N: |
* |
* 2 N |
* y = C + C x + C x +...+ C x |
* 0 1 2 N |
* |
* Coefficients are stored in reverse order: |
* |
* coef[0] = C , ..., coef[N] = C . |
* N 0 |
* |
* The function p1evll() assumes that coef[N] = 1.0 and is |
* omitted from the array. Its calling arguments are |
* otherwise the same as polevll(). |
* |
* |
* SPEED: |
* |
* In the interest of speed, there are no checks for out |
* of bounds arithmetic. This routine is used by most of |
* the functions in the library. Depending on available |
* equipment features, the user may wish to rewrite the |
* program in microcode or assembly language. |
* |
*/ |
/* Polynomial evaluator: |
* P[0] x^n + P[1] x^(n-1) + ... + P[n] |
*/ |
static __inline__ long double polevll( x, p, n ) |
long double x; |
const void *p; |
int n; |
{ |
register long double y; |
register long double *P = (long double *)p; |
y = *P++; |
do |
{ |
y = y * x + *P++; |
} |
while( --n ); |
return(y); |
} |
/* Polynomial evaluator: |
* x^n + P[0] x^(n-1) + P[1] x^(n-2) + ... + P[n] |
*/ |
static __inline__ long double p1evll( x, p, n ) |
long double x; |
const void *p; |
int n; |
{ |
register long double y; |
register long double *P = (long double *)p; |
n -= 1; |
y = x + *P++; |
do |
{ |
y = y * x + *P++; |
} |
while( --n ); |
return( y ); |
} |
/* Float version */ |
/* polevlf.c |
* p1evlf.c |
* |
* Evaluate polynomial |
* |
* |
* |
* SYNOPSIS: |
* |
* int N; |
* float x, y, coef[N+1], polevlf[]; |
* |
* y = polevlf( x, coef, N ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Evaluates polynomial of degree N: |
* |
* 2 N |
* y = C + C x + C x +...+ C x |
* 0 1 2 N |
* |
* Coefficients are stored in reverse order: |
* |
* coef[0] = C , ..., coef[N] = C . |
* N 0 |
* |
* The function p1evl() assumes that coef[N] = 1.0 and is |
* omitted from the array. Its calling arguments are |
* otherwise the same as polevl(). |
* |
* |
* SPEED: |
* |
* In the interest of speed, there are no checks for out |
* of bounds arithmetic. This routine is used by most of |
* the functions in the library. Depending on available |
* equipment features, the user may wish to rewrite the |
* program in microcode or assembly language. |
* |
*/ |
/* |
Cephes Math Library Release 2.1: December, 1988 |
Copyright 1984, 1987, 1988 by Stephen L. Moshier |
Direct inquiries to 30 Frost Street, Cambridge, MA 02140 |
*/ |
static __inline__ float polevlf(float x, const float* coef, int N ) |
{ |
float ans; |
float *p; |
int i; |
p = (float*)coef; |
ans = *p++; |
/* |
for( i=0; i<N; i++ ) |
ans = ans * x + *p++; |
*/ |
i = N; |
do |
ans = ans * x + *p++; |
while( --i ); |
return( ans ); |
} |
/* p1evl() */ |
/* N |
* Evaluate polynomial when coefficient of x is 1.0. |
* Otherwise same as polevl. |
*/ |
static __inline__ float p1evlf( float x, const float *coef, int N ) |
{ |
float ans; |
float *p; |
int i; |
p = (float*)coef; |
ans = x + *p++; |
i = N-1; |
do |
ans = ans * x + *p++; |
while( --i ); |
return( ans ); |
} |
/programs/develop/libraries/newlib/math/copysign.S |
---|
0,0 → 1,19 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "copysign.S" |
.text |
.align 4 |
.globl _copysign |
.def _copysign; .scl 2; .type 32; .endef |
_copysign: |
movl 16(%esp),%edx |
movl 8(%esp),%eax |
andl $0x80000000,%edx |
andl $0x7fffffff,%eax |
orl %edx,%eax |
movl %eax,8(%esp) |
fldl 4(%esp) |
ret |
/programs/develop/libraries/newlib/math/copysignf.S |
---|
0,0 → 1,19 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "copysignf.S" |
.text |
.align 4 |
.globl _copysignf |
.def _copysignf; .scl 2; .type 32; .endef |
_copysignf: |
movl 8(%esp),%edx |
movl 4(%esp),%eax |
andl $0x80000000,%edx |
andl $0x7fffffff,%eax |
orl %edx,%eax |
movl %eax,4(%esp) |
flds 4(%esp) |
ret |
/programs/develop/libraries/newlib/math/copysignl.S |
---|
0,0 → 1,20 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* Public domain. |
*/ |
.file "copysignl.S" |
.text |
.align 4 |
.globl _copysignl |
.def _copysignl; .scl 2; .type 32; .endef |
_copysignl: |
movl 24(%esp),%edx |
movl 12(%esp),%eax |
andl $0x8000,%edx |
andl $0x7fff,%eax |
orl %edx,%eax |
movl %eax,12(%esp) |
fldt 4(%esp) |
ret |
/programs/develop/libraries/newlib/math/cos.S |
---|
0,0 → 1,29 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Removed glibc header dependancy by Danny Smith |
* <dannysmith@users.sourceforge.net> |
*/ |
.file "cos.s" |
.text |
.align 4 |
.globl _cos |
.def _cos; .scl 2; .type 32; .endef |
_cos: |
fldl 4(%esp) |
fcos |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fnstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fcos |
ret |
/programs/develop/libraries/newlib/math/cosf.S |
---|
0,0 → 1,29 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Removed glibc header dependancy by Danny Smith |
* <dannysmith@users.sourceforge.net> |
*/ |
.file "cosf.S" |
.text |
.align 4 |
.globl _cosl |
.def _cosf; .scl 2; .type 32; .endef |
_cosf: |
flds 4(%esp) |
fcos |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fnstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fcos |
ret |
/programs/develop/libraries/newlib/math/coshf.c |
---|
0,0 → 1,3 |
#include <math.h> |
float coshf (float x) |
{return (float) cosh (x);} |
/programs/develop/libraries/newlib/math/coshl.c |
---|
0,0 → 1,110 |
/* coshl.c |
* |
* Hyperbolic cosine, long double precision |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, coshl(); |
* |
* y = coshl( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns hyperbolic cosine of argument in the range MINLOGL to |
* MAXLOGL. |
* |
* cosh(x) = ( exp(x) + exp(-x) )/2. |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE +-10000 30000 1.1e-19 2.8e-20 |
* |
* |
* ERROR MESSAGES: |
* |
* message condition value returned |
* cosh overflow |x| > MAXLOGL+LOGE2L INFINITYL |
* |
* |
*/ |
/* |
Cephes Math Library Release 2.7: May, 1998 |
Copyright 1985, 1991, 1998 by Stephen L. Moshier |
*/ |
/* |
Modified for mingw |
2002-07-22 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
#endif |
#ifndef _SET_ERRNO |
#define _SET_ERRNO(x) |
#endif |
#ifndef __MINGW32__ |
extern long double MAXLOGL, MAXNUML, LOGE2L; |
#ifdef ANSIPROT |
extern long double expl ( long double ); |
extern int isnanl ( long double ); |
#else |
long double expl(), isnanl(); |
#endif |
#ifdef INFINITIES |
extern long double INFINITYL; |
#endif |
#ifdef NANS |
extern long double NANL; |
#endif |
#endif /* __MINGW32__ */ |
long double coshl(x) |
long double x; |
{ |
long double y; |
#ifdef NANS |
if( isnanl(x) ) |
{ |
_SET_ERRNO(EDOM); |
return(x); |
} |
#endif |
if( x < 0 ) |
x = -x; |
if( x > (MAXLOGL + LOGE2L) ) |
{ |
mtherr( "coshl", OVERFLOW ); |
_SET_ERRNO(ERANGE); |
#ifdef INFINITIES |
return( INFINITYL ); |
#else |
return( MAXNUML ); |
#endif |
} |
if( x >= (MAXLOGL - LOGE2L) ) |
{ |
y = expl(0.5L * x); |
y = (0.5L * y) * y; |
return(y); |
} |
y = expl(x); |
y = 0.5L * (y + 1.0L / y); |
return( y ); |
} |
/programs/develop/libraries/newlib/math/cosl.S |
---|
0,0 → 1,30 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
* Removed glibc header dependancy by Danny Smith |
* <dannysmith@users.sourceforge.net> |
*/ |
.file "cosl.S" |
.text |
.align 4 |
.globl _cosl |
.def _cosl; .scl 2; .type 32; .endef |
_cosl: |
fldt 4(%esp) |
fcos |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fnstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fcos |
ret |
/programs/develop/libraries/newlib/math/double.h |
---|
0,0 → 1,265 |
/* Software floating-point emulation. |
Definitions for IEEE Double Precision |
Copyright (C) 1997, 1998, 1999, 2006, 2007, 2008, 2009 |
Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz), |
David S. Miller (davem@redhat.com) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
#if _FP_W_TYPE_SIZE < 32 |
#error "Here's a nickel kid. Go buy yourself a real computer." |
#endif |
#if _FP_W_TYPE_SIZE < 64 |
#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE) |
#else |
#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE |
#endif |
#define _FP_FRACBITS_D 53 |
#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D) |
#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D) |
#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D) |
#define _FP_EXPBITS_D 11 |
#define _FP_EXPBIAS_D 1023 |
#define _FP_EXPMAX_D 2047 |
#define _FP_QNANBIT_D \ |
((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE) |
#define _FP_QNANBIT_SH_D \ |
((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE) |
#define _FP_IMPLBIT_D \ |
((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE) |
#define _FP_IMPLBIT_SH_D \ |
((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE) |
#define _FP_OVERFLOW_D \ |
((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE) |
typedef float DFtype __attribute__((mode(DF))); |
#if _FP_W_TYPE_SIZE < 64 |
union _FP_UNION_D |
{ |
DFtype flt; |
struct { |
#if __BYTE_ORDER == __BIG_ENDIAN |
unsigned sign : 1; |
unsigned exp : _FP_EXPBITS_D; |
unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; |
unsigned frac0 : _FP_W_TYPE_SIZE; |
#else |
unsigned frac0 : _FP_W_TYPE_SIZE; |
unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; |
unsigned exp : _FP_EXPBITS_D; |
unsigned sign : 1; |
#endif |
} bits __attribute__((packed)); |
}; |
#define FP_DECL_D(X) _FP_DECL(2,X) |
#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val) |
#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_2_P(D,X,val) |
#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X) |
#define FP_PACK_RAW_DP(val,X) \ |
do { \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_2_P(D,val,X); \ |
} while (0) |
#define FP_UNPACK_D(X,val) \ |
do { \ |
_FP_UNPACK_RAW_2(D,X,val); \ |
_FP_UNPACK_CANONICAL(D,2,X); \ |
} while (0) |
#define FP_UNPACK_DP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_2_P(D,X,val); \ |
_FP_UNPACK_CANONICAL(D,2,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_D(X,val) \ |
do { \ |
_FP_UNPACK_RAW_2(D,X,val); \ |
_FP_UNPACK_SEMIRAW(D,2,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_DP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_2_P(D,X,val); \ |
_FP_UNPACK_SEMIRAW(D,2,X); \ |
} while (0) |
#define FP_PACK_D(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(D,2,X); \ |
_FP_PACK_RAW_2(D,val,X); \ |
} while (0) |
#define FP_PACK_DP(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(D,2,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_2_P(D,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_D(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(D,2,X); \ |
_FP_PACK_RAW_2(D,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_DP(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(D,2,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_2_P(D,val,X); \ |
} while (0) |
#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,2,X) |
#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X) |
#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y) |
#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y) |
#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y) |
#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y) |
#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X) |
#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q) |
#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un) |
#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y) |
#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,2,r,X,Y) |
#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg) |
#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt) |
#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2(X) |
#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2(X) |
#else |
union _FP_UNION_D |
{ |
DFtype flt; |
struct { |
#if __BYTE_ORDER == __BIG_ENDIAN |
unsigned sign : 1; |
unsigned exp : _FP_EXPBITS_D; |
_FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); |
#else |
_FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); |
unsigned exp : _FP_EXPBITS_D; |
unsigned sign : 1; |
#endif |
} bits __attribute__((packed)); |
}; |
#define FP_DECL_D(X) _FP_DECL(1,X) |
#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val) |
#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_1_P(D,X,val) |
#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X) |
#define FP_PACK_RAW_DP(val,X) \ |
do { \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_1_P(D,val,X); \ |
} while (0) |
#define FP_UNPACK_D(X,val) \ |
do { \ |
_FP_UNPACK_RAW_1(D,X,val); \ |
_FP_UNPACK_CANONICAL(D,1,X); \ |
} while (0) |
#define FP_UNPACK_DP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_1_P(D,X,val); \ |
_FP_UNPACK_CANONICAL(D,1,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_D(X,val) \ |
do { \ |
_FP_UNPACK_RAW_1(D,X,val); \ |
_FP_UNPACK_SEMIRAW(D,1,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_DP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_1_P(D,X,val); \ |
_FP_UNPACK_SEMIRAW(D,1,X); \ |
} while (0) |
#define FP_PACK_D(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(D,1,X); \ |
_FP_PACK_RAW_1(D,val,X); \ |
} while (0) |
#define FP_PACK_DP(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(D,1,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_1_P(D,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_D(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(D,1,X); \ |
_FP_PACK_RAW_1(D,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_DP(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(D,1,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_1_P(D,val,X); \ |
} while (0) |
#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,1,X) |
#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X) |
#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y) |
#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y) |
#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y) |
#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y) |
#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X) |
#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q) |
/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by |
the target machine. */ |
#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un) |
#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y) |
#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,1,r,X,Y) |
#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg) |
#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt) |
#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1(X) |
#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X) |
#endif /* W_TYPE_SIZE < 64 */ |
/programs/develop/libraries/newlib/math/e_atan2.c |
---|
0,0 → 1,131 |
/* @(#)e_atan2.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
* |
* Developed at SunPro, a Sun Microsystems, Inc. business. |
* Permission to use, copy, modify, and distribute this |
* software is freely granted, provided that this notice |
* is preserved. |
* ==================================================== |
* |
*/ |
/* __ieee754_atan2(y,x) |
* Method : |
* 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). |
* 2. Reduce x to positive by (if x and y are unexceptional): |
* ARG (x+iy) = arctan(y/x) ... if x > 0, |
* ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, |
* |
* Special cases: |
* |
* ATAN2((anything), NaN ) is NaN; |
* ATAN2(NAN , (anything) ) is NaN; |
* ATAN2(+-0, +(anything but NaN)) is +-0 ; |
* ATAN2(+-0, -(anything but NaN)) is +-pi ; |
* ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; |
* ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; |
* ATAN2(+-(anything but INF and NaN), -INF) is +-pi; |
* ATAN2(+-INF,+INF ) is +-pi/4 ; |
* ATAN2(+-INF,-INF ) is +-3pi/4; |
* ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; |
* |
* Constants: |
* The hexadecimal values are the intended ones for the following |
* constants. The decimal values may be used, provided that the |
* compiler will convert from decimal to binary accurately enough |
* to produce the hexadecimal values shown. |
*/ |
#include "fdlibm.h" |
#ifndef _DOUBLE_IS_32BITS |
#ifdef __STDC__ |
static const double |
#else |
static double |
#endif |
tiny = 1.0e-300, |
zero = 0.0, |
pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ |
pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ |
pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ |
pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ |
#ifdef __STDC__ |
double __ieee754_atan2(double y, double x) |
#else |
double __ieee754_atan2(y,x) |
double y,x; |
#endif |
{ |
double z; |
__int32_t k,m,hx,hy,ix,iy; |
__uint32_t lx,ly; |
EXTRACT_WORDS(hx,lx,x); |
ix = hx&0x7fffffff; |
EXTRACT_WORDS(hy,ly,y); |
iy = hy&0x7fffffff; |
if(((ix|((lx|-lx)>>31))>0x7ff00000)|| |
((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */ |
return x+y; |
if((hx-0x3ff00000|lx)==0) return atan(y); /* x=1.0 */ |
m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ |
/* when y = 0 */ |
if((iy|ly)==0) { |
switch(m) { |
case 0: |
case 1: return y; /* atan(+-0,+anything)=+-0 */ |
case 2: return pi+tiny;/* atan(+0,-anything) = pi */ |
case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ |
} |
} |
/* when x = 0 */ |
if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; |
/* when x is INF */ |
if(ix==0x7ff00000) { |
if(iy==0x7ff00000) { |
switch(m) { |
case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ |
case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ |
case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ |
case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ |
} |
} else { |
switch(m) { |
case 0: return zero ; /* atan(+...,+INF) */ |
case 1: return -zero ; /* atan(-...,+INF) */ |
case 2: return pi+tiny ; /* atan(+...,-INF) */ |
case 3: return -pi-tiny ; /* atan(-...,-INF) */ |
} |
} |
} |
/* when y is INF */ |
if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; |
/* compute y/x */ |
k = (iy-ix)>>20; |
if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */ |
else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */ |
else z=atan(fabs(y/x)); /* safe to do y/x */ |
switch (m) { |
case 0: return z ; /* atan(+,+) */ |
case 1: { |
__uint32_t zh; |
GET_HIGH_WORD(zh,z); |
SET_HIGH_WORD(z,zh ^ 0x80000000); |
} |
return z ; /* atan(-,+) */ |
case 2: return pi-(z-pi_lo);/* atan(+,-) */ |
default: /* case 3 */ |
return (z-pi_lo)-pi;/* atan(-,-) */ |
} |
} |
#endif /* defined(_DOUBLE_IS_32BITS) */ |
/programs/develop/libraries/newlib/math/e_cosh.c |
---|
0,0 → 1,90 |
/* @(#)e_cosh.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
* |
* Developed at SunPro, a Sun Microsystems, Inc. business. |
* Permission to use, copy, modify, and distribute this |
* software is freely granted, provided that this notice |
* is preserved. |
* ==================================================== |
*/ |
/* __ieee754_cosh(x) |
* Method : |
* mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 |
* 1. Replace x by |x| (cosh(x) = cosh(-x)). |
* 2. |
* [ exp(x) - 1 ]^2 |
* 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- |
* 2*exp(x) |
* |
* exp(x) + 1/exp(x) |
* ln2/2 <= x <= 22 : cosh(x) := ------------------- |
* 2 |
* 22 <= x <= lnovft : cosh(x) := exp(x)/2 |
* lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) |
* ln2ovft < x : cosh(x) := huge*huge (overflow) |
* |
* Special cases: |
* cosh(x) is |x| if x is +INF, -INF, or NaN. |
* only cosh(0)=1 is exact for finite x. |
*/ |
#include "fdlibm.h" |
#ifdef __STDC__ |
static const double one = 1.0, half=0.5, huge = 1.0e300; |
#else |
static double one = 1.0, half=0.5, huge = 1.0e300; |
#endif |
#ifdef __STDC__ |
double cosh(double x) |
#else |
double cosh(x) |
double x; |
#endif |
{ |
double t,w; |
__int32_t ix; |
__uint32_t lx; |
/* High word of |x|. */ |
GET_HIGH_WORD(ix,x); |
ix &= 0x7fffffff; |
/* x is INF or NaN */ |
if(ix>=0x7ff00000) return x*x; |
/* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ |
if(ix<0x3fd62e43) { |
t = expm1(fabs(x)); |
w = one+t; |
if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ |
return one+(t*t)/(w+w); |
} |
/* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ |
if (ix < 0x40360000) { |
t = exp(fabs(x)); |
return half*t+half/t; |
} |
/* |x| in [22, log(maxdouble)] return half*exp(|x|) */ |
if (ix < 0x40862E42) return half*exp(fabs(x)); |
/* |x| in [log(maxdouble), overflowthresold] */ |
GET_LOW_WORD(lx,x); |
if (ix<0x408633CE || |
(ix==0x408633ce && lx<=(__uint32_t)0x8fb9f87d)) { |
w = exp(half*fabs(x)); |
t = half*w; |
return t*w; |
} |
/* |x| > overflowthresold, cosh(x) overflow */ |
return huge*huge; |
} |
/programs/develop/libraries/newlib/math/e_hypot.c |
---|
0,0 → 1,128 |
/* @(#)e_hypot.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
* |
* Developed at SunPro, a Sun Microsystems, Inc. business. |
* Permission to use, copy, modify, and distribute this |
* software is freely granted, provided that this notice |
* is preserved. |
* ==================================================== |
*/ |
/* __ieee754_hypot(x,y) |
* |
* Method : |
* If (assume round-to-nearest) z=x*x+y*y |
* has error less than sqrt(2)/2 ulp, than |
* sqrt(z) has error less than 1 ulp (exercise). |
* |
* So, compute sqrt(x*x+y*y) with some care as |
* follows to get the error below 1 ulp: |
* |
* Assume x>y>0; |
* (if possible, set rounding to round-to-nearest) |
* 1. if x > 2y use |
* x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y |
* where x1 = x with lower 32 bits cleared, x2 = x-x1; else |
* 2. if x <= 2y use |
* t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) |
* where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, |
* y1= y with lower 32 bits chopped, y2 = y-y1. |
* |
* NOTE: scaling may be necessary if some argument is too |
* large or too tiny |
* |
* Special cases: |
* hypot(x,y) is INF if x or y is +INF or -INF; else |
* hypot(x,y) is NAN if x or y is NAN. |
* |
* Accuracy: |
* hypot(x,y) returns sqrt(x^2+y^2) with error less |
* than 1 ulps (units in the last place) |
*/ |
#include "fdlibm.h" |
#ifndef _DOUBLE_IS_32BITS |
#ifdef __STDC__ |
double __ieee754_hypot(double x, double y) |
#else |
double __ieee754_hypot(x,y) |
double x, y; |
#endif |
{ |
double a=x,b=y,t1,t2,y1,y2,w; |
__int32_t j,k,ha,hb; |
GET_HIGH_WORD(ha,x); |
ha &= 0x7fffffff; |
GET_HIGH_WORD(hb,y); |
hb &= 0x7fffffff; |
if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} |
SET_HIGH_WORD(a,ha); /* a <- |a| */ |
SET_HIGH_WORD(b,hb); /* b <- |b| */ |
if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */ |
k=0; |
if(ha > 0x5f300000) { /* a>2**500 */ |
if(ha >= 0x7ff00000) { /* Inf or NaN */ |
__uint32_t low; |
w = a+b; /* for sNaN */ |
GET_LOW_WORD(low,a); |
if(((ha&0xfffff)|low)==0) w = a; |
GET_LOW_WORD(low,b); |
if(((hb^0x7ff00000)|low)==0) w = b; |
return w; |
} |
/* scale a and b by 2**-600 */ |
ha -= 0x25800000; hb -= 0x25800000; k += 600; |
SET_HIGH_WORD(a,ha); |
SET_HIGH_WORD(b,hb); |
} |
if(hb < 0x20b00000) { /* b < 2**-500 */ |
if(hb <= 0x000fffff) { /* subnormal b or 0 */ |
__uint32_t low; |
GET_LOW_WORD(low,b); |
if((hb|low)==0) return a; |
t1=0; |
SET_HIGH_WORD(t1,0x7fd00000); /* t1=2^1022 */ |
b *= t1; |
a *= t1; |
k -= 1022; |
} else { /* scale a and b by 2^600 */ |
ha += 0x25800000; /* a *= 2^600 */ |
hb += 0x25800000; /* b *= 2^600 */ |
k -= 600; |
SET_HIGH_WORD(a,ha); |
SET_HIGH_WORD(b,hb); |
} |
} |
/* medium size a and b */ |
w = a-b; |
if (w>b) { |
t1 = 0; |
SET_HIGH_WORD(t1,ha); |
t2 = a-t1; |
w = __ieee754_sqrt(t1*t1-(b*(-b)-t2*(a+t1))); |
} else { |
a = a+a; |
y1 = 0; |
SET_HIGH_WORD(y1,hb); |
y2 = b - y1; |
t1 = 0; |
SET_HIGH_WORD(t1,ha+0x00100000); |
t2 = a - t1; |
w = __ieee754_sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); |
} |
if(k!=0) { |
__uint32_t high; |
t1 = 1.0; |
GET_HIGH_WORD(high,t1); |
SET_HIGH_WORD(t1,high+(k<<20)); |
return t1*w; |
} else return w; |
} |
#endif /* defined(_DOUBLE_IS_32BITS) */ |
/programs/develop/libraries/newlib/math/e_sinh.c |
---|
0,0 → 1,83 |
/* @(#)e_sinh.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
* |
* Developed at SunPro, a Sun Microsystems, Inc. business. |
* Permission to use, copy, modify, and distribute this |
* software is freely granted, provided that this notice |
* is preserved. |
* ==================================================== |
*/ |
/* __ieee754_sinh(x) |
* Method : |
* mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 |
* 1. Replace x by |x| (sinh(-x) = -sinh(x)). |
* 2. |
* E + E/(E+1) |
* 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) |
* 2 |
* |
* 22 <= x <= lnovft : sinh(x) := exp(x)/2 |
* lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) |
* ln2ovft < x : sinh(x) := x*shuge (overflow) |
* |
* Special cases: |
* sinh(x) is |x| if x is +INF, -INF, or NaN. |
* only sinh(0)=0 is exact for finite x. |
*/ |
#include "fdlibm.h" |
#ifdef __STDC__ |
static const double one = 1.0, shuge = 1.0e307; |
#else |
static double one = 1.0, shuge = 1.0e307; |
#endif |
#ifdef __STDC__ |
double sinh(double x) |
#else |
double sinh(x) |
double x; |
#endif |
{ |
double t,w,h; |
__int32_t ix,jx; |
__uint32_t lx; |
/* High word of |x|. */ |
GET_HIGH_WORD(jx,x); |
ix = jx&0x7fffffff; |
/* x is INF or NaN */ |
if(ix>=0x7ff00000) return x+x; |
h = 0.5; |
if (jx<0) h = -h; |
/* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ |
if (ix < 0x40360000) { /* |x|<22 */ |
if (ix<0x3e300000) /* |x|<2**-28 */ |
if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ |
t = expm1(fabs(x)); |
if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one)); |
return h*(t+t/(t+one)); |
} |
/* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ |
if (ix < 0x40862E42) return h * exp(fabs(x)); |
/* |x| in [log(maxdouble), overflowthresold] */ |
GET_LOW_WORD(lx,x); |
if (ix<0x408633CE || (ix==0x408633ce && lx<=(__uint32_t)0x8fb9f87d)) { |
w = exp(0.5*fabs(x)); |
t = h*w; |
return t*w; |
} |
/* |x| > overflowthresold, sinh(x) overflow */ |
return x*shuge; |
} |
/programs/develop/libraries/newlib/math/e_sqrt.c |
---|
0,0 → 1,452 |
/* @(#)e_sqrt.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
* |
* Developed at SunPro, a Sun Microsystems, Inc. business. |
* Permission to use, copy, modify, and distribute this |
* software is freely granted, provided that this notice |
* is preserved. |
* ==================================================== |
*/ |
/* __ieee754_sqrt(x) |
* Return correctly rounded sqrt. |
* ------------------------------------------ |
* | Use the hardware sqrt if you have one | |
* ------------------------------------------ |
* Method: |
* Bit by bit method using integer arithmetic. (Slow, but portable) |
* 1. Normalization |
* Scale x to y in [1,4) with even powers of 2: |
* find an integer k such that 1 <= (y=x*2^(2k)) < 4, then |
* sqrt(x) = 2^k * sqrt(y) |
* 2. Bit by bit computation |
* Let q = sqrt(y) truncated to i bit after binary point (q = 1), |
* i 0 |
* i+1 2 |
* s = 2*q , and y = 2 * ( y - q ). (1) |
* i i i i |
* |
* To compute q from q , one checks whether |
* i+1 i |
* |
* -(i+1) 2 |
* (q + 2 ) <= y. (2) |
* i |
* -(i+1) |
* If (2) is false, then q = q ; otherwise q = q + 2 . |
* i+1 i i+1 i |
* |
* With some algebric manipulation, it is not difficult to see |
* that (2) is equivalent to |
* -(i+1) |
* s + 2 <= y (3) |
* i i |
* |
* The advantage of (3) is that s and y can be computed by |
* i i |
* the following recurrence formula: |
* if (3) is false |
* |
* s = s , y = y ; (4) |
* i+1 i i+1 i |
* |
* otherwise, |
* -i -(i+1) |
* s = s + 2 , y = y - s - 2 (5) |
* i+1 i i+1 i i |
* |
* One may easily use induction to prove (4) and (5). |
* Note. Since the left hand side of (3) contain only i+2 bits, |
* it does not necessary to do a full (53-bit) comparison |
* in (3). |
* 3. Final rounding |
* After generating the 53 bits result, we compute one more bit. |
* Together with the remainder, we can decide whether the |
* result is exact, bigger than 1/2ulp, or less than 1/2ulp |
* (it will never equal to 1/2ulp). |
* The rounding mode can be detected by checking whether |
* huge + tiny is equal to huge, and whether huge - tiny is |
* equal to huge for some floating point number "huge" and "tiny". |
* |
* Special cases: |
* sqrt(+-0) = +-0 ... exact |
* sqrt(inf) = inf |
* sqrt(-ve) = NaN ... with invalid signal |
* sqrt(NaN) = NaN ... with invalid signal for signaling NaN |
* |
* Other methods : see the appended file at the end of the program below. |
*--------------- |
*/ |
#include "fdlibm.h" |
#ifndef _DOUBLE_IS_32BITS |
#ifdef __STDC__ |
static const double one = 1.0, tiny=1.0e-300; |
#else |
static double one = 1.0, tiny=1.0e-300; |
#endif |
#ifdef __STDC__ |
double __ieee754_sqrt(double x) |
#else |
double __ieee754_sqrt(x) |
double x; |
#endif |
{ |
double z; |
__int32_t sign = (int)0x80000000; |
__uint32_t r,t1,s1,ix1,q1; |
__int32_t ix0,s0,q,m,t,i; |
EXTRACT_WORDS(ix0,ix1,x); |
/* take care of Inf and NaN */ |
if((ix0&0x7ff00000)==0x7ff00000) { |
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf |
sqrt(-inf)=sNaN */ |
} |
/* take care of zero */ |
if(ix0<=0) { |
if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ |
else if(ix0<0) |
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ |
} |
/* normalize x */ |
m = (ix0>>20); |
if(m==0) { /* subnormal x */ |
while(ix0==0) { |
m -= 21; |
ix0 |= (ix1>>11); ix1 <<= 21; |
} |
for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; |
m -= i-1; |
ix0 |= (ix1>>(32-i)); |
ix1 <<= i; |
} |
m -= 1023; /* unbias exponent */ |
ix0 = (ix0&0x000fffff)|0x00100000; |
if(m&1){ /* odd m, double x to make it even */ |
ix0 += ix0 + ((ix1&sign)>>31); |
ix1 += ix1; |
} |
m >>= 1; /* m = [m/2] */ |
/* generate sqrt(x) bit by bit */ |
ix0 += ix0 + ((ix1&sign)>>31); |
ix1 += ix1; |
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ |
r = 0x00200000; /* r = moving bit from right to left */ |
while(r!=0) { |
t = s0+r; |
if(t<=ix0) { |
s0 = t+r; |
ix0 -= t; |
q += r; |
} |
ix0 += ix0 + ((ix1&sign)>>31); |
ix1 += ix1; |
r>>=1; |
} |
r = sign; |
while(r!=0) { |
t1 = s1+r; |
t = s0; |
if((t<ix0)||((t==ix0)&&(t1<=ix1))) { |
s1 = t1+r; |
if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; |
ix0 -= t; |
if (ix1 < t1) ix0 -= 1; |
ix1 -= t1; |
q1 += r; |
} |
ix0 += ix0 + ((ix1&sign)>>31); |
ix1 += ix1; |
r>>=1; |
} |
/* use floating add to find out rounding direction */ |
if((ix0|ix1)!=0) { |
z = one-tiny; /* trigger inexact flag */ |
if (z>=one) { |
z = one+tiny; |
if (q1==(__uint32_t)0xffffffff) { q1=0; q += 1;} |
else if (z>one) { |
if (q1==(__uint32_t)0xfffffffe) q+=1; |
q1+=2; |
} else |
q1 += (q1&1); |
} |
} |
ix0 = (q>>1)+0x3fe00000; |
ix1 = q1>>1; |
if ((q&1)==1) ix1 |= sign; |
ix0 += (m <<20); |
INSERT_WORDS(z,ix0,ix1); |
return z; |
} |
#endif /* defined(_DOUBLE_IS_32BITS) */ |
/* |
Other methods (use floating-point arithmetic) |
------------- |
(This is a copy of a drafted paper by Prof W. Kahan |
and K.C. Ng, written in May, 1986) |
Two algorithms are given here to implement sqrt(x) |
(IEEE double precision arithmetic) in software. |
Both supply sqrt(x) correctly rounded. The first algorithm (in |
Section A) uses newton iterations and involves four divisions. |
The second one uses reciproot iterations to avoid division, but |
requires more multiplications. Both algorithms need the ability |
to chop results of arithmetic operations instead of round them, |
and the INEXACT flag to indicate when an arithmetic operation |
is executed exactly with no roundoff error, all part of the |
standard (IEEE 754-1985). The ability to perform shift, add, |
subtract and logical AND operations upon 32-bit words is needed |
too, though not part of the standard. |
A. sqrt(x) by Newton Iteration |
(1) Initial approximation |
Let x0 and x1 be the leading and the trailing 32-bit words of |
a floating point number x (in IEEE double format) respectively |
1 11 52 ...widths |
------------------------------------------------------ |
x: |s| e | f | |
------------------------------------------------------ |
msb lsb msb lsb ...order |
------------------------ ------------------------ |
x0: |s| e | f1 | x1: | f2 | |
------------------------ ------------------------ |
By performing shifts and subtracts on x0 and x1 (both regarded |
as integers), we obtain an 8-bit approximation of sqrt(x) as |
follows. |
k := (x0>>1) + 0x1ff80000; |
y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits |
Here k is a 32-bit integer and T1[] is an integer array containing |
correction terms. Now magically the floating value of y (y's |
leading 32-bit word is y0, the value of its trailing word is 0) |
approximates sqrt(x) to almost 8-bit. |
Value of T1: |
static int T1[32]= { |
0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, |
29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, |
83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, |
16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; |
(2) Iterative refinement |
Apply Heron's rule three times to y, we have y approximates |
sqrt(x) to within 1 ulp (Unit in the Last Place): |
y := (y+x/y)/2 ... almost 17 sig. bits |
y := (y+x/y)/2 ... almost 35 sig. bits |
y := y-(y-x/y)/2 ... within 1 ulp |
Remark 1. |
Another way to improve y to within 1 ulp is: |
y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) |
y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) |
2 |
(x-y )*y |
y := y + 2* ---------- ...within 1 ulp |
2 |
3y + x |
This formula has one division fewer than the one above; however, |
it requires more multiplications and additions. Also x must be |
scaled in advance to avoid spurious overflow in evaluating the |
expression 3y*y+x. Hence it is not recommended uless division |
is slow. If division is very slow, then one should use the |
reciproot algorithm given in section B. |
(3) Final adjustment |
By twiddling y's last bit it is possible to force y to be |
correctly rounded according to the prevailing rounding mode |
as follows. Let r and i be copies of the rounding mode and |
inexact flag before entering the square root program. Also we |
use the expression y+-ulp for the next representable floating |
numbers (up and down) of y. Note that y+-ulp = either fixed |
point y+-1, or multiply y by nextafter(1,+-inf) in chopped |
mode. |
I := FALSE; ... reset INEXACT flag I |
R := RZ; ... set rounding mode to round-toward-zero |
z := x/y; ... chopped quotient, possibly inexact |
If(not I) then { ... if the quotient is exact |
if(z=y) { |
I := i; ... restore inexact flag |
R := r; ... restore rounded mode |
return sqrt(x):=y. |
} else { |
z := z - ulp; ... special rounding |
} |
} |
i := TRUE; ... sqrt(x) is inexact |
If (r=RN) then z=z+ulp ... rounded-to-nearest |
If (r=RP) then { ... round-toward-+inf |
y = y+ulp; z=z+ulp; |
} |
y := y+z; ... chopped sum |
y0:=y0-0x00100000; ... y := y/2 is correctly rounded. |
I := i; ... restore inexact flag |
R := r; ... restore rounded mode |
return sqrt(x):=y. |
(4) Special cases |
Square root of +inf, +-0, or NaN is itself; |
Square root of a negative number is NaN with invalid signal. |
B. sqrt(x) by Reciproot Iteration |
(1) Initial approximation |
Let x0 and x1 be the leading and the trailing 32-bit words of |
a floating point number x (in IEEE double format) respectively |
(see section A). By performing shifs and subtracts on x0 and y0, |
we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. |
k := 0x5fe80000 - (x0>>1); |
y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits |
Here k is a 32-bit integer and T2[] is an integer array |
containing correction terms. Now magically the floating |
value of y (y's leading 32-bit word is y0, the value of |
its trailing word y1 is set to zero) approximates 1/sqrt(x) |
to almost 7.8-bit. |
Value of T2: |
static int T2[64]= { |
0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, |
0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, |
0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, |
0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, |
0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, |
0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, |
0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, |
0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; |
(2) Iterative refinement |
Apply Reciproot iteration three times to y and multiply the |
result by x to get an approximation z that matches sqrt(x) |
to about 1 ulp. To be exact, we will have |
-1ulp < sqrt(x)-z<1.0625ulp. |
... set rounding mode to Round-to-nearest |
y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) |
y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) |
... special arrangement for better accuracy |
z := x*y ... 29 bits to sqrt(x), with z*y<1 |
z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) |
Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that |
(a) the term z*y in the final iteration is always less than 1; |
(b) the error in the final result is biased upward so that |
-1 ulp < sqrt(x) - z < 1.0625 ulp |
instead of |sqrt(x)-z|<1.03125ulp. |
(3) Final adjustment |
By twiddling y's last bit it is possible to force y to be |
correctly rounded according to the prevailing rounding mode |
as follows. Let r and i be copies of the rounding mode and |
inexact flag before entering the square root program. Also we |
use the expression y+-ulp for the next representable floating |
numbers (up and down) of y. Note that y+-ulp = either fixed |
point y+-1, or multiply y by nextafter(1,+-inf) in chopped |
mode. |
R := RZ; ... set rounding mode to round-toward-zero |
switch(r) { |
case RN: ... round-to-nearest |
if(x<= z*(z-ulp)...chopped) z = z - ulp; else |
if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; |
break; |
case RZ:case RM: ... round-to-zero or round-to--inf |
R:=RP; ... reset rounding mod to round-to-+inf |
if(x<z*z ... rounded up) z = z - ulp; else |
if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; |
break; |
case RP: ... round-to-+inf |
if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else |
if(x>z*z ...chopped) z = z+ulp; |
break; |
} |
Remark 3. The above comparisons can be done in fixed point. For |
example, to compare x and w=z*z chopped, it suffices to compare |
x1 and w1 (the trailing parts of x and w), regarding them as |
two's complement integers. |
...Is z an exact square root? |
To determine whether z is an exact square root of x, let z1 be the |
trailing part of z, and also let x0 and x1 be the leading and |
trailing parts of x. |
If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 |
I := 1; ... Raise Inexact flag: z is not exact |
else { |
j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 |
k := z1 >> 26; ... get z's 25-th and 26-th |
fraction bits |
I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); |
} |
R:= r ... restore rounded mode |
return sqrt(x):=z. |
If multiplication is cheaper then the foregoing red tape, the |
Inexact flag can be evaluated by |
I := i; |
I := (z*z!=x) or I. |
Note that z*z can overwrite I; this value must be sensed if it is |
True. |
Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be |
zero. |
-------------------- |
z1: | f2 | |
-------------------- |
bit 31 bit 0 |
Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd |
or even of logb(x) have the following relations: |
------------------------------------------------- |
bit 27,26 of z1 bit 1,0 of x1 logb(x) |
------------------------------------------------- |
00 00 odd and even |
01 01 even |
10 10 odd |
10 00 even |
11 01 even |
------------------------------------------------- |
(4) Special cases (see (4) of Section A). |
*/ |
/programs/develop/libraries/newlib/math/erfl.c |
---|
0,0 → 1,299 |
/* erfl.c |
* |
* Error function |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, erfl(); |
* |
* y = erfl( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* The integral is |
* |
* x |
* - |
* 2 | | 2 |
* erf(x) = -------- | exp( - t ) dt. |
* sqrt(pi) | | |
* - |
* 0 |
* |
* The magnitude of x is limited to about 106.56 for IEEE |
* arithmetic; 1 or -1 is returned outside this range. |
* |
* For 0 <= |x| < 1, erf(x) = x * P6(x^2)/Q6(x^2); |
* Otherwise: erf(x) = 1 - erfc(x). |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE 0,1 50000 2.0e-19 5.7e-20 |
* |
*/ |
/* erfcl.c |
* |
* Complementary error function |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, erfcl(); |
* |
* y = erfcl( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* |
* 1 - erf(x) = |
* |
* inf. |
* - |
* 2 | | 2 |
* erfc(x) = -------- | exp( - t ) dt |
* sqrt(pi) | | |
* - |
* x |
* |
* |
* For small x, erfc(x) = 1 - erf(x); otherwise rational |
* approximations are computed. |
* |
* A special function expx2l.c is used to suppress error amplification |
* in computing exp(-x^2). |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE 0,13 50000 8.4e-19 9.7e-20 |
* IEEE 6,106.56 20000 2.9e-19 7.1e-20 |
* |
* |
* ERROR MESSAGES: |
* |
* message condition value returned |
* erfcl underflow x^2 > MAXLOGL 0.0 |
* |
* |
*/ |
/* |
Modified from file ndtrl.c |
Cephes Math Library Release 2.3: January, 1995 |
Copyright 1984, 1995 by Stephen L. Moshier |
*/ |
#include <math.h> |
#include "cephes_mconf.h" |
/* erfc(x) = exp(-x^2) P(1/x)/Q(1/x) |
1/8 <= 1/x <= 1 |
Peak relative error 5.8e-21 */ |
static const unsigned short P[] = { |
0x4bf0,0x9ad8,0x7a03,0x86c7,0x401d, XPD |
0xdf23,0xd843,0x4032,0x8881,0x401e, XPD |
0xd025,0xcfd5,0x8494,0x88d3,0x401e, XPD |
0xb6d0,0xc92b,0x5417,0xacb1,0x401d, XPD |
0xada8,0x356a,0x4982,0x94a6,0x401c, XPD |
0x4e13,0xcaee,0x9e31,0xb258,0x401a, XPD |
0x5840,0x554d,0x37a3,0x9239,0x4018, XPD |
0x3b58,0x3da2,0xaf02,0x9780,0x4015, XPD |
0x0144,0x489e,0xbe68,0x9c31,0x4011, XPD |
0x333b,0xd9e6,0xd404,0x986f,0xbfee, XPD |
}; |
static const unsigned short Q[] = { |
/* 0x0000,0x0000,0x0000,0x8000,0x3fff, XPD */ |
0x0e43,0x302d,0x79ed,0x86c7,0x401d, XPD |
0xf817,0x9128,0xc0f8,0xd48b,0x401e, XPD |
0x8eae,0x8dad,0x6eb4,0x9aa2,0x401f, XPD |
0x00e7,0x7595,0xcd06,0x88bb,0x401f, XPD |
0x4991,0xcfda,0x52f1,0xa2a9,0x401e, XPD |
0xc39d,0xe415,0xc43d,0x87c0,0x401d, XPD |
0xa75d,0x436f,0x30dd,0xa027,0x401b, XPD |
0xc4cb,0x305a,0xbf78,0x8220,0x4019, XPD |
0x3708,0x33b1,0x07fa,0x8644,0x4016, XPD |
0x24fa,0x96f6,0x7153,0x8a6c,0x4012, XPD |
}; |
/* erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2) |
1/128 <= 1/x < 1/8 |
Peak relative error 1.9e-21 */ |
static const unsigned short R[] = { |
0x260a,0xab95,0x2fc7,0xe7c4,0x4000, XPD |
0x4761,0x613e,0xdf6d,0xe58e,0x4001, XPD |
0x0615,0x4b00,0x575f,0xdc7b,0x4000, XPD |
0x521d,0x8527,0x3435,0x8dc2,0x3ffe, XPD |
0x22cf,0xc711,0x6c5b,0xdcfb,0x3ff9, XPD |
}; |
static const unsigned short S[] = { |
/* 0x0000,0x0000,0x0000,0x8000,0x3fff, XPD */ |
0x5de6,0x17d7,0x54d6,0xaba9,0x4002, XPD |
0x55d5,0xd300,0xe71e,0xf564,0x4002, XPD |
0xb611,0x8f76,0xf020,0xd255,0x4001, XPD |
0x3684,0x3798,0xb793,0x80b0,0x3fff, XPD |
0xf5af,0x2fb2,0x1e57,0xc3d7,0x3ffa, XPD |
}; |
/* erf(x) = x T(x^2)/U(x^2) |
0 <= x <= 1 |
Peak relative error 7.6e-23 */ |
static const unsigned short T[] = { |
0xfd7a,0x3a1a,0x705b,0xe0c4,0x3ffb, XPD |
0x3128,0xc337,0x3716,0xace5,0x4001, XPD |
0x9517,0x4e93,0x540e,0x8f97,0x4007, XPD |
0x6118,0x6059,0x9093,0xa757,0x400a, XPD |
0xb954,0xa987,0xc60c,0xbc83,0x400e, XPD |
0x7a56,0xe45a,0xa4bd,0x975b,0x4010, XPD |
0xc446,0x6bab,0x0b2a,0x86d0,0x4013, XPD |
}; |
static const unsigned short U[] = { |
/* 0x0000,0x0000,0x0000,0x8000,0x3fff, XPD */ |
0x3453,0x1f8e,0xf688,0xb507,0x4004, XPD |
0x71ac,0xb12f,0x21ca,0xf2e2,0x4008, XPD |
0xffe8,0x9cac,0x3b84,0xc2ac,0x400c, XPD |
0x481d,0x445b,0xc807,0xc232,0x400f, XPD |
0x9ad5,0x1aef,0x45b1,0xe25e,0x4011, XPD |
0x71a7,0x1cad,0x012e,0xeef3,0x4012, XPD |
}; |
/* expx2l.c |
* |
* Exponential of squared argument |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, expmx2l(); |
* int sign; |
* |
* y = expx2l( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Computes y = exp(x*x) while suppressing error amplification |
* that would ordinarily arise from the inexactness of the |
* exponential argument x*x. |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE -106.566, 106.566 10^5 1.6e-19 4.4e-20 |
* |
*/ |
#define M 32768.0L |
#define MINV 3.0517578125e-5L |
static long double expx2l (long double x) |
{ |
long double u, u1, m, f; |
x = fabsl (x); |
/* Represent x as an exact multiple of M plus a residual. |
M is a power of 2 chosen so that exp(m * m) does not overflow |
or underflow and so that |x - m| is small. */ |
m = MINV * floorl(M * x + 0.5L); |
f = x - m; |
/* x^2 = m^2 + 2mf + f^2 */ |
u = m * m; |
u1 = 2 * m * f + f * f; |
if ((u+u1) > MAXLOGL) |
return (INFINITYL); |
/* u is exact, u1 is small. */ |
u = expl(u) * expl(u1); |
return(u); |
} |
long double erfcl(long double a) |
{ |
long double p,q,x,y,z; |
if (isinf (a)) |
return (signbit (a) ? 2.0 : 0.0); |
x = fabsl (a); |
if (x < 1.0L) |
return (1.0L - erfl(a)); |
z = a * a; |
if( z > MAXLOGL ) |
{ |
under: |
mtherr( "erfcl", UNDERFLOW ); |
errno = ERANGE; |
return (signbit (a) ? 2.0 : 0.0); |
} |
/* Compute z = expl(a * a). */ |
z = expx2l (a); |
y = 1.0L/x; |
if (x < 8.0L) |
{ |
p = polevll (y, P, 9); |
q = p1evll (y, Q, 10); |
} |
else |
{ |
q = y * y; |
p = y * polevll (q, R, 4); |
q = p1evll (q, S, 5); |
} |
y = p/(q * z); |
if (a < 0.0L) |
y = 2.0L - y; |
if (y == 0.0L) |
goto under; |
return (y); |
} |
long double erfl(long double x) |
{ |
long double y, z; |
if( x == 0.0L ) |
return (x); |
if (isinf (x)) |
return (signbit (x) ? -1.0L : 1.0L); |
if (fabsl(x) > 1.0L) |
return (1.0L - erfcl (x)); |
z = x * x; |
y = x * polevll( z, T, 6 ) / p1evll( z, U, 6 ); |
return( y ); |
} |
/programs/develop/libraries/newlib/math/exp.S |
---|
0,0 → 1,49 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
/* e^x = 2^(x * log2(e)) */ |
.file "exp.s" |
.text |
.p2align 4,,15 |
.globl _exp |
.def _exp; .scl 2; .type 32; .endef |
_exp: |
fldl 4(%esp) |
/* I added the following ugly construct because exp(+-Inf) resulted |
in NaN. The ugliness results from the bright minds at Intel. |
For the i686 the code can be written better. |
-- drepper@cygnus.com. */ |
fxam /* Is NaN or +-Inf? */ |
fstsw %ax |
movb $0x45, %dh |
andb %ah, %dh |
cmpb $0x05, %dh |
je 1f /* Is +-Inf, jump. */ |
fldl2e |
fmulp /* x * log2(e) */ |
fld %st |
frndint /* int(x * log2(e)) */ |
fsubr %st,%st(1) /* fract(x * log2(e)) */ |
fxch |
f2xm1 /* 2^(fract(x * log2(e))) - 1 */ |
fld1 |
faddp /* 2^(fract(x * log2(e))) */ |
fscale /* e^x */ |
fstp %st(1) |
ret |
1: |
testl $0x200, %eax /* Test sign. */ |
jz 2f /* If positive, jump. */ |
fstp %st |
fldz /* Set result to 0. */ |
2: |
ret |
/programs/develop/libraries/newlib/math/exp2.S |
---|
0,0 → 1,39 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Adapted for exp2 by Ulrich Drepper <drepper@cygnus.com>. |
* Public domain. |
*/ |
.file "exp2.S" |
.text |
.align 4 |
.globl _exp2 |
.def _exp2; .scl 2; .type 32; .endef |
_exp2: |
fldl 4(%esp) |
/* I added the following ugly construct because exp(+-Inf) resulted |
in NaN. The ugliness results from the bright minds at Intel. |
For the i686 the code can be written better. |
-- drepper@cygnus.com. */ |
fxam /* Is NaN or +-Inf? */ |
fstsw %ax |
movb $0x45, %dh |
andb %ah, %dh |
cmpb $0x05, %dh |
je 1f /* Is +-Inf, jump. */ |
fld %st |
frndint /* int(x) */ |
fsubr %st,%st(1) /* fract(x) */ |
fxch |
f2xm1 /* 2^(fract(x)) - 1 */ |
fld1 |
faddp /* 2^(fract(x)) */ |
fscale /* e^x */ |
fstp %st(1) |
ret |
1: testl $0x200, %eax /* Test sign. */ |
jz 2f /* If positive, jump. */ |
fstp %st |
fldz /* Set result to 0. */ |
2: ret |
/programs/develop/libraries/newlib/math/exp2f.S |
---|
0,0 → 1,39 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Adapted for exp2 by Ulrich Drepper <drepper@cygnus.com>. |
* Public domain. |
*/ |
.file "exp2f.S" |
.text |
.align 4 |
.globl _exp2f |
.def _exp2f; .scl 2; .type 32; .endef |
_exp2f: |
flds 4(%esp) |
/* I added the following ugly construct because exp(+-Inf) resulted |
in NaN. The ugliness results from the bright minds at Intel. |
For the i686 the code can be written better. |
-- drepper@cygnus.com. */ |
fxam /* Is NaN or +-Inf? */ |
fstsw %ax |
movb $0x45, %dh |
andb %ah, %dh |
cmpb $0x05, %dh |
je 1f /* Is +-Inf, jump. */ |
fld %st |
frndint /* int(x) */ |
fsubr %st,%st(1) /* fract(x) */ |
fxch |
f2xm1 /* 2^(fract(x)) - 1 */ |
fld1 |
faddp /* 2^(fract(x)) */ |
fscale /* e^x */ |
fstp %st(1) |
ret |
1: testl $0x200, %eax /* Test sign. */ |
jz 2f /* If positive, jump. */ |
fstp %st |
fldz /* Set result to 0. */ |
2: ret |
/programs/develop/libraries/newlib/math/exp2l.S |
---|
0,0 → 1,39 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Adapted for exp2 by Ulrich Drepper <drepper@cygnus.com>. |
* Public domain. |
*/ |
.file "exp2l.S" |
.text |
.align 4 |
.globl _exp2l |
.def _exp2l; .scl 2; .type 32; .endef |
_exp2l: |
fldt 4(%esp) |
/* I added the following ugly construct because exp(+-Inf) resulted |
in NaN. The ugliness results from the bright minds at Intel. |
For the i686 the code can be written better. |
-- drepper@cygnus.com. */ |
fxam /* Is NaN or +-Inf? */ |
fstsw %ax |
movb $0x45, %dh |
andb %ah, %dh |
cmpb $0x05, %dh |
je 1f /* Is +-Inf, jump. */ |
fld %st |
frndint /* int(x) */ |
fsubr %st,%st(1) /* fract(x) */ |
fxch |
f2xm1 /* 2^(fract(x)) - 1 */ |
fld1 |
faddp /* 2^(fract(x)) */ |
fscale /* e^x */ |
fstp %st(1) |
ret |
1: testl $0x200, %eax /* Test sign. */ |
jz 2f /* If positive, jump. */ |
fstp %st |
fldz /* Set result to 0. */ |
2: ret |
/programs/develop/libraries/newlib/math/expf.c |
---|
0,0 → 1,3 |
#include <math.h> |
float expf (float x) |
{return (float) exp (x);} |
/programs/develop/libraries/newlib/math/expl.c |
---|
0,0 → 1,71 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
*/ |
/* |
* The 8087 method for the exponential function is to calculate |
* exp(x) = 2^(x log2(e)) |
* after separating integer and fractional parts |
* x log2(e) = i + f, |f| <= .5 |
* 2^i is immediate but f needs to be precise for long double accuracy. |
* Suppress range reduction error in computing f by the following. |
* Separate x into integer and fractional parts |
* x = xi + xf, |xf| <= .5 |
* Separate log2(e) into the sum of an exact number c0 and small part c1. |
* c0 + c1 = log2(e) to extra precision |
* Then |
* f = (c0 xi - i) + c0 xf + c1 x |
* where c0 xi is exact and so also is (c0 xi - i). |
* -- moshier@na-net.ornl.gov |
*/ |
#include <math.h> |
#include "cephes_mconf.h" /* for max and min log thresholds */ |
static long double c0 = 1.44268798828125L; |
static long double c1 = 7.05260771340735992468e-6L; |
static long double |
__expl (long double x) |
{ |
long double res; |
asm ("fldl2e\n\t" /* 1 log2(e) */ |
"fmul %%st(1),%%st\n\t" /* 1 x log2(e) */ |
"frndint\n\t" /* 1 i */ |
"fld %%st(1)\n\t" /* 2 x */ |
"frndint\n\t" /* 2 xi */ |
"fld %%st(1)\n\t" /* 3 i */ |
"fldt %2\n\t" /* 4 c0 */ |
"fld %%st(2)\n\t" /* 5 xi */ |
"fmul %%st(1),%%st\n\t" /* 5 c0 xi */ |
"fsubp %%st,%%st(2)\n\t" /* 4 f = c0 xi - i */ |
"fld %%st(4)\n\t" /* 5 x */ |
"fsub %%st(3),%%st\n\t" /* 5 xf = x - xi */ |
"fmulp %%st,%%st(1)\n\t" /* 4 c0 xf */ |
"faddp %%st,%%st(1)\n\t" /* 3 f = f + c0 xf */ |
"fldt %3\n\t" /* 4 */ |
"fmul %%st(4),%%st\n\t" /* 4 c1 * x */ |
"faddp %%st,%%st(1)\n\t" /* 3 f = f + c1 * x */ |
"f2xm1\n\t" /* 3 2^(fract(x * log2(e))) - 1 */ |
"fld1\n\t" /* 4 1.0 */ |
"faddp\n\t" /* 3 2^(fract(x * log2(e))) */ |
"fstp %%st(1)\n\t" /* 2 */ |
"fscale\n\t" /* 2 scale factor is st(1); e^x */ |
"fstp %%st(1)\n\t" /* 1 */ |
"fstp %%st(1)\n\t" /* 0 */ |
: "=t" (res) : "0" (x), "m" (c0), "m" (c1) : "ax", "dx"); |
return res; |
} |
long double expl (long double x) |
{ |
if (x > MAXLOGL) |
return INFINITY; |
else if (x < MINLOGL) |
return 0.0L; |
else |
return __expl (x); |
} |
/programs/develop/libraries/newlib/math/expm1.c |
---|
0,0 → 1,28 |
/* |
* Written 2005 by Gregory W. Chicares <chicares@cox.net>. |
* Adapted to double by Danny Smith <dannysmith@users.sourceforge.net>. |
* Public domain. |
* |
* F2XM1's input is constrained to (-1, +1), so the domain of |
* 'x * LOG2EL' is (-LOGE2L, +LOGE2L). Outside that domain, |
* delegating to exp() handles C99 7.12.6.3/2 range errors. |
* |
* Constants from moshier.net, file cephes/ldouble/constl.c, |
* are used instead of M_LN2 and M_LOG2E, which would not be |
* visible with 'gcc std=c99'. The use of these extended precision |
* constants also allows gcc to replace them with x87 opcodes. |
*/ |
#include <math.h> /* expl() */ |
#include "cephes_mconf.h" |
double expm1 (double x) |
{ |
if (fabs(x) < LOGE2L) |
{ |
x *= LOG2EL; |
__asm__("f2xm1" : "=t" (x) : "0" (x)); |
return x; |
} |
else |
return exp(x) - 1.0; |
} |
/programs/develop/libraries/newlib/math/expm1f.c |
---|
0,0 → 1,29 |
/* |
* Written 2005 by Gregory W. Chicares <chicares@cox.net>. |
* Adapted to float by Danny Smith <dannysmith@users.sourceforge.net>. |
* Public domain. |
* |
* F2XM1's input is constrained to (-1, +1), so the domain of |
* 'x * LOG2EL' is (-LOGE2L, +LOGE2L). Outside that domain, |
* delegating to exp() handles C99 7.12.6.3/2 range errors. |
* |
* Constants from moshier.net, file cephes/ldouble/constl.c, |
* are used instead of M_LN2 and M_LOG2E, which would not be |
* visible with 'gcc std=c99'. The use of these extended precision |
* constants also allows gcc to replace them with x87 opcodes. |
*/ |
#include <math.h> /* expl() */ |
#include "cephes_mconf.h" |
float expm1f (float x) |
{ |
if (fabsf(x) < LOGE2L) |
{ |
x *= LOG2EL; |
__asm__("f2xm1" : "=t" (x) : "0" (x)); |
return x; |
} |
else |
return expf(x) - 1.0F; |
} |
/programs/develop/libraries/newlib/math/expm1l.c |
---|
0,0 → 1,29 |
/* |
* Written 2005 by Gregory W. Chicares <chicares@cox.net> with |
* help from Danny Smith. dannysmith@users.sourceforge.net>. |
* Public domain. |
* |
* F2XM1's input is constrained to (-1, +1), so the domain of |
* 'x * LOG2EL' is (-LOGE2L, +LOGE2L). Outside that domain, |
* delegating to expl() handles C99 7.12.6.3/2 range errors. |
* |
* Constants from moshier.net, file cephes/ldouble/constl.c, |
* are used instead of M_LN2 and M_LOG2E, which would not be |
* visible with 'gcc std=c99'. The use of these extended precision |
* constants also allows gcc to replace them with x87 opcodes. |
*/ |
#include <math.h> /* expl() */ |
#include "cephes_mconf.h" |
long double expm1l (long double x) |
{ |
if (fabsl(x) < LOGE2L) |
{ |
x *= LOG2EL; |
__asm__("f2xm1" : "=t" (x) : "0" (x)); |
return x; |
} |
else |
return expl(x) - 1.0L; |
} |
/programs/develop/libraries/newlib/math/fabs.c |
---|
0,0 → 1,10 |
#include <math.h> |
double |
fabs (double x) |
{ |
double res; |
asm ("fabs;" : "=t" (res) : "0" (x)); |
return res; |
} |
/programs/develop/libraries/newlib/math/fabsf.c |
---|
0,0 → 1,9 |
#include <math.h> |
float |
fabsf (float x) |
{ |
float res; |
asm ("fabs;" : "=t" (res) : "0" (x)); |
return res; |
} |
/programs/develop/libraries/newlib/math/fabsl.c |
---|
0,0 → 1,9 |
#include <math.h> |
long double |
fabsl (long double x) |
{ |
long double res; |
asm ("fabs;" : "=t" (res) : "0" (x)); |
return res; |
} |
/programs/develop/libraries/newlib/math/fastmath.h |
---|
0,0 → 1,115 |
#ifndef _MINGWEX_FASTMATH_H_ |
#define _MINGWEX_FASTMATH_H_ |
/* Fast math inlines |
No range or domain checks. No setting of errno. No tweaks to |
protect precision near range limits. */ |
/* For now this is an internal header with just the functions that |
are currently used in building libmingwex.a math components */ |
/* FIXME: We really should get rid of the code duplication using euther |
C++ templates or tgmath-type macros. */ |
static __inline__ double __fast_sqrt (double x) |
{ |
double res; |
asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); |
return res; |
} |
static __inline__ long double __fast_sqrtl (long double x) |
{ |
long double res; |
asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); |
return res; |
} |
static __inline__ float __fast_sqrtf (float x) |
{ |
float res; |
asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); |
return res; |
} |
static __inline__ double __fast_log (double x) |
{ |
double res; |
asm __volatile__ |
("fldln2\n\t" |
"fxch\n\t" |
"fyl2x" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
static __inline__ long double __fast_logl (long double x) |
{ |
long double res; |
asm __volatile__ |
("fldln2\n\t" |
"fxch\n\t" |
"fyl2x" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
static __inline__ float __fast_logf (float x) |
{ |
float res; |
asm __volatile__ |
("fldln2\n\t" |
"fxch\n\t" |
"fyl2x" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
static __inline__ double __fast_log1p (double x) |
{ |
double res; |
/* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ |
if (fabs (x) >= 1.0 - 0.5 * 1.41421356237309504880) |
res = __fast_log (1.0 + x); |
else |
asm __volatile__ |
("fldln2\n\t" |
"fxch\n\t" |
"fyl2xp1" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
static __inline__ long double __fast_log1pl (long double x) |
{ |
long double res; |
/* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ |
if (fabsl (x) >= 1.0L - 0.5L * 1.41421356237309504880L) |
res = __fast_logl (1.0L + x); |
else |
asm __volatile__ |
("fldln2\n\t" |
"fxch\n\t" |
"fyl2xp1" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
static __inline__ float __fast_log1pf (float x) |
{ |
float res; |
/* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ |
if (fabsf (x) >= 1.0 - 0.5 * 1.41421356237309504880) |
res = __fast_logf (1.0 + x); |
else |
asm __volatile__ |
("fldln2\n\t" |
"fxch\n\t" |
"fyl2xp1" |
: "=t" (res) : "0" (x) : "st(1)"); |
return res; |
} |
#endif |
/programs/develop/libraries/newlib/math/fdim.c |
---|
0,0 → 1,7 |
#include <math.h> |
double |
fdim (double x, double y) |
{ |
return (isgreater(x, y) ? (x - y) : 0.0); |
} |
/programs/develop/libraries/newlib/math/fdimf.c |
---|
0,0 → 1,7 |
#include <math.h> |
float |
fdimf (float x, float y) |
{ |
return (isgreater(x, y) ? (x - y) : 0.0F); |
} |
/programs/develop/libraries/newlib/math/fdiml.c |
---|
0,0 → 1,7 |
#include <math.h> |
long double |
fdiml (long double x, long double y) |
{ |
return (isgreater(x, y) ? (x - y) : 0.0L); |
} |
/programs/develop/libraries/newlib/math/fdlibm.h |
---|
0,0 → 1,365 |
/* @(#)fdlibm.h 5.1 93/09/24 */ |
/* |
* ==================================================== |
* 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. |
* ==================================================== |
*/ |
/* REDHAT LOCAL: Include files. */ |
#include <math.h> |
#include <sys/types.h> |
#include <machine/ieeefp.h> |
/* REDHAT LOCAL: Default to XOPEN_MODE. */ |
#define _XOPEN_MODE |
/* Most routines need to check whether a float is finite, infinite, or not a |
number, and many need to know whether the result of an operation will |
overflow. These conditions depend on whether the largest exponent is |
used for NaNs & infinities, or whether it's used for finite numbers. The |
macros below wrap up that kind of information: |
FLT_UWORD_IS_FINITE(X) |
True if a positive float with bitmask X is finite. |
FLT_UWORD_IS_NAN(X) |
True if a positive float with bitmask X is not a number. |
FLT_UWORD_IS_INFINITE(X) |
True if a positive float with bitmask X is +infinity. |
FLT_UWORD_MAX |
The bitmask of FLT_MAX. |
FLT_UWORD_HALF_MAX |
The bitmask of FLT_MAX/2. |
FLT_UWORD_EXP_MAX |
The bitmask of the largest finite exponent (129 if the largest |
exponent is used for finite numbers, 128 otherwise). |
FLT_UWORD_LOG_MAX |
The bitmask of log(FLT_MAX), rounded down. This value is the largest |
input that can be passed to exp() without producing overflow. |
FLT_UWORD_LOG_2MAX |
The bitmask of log(2*FLT_MAX), rounded down. This value is the |
largest input than can be passed to cosh() without producing |
overflow. |
FLT_LARGEST_EXP |
The largest biased exponent that can be used for finite numbers |
(255 if the largest exponent is used for finite numbers, 254 |
otherwise) */ |
#ifdef _FLT_LARGEST_EXPONENT_IS_NORMAL |
#define FLT_UWORD_IS_FINITE(x) 1 |
#define FLT_UWORD_IS_NAN(x) 0 |
#define FLT_UWORD_IS_INFINITE(x) 0 |
#define FLT_UWORD_MAX 0x7fffffff |
#define FLT_UWORD_EXP_MAX 0x43010000 |
#define FLT_UWORD_LOG_MAX 0x42b2d4fc |
#define FLT_UWORD_LOG_2MAX 0x42b437e0 |
#define HUGE ((float)0X1.FFFFFEP128) |
#else |
#define FLT_UWORD_IS_FINITE(x) ((x)<0x7f800000L) |
#define FLT_UWORD_IS_NAN(x) ((x)>0x7f800000L) |
#define FLT_UWORD_IS_INFINITE(x) ((x)==0x7f800000L) |
#define FLT_UWORD_MAX 0x7f7fffffL |
#define FLT_UWORD_EXP_MAX 0x43000000 |
#define FLT_UWORD_LOG_MAX 0x42b17217 |
#define FLT_UWORD_LOG_2MAX 0x42b2d4fc |
#define HUGE ((float)3.40282346638528860e+38) |
#endif |
#define FLT_UWORD_HALF_MAX (FLT_UWORD_MAX-(1L<<23)) |
#define FLT_LARGEST_EXP (FLT_UWORD_MAX>>23) |
/* Many routines check for zero and subnormal numbers. Such things depend |
on whether the target supports denormals or not: |
FLT_UWORD_IS_ZERO(X) |
True if a positive float with bitmask X is +0. Without denormals, |
any float with a zero exponent is a +0 representation. With |
denormals, the only +0 representation is a 0 bitmask. |
FLT_UWORD_IS_SUBNORMAL(X) |
True if a non-zero positive float with bitmask X is subnormal. |
(Routines should check for zeros first.) |
FLT_UWORD_MIN |
The bitmask of the smallest float above +0. Call this number |
REAL_FLT_MIN... |
FLT_UWORD_EXP_MIN |
The bitmask of the float representation of REAL_FLT_MIN's exponent. |
FLT_UWORD_LOG_MIN |
The bitmask of |log(REAL_FLT_MIN)|, rounding down. |
FLT_SMALLEST_EXP |
REAL_FLT_MIN's exponent - EXP_BIAS (1 if denormals are not supported, |
-22 if they are). |
*/ |
#ifdef _FLT_NO_DENORMALS |
#define FLT_UWORD_IS_ZERO(x) ((x)<0x00800000L) |
#define FLT_UWORD_IS_SUBNORMAL(x) 0 |
#define FLT_UWORD_MIN 0x00800000 |
#define FLT_UWORD_EXP_MIN 0x42fc0000 |
#define FLT_UWORD_LOG_MIN 0x42aeac50 |
#define FLT_SMALLEST_EXP 1 |
#else |
#define FLT_UWORD_IS_ZERO(x) ((x)==0) |
#define FLT_UWORD_IS_SUBNORMAL(x) ((x)<0x00800000L) |
#define FLT_UWORD_MIN 0x00000001 |
#define FLT_UWORD_EXP_MIN 0x43160000 |
#define FLT_UWORD_LOG_MIN 0x42cff1b5 |
#define FLT_SMALLEST_EXP -22 |
#endif |
#ifdef __STDC__ |
#undef __P |
#define __P(p) p |
#else |
#define __P(p) () |
#endif |
/* |
* set X_TLOSS = pi*2**52, which is possibly defined in <values.h> |
* (one may replace the following line by "#include <values.h>") |
*/ |
#define X_TLOSS 1.41484755040568800000e+16 |
/* Functions that are not documented, and are not in <math.h>. */ |
extern double logb __P((double)); |
#ifdef _SCALB_INT |
extern double scalb __P((double, int)); |
#else |
extern double scalb __P((double, double)); |
#endif |
extern double significand __P((double)); |
/* ieee style elementary functions */ |
extern double __ieee754_sqrt __P((double)); |
extern double __ieee754_acos __P((double)); |
extern double __ieee754_acosh __P((double)); |
extern double __ieee754_log __P((double)); |
extern double __ieee754_atanh __P((double)); |
extern double __ieee754_asin __P((double)); |
extern double __ieee754_atan2 __P((double,double)); |
extern double __ieee754_exp __P((double)); |
extern double __ieee754_cosh __P((double)); |
extern double __ieee754_fmod __P((double,double)); |
extern double __ieee754_pow __P((double,double)); |
extern double __ieee754_lgamma_r __P((double,int *)); |
extern double __ieee754_gamma_r __P((double,int *)); |
extern double __ieee754_log10 __P((double)); |
extern double __ieee754_sinh __P((double)); |
extern double __ieee754_hypot __P((double,double)); |
extern double __ieee754_j0 __P((double)); |
extern double __ieee754_j1 __P((double)); |
extern double __ieee754_y0 __P((double)); |
extern double __ieee754_y1 __P((double)); |
extern double __ieee754_jn __P((int,double)); |
extern double __ieee754_yn __P((int,double)); |
extern double __ieee754_remainder __P((double,double)); |
extern __int32_t __ieee754_rem_pio2 __P((double,double*)); |
#ifdef _SCALB_INT |
extern double __ieee754_scalb __P((double,int)); |
#else |
extern double __ieee754_scalb __P((double,double)); |
#endif |
/* fdlibm kernel function */ |
extern double __kernel_standard __P((double,double,int)); |
extern double __kernel_sin __P((double,double,int)); |
extern double __kernel_cos __P((double,double)); |
extern double __kernel_tan __P((double,double,int)); |
extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const __int32_t*)); |
/* Undocumented float functions. */ |
extern float logbf __P((float)); |
#ifdef _SCALB_INT |
extern float scalbf __P((float, int)); |
#else |
extern float scalbf __P((float, float)); |
#endif |
extern float significandf __P((float)); |
/* ieee style elementary float functions */ |
extern float __ieee754_sqrtf __P((float)); |
extern float __ieee754_acosf __P((float)); |
extern float __ieee754_acoshf __P((float)); |
extern float __ieee754_logf __P((float)); |
extern float __ieee754_atanhf __P((float)); |
extern float __ieee754_asinf __P((float)); |
extern float __ieee754_atan2f __P((float,float)); |
extern float __ieee754_expf __P((float)); |
extern float __ieee754_coshf __P((float)); |
extern float __ieee754_fmodf __P((float,float)); |
extern float __ieee754_powf __P((float,float)); |
extern float __ieee754_lgammaf_r __P((float,int *)); |
extern float __ieee754_gammaf_r __P((float,int *)); |
extern float __ieee754_log10f __P((float)); |
extern float __ieee754_sinhf __P((float)); |
extern float __ieee754_hypotf __P((float,float)); |
extern float __ieee754_j0f __P((float)); |
extern float __ieee754_j1f __P((float)); |
extern float __ieee754_y0f __P((float)); |
extern float __ieee754_y1f __P((float)); |
extern float __ieee754_jnf __P((int,float)); |
extern float __ieee754_ynf __P((int,float)); |
extern float __ieee754_remainderf __P((float,float)); |
extern __int32_t __ieee754_rem_pio2f __P((float,float*)); |
#ifdef _SCALB_INT |
extern float __ieee754_scalbf __P((float,int)); |
#else |
extern float __ieee754_scalbf __P((float,float)); |
#endif |
/* float versions of fdlibm kernel functions */ |
extern float __kernel_sinf __P((float,float,int)); |
extern float __kernel_cosf __P((float,float)); |
extern float __kernel_tanf __P((float,float,int)); |
extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const __int32_t*)); |
/* The original code used statements like |
n0 = ((*(int*)&one)>>29)^1; * index of high word * |
ix0 = *(n0+(int*)&x); * high word of x * |
ix1 = *((1-n0)+(int*)&x); * low word of x * |
to dig two 32 bit words out of the 64 bit IEEE floating point |
value. That is non-ANSI, and, moreover, the gcc instruction |
scheduler gets it wrong. We instead use the following macros. |
Unlike the original code, we determine the endianness at compile |
time, not at run time; I don't see much benefit to selecting |
endianness at run time. */ |
#ifndef __IEEE_BIG_ENDIAN |
#ifndef __IEEE_LITTLE_ENDIAN |
#error Must define endianness |
#endif |
#endif |
/* A union which permits us to convert between a double and two 32 bit |
ints. */ |
#ifdef __IEEE_BIG_ENDIAN |
typedef union |
{ |
double value; |
struct |
{ |
__uint32_t msw; |
__uint32_t lsw; |
} parts; |
} ieee_double_shape_type; |
#endif |
#ifdef __IEEE_LITTLE_ENDIAN |
typedef union |
{ |
double value; |
struct |
{ |
__uint32_t lsw; |
__uint32_t msw; |
} parts; |
} ieee_double_shape_type; |
#endif |
/* Get two 32 bit ints from a double. */ |
#define EXTRACT_WORDS(ix0,ix1,d) \ |
do { \ |
ieee_double_shape_type ew_u; \ |
ew_u.value = (d); \ |
(ix0) = ew_u.parts.msw; \ |
(ix1) = ew_u.parts.lsw; \ |
} while (0) |
/* Get the more significant 32 bit int from a double. */ |
#define GET_HIGH_WORD(i,d) \ |
do { \ |
ieee_double_shape_type gh_u; \ |
gh_u.value = (d); \ |
(i) = gh_u.parts.msw; \ |
} while (0) |
/* Get the less significant 32 bit int from a double. */ |
#define GET_LOW_WORD(i,d) \ |
do { \ |
ieee_double_shape_type gl_u; \ |
gl_u.value = (d); \ |
(i) = gl_u.parts.lsw; \ |
} while (0) |
/* Set a double from two 32 bit ints. */ |
#define INSERT_WORDS(d,ix0,ix1) \ |
do { \ |
ieee_double_shape_type iw_u; \ |
iw_u.parts.msw = (ix0); \ |
iw_u.parts.lsw = (ix1); \ |
(d) = iw_u.value; \ |
} while (0) |
/* Set the more significant 32 bits of a double from an int. */ |
#define SET_HIGH_WORD(d,v) \ |
do { \ |
ieee_double_shape_type sh_u; \ |
sh_u.value = (d); \ |
sh_u.parts.msw = (v); \ |
(d) = sh_u.value; \ |
} while (0) |
/* Set the less significant 32 bits of a double from an int. */ |
#define SET_LOW_WORD(d,v) \ |
do { \ |
ieee_double_shape_type sl_u; \ |
sl_u.value = (d); \ |
sl_u.parts.lsw = (v); \ |
(d) = sl_u.value; \ |
} while (0) |
/* A union which permits us to convert between a float and a 32 bit |
int. */ |
typedef union |
{ |
float value; |
__uint32_t word; |
} ieee_float_shape_type; |
/* Get a 32 bit int from a float. */ |
#define GET_FLOAT_WORD(i,d) \ |
do { \ |
ieee_float_shape_type gf_u; \ |
gf_u.value = (d); \ |
(i) = gf_u.word; \ |
} while (0) |
/* Set a float from a 32 bit int. */ |
#define SET_FLOAT_WORD(d,i) \ |
do { \ |
ieee_float_shape_type sf_u; \ |
sf_u.word = (i); \ |
(d) = sf_u.value; \ |
} while (0) |
/programs/develop/libraries/newlib/math/floor.S |
---|
0,0 → 1,33 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* |
*/ |
.file "floor.s" |
.text |
.align 4 |
.globl _floor |
.def _floor; .scl 2; .type 32; .endef |
_floor: |
fldl 4(%esp) |
subl $8,%esp |
fstcw 4(%esp) /* store fpu control word */ |
/* We use here %edx although only the low 1 bits are defined. |
But none of the operations should care and they are faster |
than the 16 bit operations. */ |
movl $0x400,%edx /* round towards -oo */ |
orl 4(%esp),%edx |
andl $0xf7ff,%edx |
movl %edx,(%esp) |
fldcw (%esp) /* load modified control word */ |
frndint /* round */ |
fldcw 4(%esp) /* restore original control word */ |
addl $8,%esp |
ret |
/programs/develop/libraries/newlib/math/floorf.S |
---|
0,0 → 1,35 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "floorf.S" |
.text |
.align 4 |
.globl _floorf |
.def _floorf; .scl 2; .type 32; .endef |
_floorf: |
flds 4(%esp) |
subl $8,%esp |
fstcw 4(%esp) /* store fpu control word */ |
/* We use here %edx although only the low 1 bits are defined. |
But none of the operations should care and they are faster |
than the 16 bit operations. */ |
movl $0x400,%edx /* round towards -oo */ |
orl 4(%esp),%edx |
andl $0xf7ff,%edx |
movl %edx,(%esp) |
fldcw (%esp) /* load modified control word */ |
frndint /* round */ |
fldcw 4(%esp) /* restore original control word */ |
addl $8,%esp |
ret |
/programs/develop/libraries/newlib/math/floorl.S |
---|
0,0 → 1,33 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* |
*/ |
.file "floorl.S" |
.text |
.align 4 |
.globl _floorl |
.def _floorl; .scl 2; .type 32; .endef |
_floorl: |
fldt 4(%esp) |
subl $8,%esp |
fstcw 4(%esp) /* store fpu control word */ |
/* We use here %edx although only the low 1 bits are defined. |
But none of the operations should care and they are faster |
than the 16 bit operations. */ |
movl $0x400,%edx /* round towards -oo */ |
orl 4(%esp),%edx |
andl $0xf7ff,%edx |
movl %edx,(%esp) |
fldcw (%esp) /* load modified control word */ |
frndint /* round */ |
fldcw 4(%esp) /* restore original control word */ |
addl $8,%esp |
ret |
/programs/develop/libraries/newlib/math/fma.S |
---|
0,0 → 1,12 |
.file "fma.S" |
.text |
.align 2 |
.p2align 4,,15 |
.globl _fma |
.def _fma; .scl 2; .type 32; .endef |
_fma: |
fldl 4(%esp) |
fmull 12(%esp) |
fldl 20(%esp) |
faddp |
ret |
/programs/develop/libraries/newlib/math/fmaf.S |
---|
0,0 → 1,12 |
.file "fmaf.S" |
.text |
.align 2 |
.p2align 4,,15 |
.globl _fmaf |
.def _fmaf; .scl 2; .type 32; .endef |
_fmaf: |
flds 4(%esp) |
fmuls 8(%esp) |
flds 12(%esp) |
faddp |
ret |
/programs/develop/libraries/newlib/math/fmal.c |
---|
0,0 → 1,5 |
long double |
fmal ( long double _x, long double _y, long double _z) |
{ |
return ((_x * _y) + _z); |
} |
/programs/develop/libraries/newlib/math/fmax.c |
---|
0,0 → 1,7 |
#include <math.h> |
double |
fmax (double _x, double _y) |
{ |
return ( isgreaterequal (_x, _y)|| __isnan (_y) ? _x : _y ); |
} |
/programs/develop/libraries/newlib/math/fmaxf.c |
---|
0,0 → 1,7 |
#include <math.h> |
float |
fmaxf (float _x, float _y) |
{ |
return (( isgreaterequal(_x, _y) || __isnanf (_y)) ? _x : _y ); |
} |
/programs/develop/libraries/newlib/math/fmaxl.c |
---|
0,0 → 1,7 |
#include <math.h> |
long double |
fmaxl (long double _x, long double _y) |
{ |
return (( isgreaterequal(_x, _y) || __isnanl (_y)) ? _x : _y ); |
} |
/programs/develop/libraries/newlib/math/fmin.c |
---|
0,0 → 1,7 |
#include <math.h> |
double |
fmin (double _x, double _y) |
{ |
return ((islessequal(_x, _y) || __isnan (_y)) ? _x : _y ); |
} |
/programs/develop/libraries/newlib/math/fminf.c |
---|
0,0 → 1,7 |
#include <math.h> |
float |
fminf (float _x, float _y) |
{ |
return ((islessequal(_x, _y) || isnan (_y)) ? _x : _y ); |
} |
/programs/develop/libraries/newlib/math/fminl.c |
---|
0,0 → 1,7 |
#include <math.h> |
long double |
fminl (long double _x, long double _y) |
{ |
return ((islessequal(_x, _y) || __isnanl (_y)) ? _x : _y ); |
} |
/programs/develop/libraries/newlib/math/fmodf.c |
---|
0,0 → 1,37 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for float type by Danny Smith |
* <dannysmith@users.sourceforge.net>. |
*/ |
#include <math.h> |
float |
fmodf (float x, float y) |
{ |
float res; |
asm ("1:\tfprem\n\t" |
"fstsw %%ax\n\t" |
"sahf\n\t" |
"jp 1b\n\t" |
"fstp %%st(1)" |
: "=t" (res) : "0" (x), "u" (y) : "ax", "st(1)"); |
return res; |
} |
double |
fmod (double x, double y) |
{ |
float res; |
asm ("1:\tfprem\n\t" |
"fstsw %%ax\n\t" |
"sahf\n\t" |
"jp 1b\n\t" |
"fstp %%st(1)" |
: "=t" (res) : "0" (x), "u" (y) : "ax", "st(1)"); |
return res; |
} |
/programs/develop/libraries/newlib/math/fmodl.c |
---|
0,0 → 1,22 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
*/ |
#include <math.h> |
long double |
fmodl (long double x, long double y) |
{ |
long double res; |
asm ("1:\tfprem\n\t" |
"fstsw %%ax\n\t" |
"sahf\n\t" |
"jp 1b\n\t" |
"fstp %%st(1)" |
: "=t" (res) : "0" (x), "u" (y) : "ax", "st(1)"); |
return res; |
} |
/programs/develop/libraries/newlib/math/fp_consts.c |
---|
0,0 → 1,14 |
#include "fp_consts.h" |
const union _ieee_rep __QNAN = { __DOUBLE_QNAN_REP }; |
const union _ieee_rep __SNAN = { __DOUBLE_SNAN_REP }; |
const union _ieee_rep __INF = { __DOUBLE_INF_REP }; |
const union _ieee_rep __DENORM = { __DOUBLE_DENORM_REP }; |
/* ISO C99 */ |
#undef nan |
/* FIXME */ |
double nan (const char * tagp __attribute__((unused)) ) |
{ return __QNAN.double_val; } |
/programs/develop/libraries/newlib/math/fp_consts.h |
---|
0,0 → 1,48 |
#ifndef _FP_CONSTS_H |
#define _FP_CONSTS_H |
/* |
According to IEEE 754 a QNaN has exponent bits of all 1 values and |
initial significand bit of 1. A SNaN has has an exponent of all 1 |
values and initial significand bit of 0 (with one or more other |
significand bits of 1). An Inf has significand of 0 and |
exponent of all 1 values. A denormal value has all exponent bits of 0. |
The following does _not_ follow those rules, but uses values |
equal to those exported from MS C++ runtime lib, msvcprt.dll |
for float and double. MSVC however, does not have long doubles. |
*/ |
#define __DOUBLE_INF_REP { 0, 0, 0, 0x7ff0 } |
#define __DOUBLE_QNAN_REP { 0, 0, 0, 0xfff8 } /* { 0, 0, 0, 0x7ff8 } */ |
#define __DOUBLE_SNAN_REP { 0, 0, 0, 0xfff0 } /* { 1, 0, 0, 0x7ff0 } */ |
#define __DOUBLE_DENORM_REP {1, 0, 0, 0} |
#define D_NAN_MASK 0x7ff0000000000000LL /* this will mask NaN's and Inf's */ |
#define __FLOAT_INF_REP { 0, 0x7f80 } |
#define __FLOAT_QNAN_REP { 0, 0xffc0 } /* { 0, 0x7fc0 } */ |
#define __FLOAT_SNAN_REP { 0, 0xff80 } /* { 1, 0x7f80 } */ |
#define __FLOAT_DENORM_REP {1,0} |
#define F_NAN_MASK 0x7f800000 |
/* |
This assumes no implicit (hidden) bit in extended mode. |
Padded to 96 bits |
*/ |
#define __LONG_DOUBLE_INF_REP { 0, 0, 0, 0x8000, 0x7fff, 0 } |
#define __LONG_DOUBLE_QNAN_REP { 0, 0, 0, 0xc000, 0xffff, 0 } |
#define __LONG_DOUBLE_SNAN_REP { 0, 0, 0, 0x8000, 0xffff, 0 } |
#define __LONG_DOUBLE_DENORM_REP {1, 0, 0, 0, 0, 0} |
union _ieee_rep |
{ |
unsigned short rep[6]; |
float float_val; |
double double_val; |
long double ldouble_val; |
} ; |
#endif |
/programs/develop/libraries/newlib/math/fp_constsf.c |
---|
0,0 → 1,12 |
#include "fp_consts.h" |
const union _ieee_rep __QNANF = { __FLOAT_QNAN_REP }; |
const union _ieee_rep __SNANF = { __FLOAT_SNAN_REP }; |
const union _ieee_rep __INFF = { __FLOAT_INF_REP }; |
const union _ieee_rep __DENORMF = { __FLOAT_DENORM_REP }; |
/* ISO C99 */ |
#undef nanf |
/* FIXME */ |
float nanf(const char * tagp __attribute__((unused)) ) |
{ return __QNANF.float_val;} |
/programs/develop/libraries/newlib/math/fp_constsl.c |
---|
0,0 → 1,12 |
#include "fp_consts.h" |
const union _ieee_rep __QNANL = { __LONG_DOUBLE_QNAN_REP }; |
const union _ieee_rep __SNANL = { __LONG_DOUBLE_SNAN_REP }; |
const union _ieee_rep __INFL = { __LONG_DOUBLE_INF_REP }; |
const union _ieee_rep __DENORML = { __LONG_DOUBLE_DENORM_REP }; |
#undef nanl |
/* FIXME */ |
long double nanl (const char * tagp __attribute__((unused)) ) |
{ return __QNANL.ldouble_val; } |
/programs/develop/libraries/newlib/math/fpclassify.c |
---|
0,0 → 1,20 |
#include <math.h> |
/* 'fxam' sets FPU flags C3,C2,C0 'fstsw' stores: |
FP_NAN 001 0x0100 |
FP_NORMAL 010 0x0400 |
FP_INFINITE 011 0x0500 |
FP_ZERO 100 0x4000 |
FP_SUBNORMAL 110 0x4400 |
and sets C1 flag (signbit) if neg */ |
int __fpclassify (double _x){ |
unsigned short sw; |
__asm__ ( |
"fxam; fstsw %%ax;" |
: "=a" (sw) |
: "t" (_x) |
); |
return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); |
} |
/programs/develop/libraries/newlib/math/fpclassifyf.c |
---|
0,0 → 1,10 |
#include <math.h> |
int __fpclassifyf (float _x){ |
unsigned short sw; |
__asm__ ( |
"fxam; fstsw %%ax;" |
: "=a" (sw) |
: "t" (_x) |
); |
return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); |
} |
/programs/develop/libraries/newlib/math/fpclassifyl.c |
---|
0,0 → 1,10 |
#include <math.h> |
int __fpclassifyl (long double _x){ |
unsigned short sw; |
__asm__ ( |
"fxam; fstsw %%ax;" |
: "=a" (sw) |
: "t" (_x) |
); |
return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); |
} |
/programs/develop/libraries/newlib/math/frexp.S |
---|
0,0 → 1,74 |
/* ix87 specific frexp implementation for double. |
Copyright (C) 1997, 2000, 2005 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
02111-1307 USA. */ |
.file "frexp.s" |
.text |
.align 4 |
two54: .byte 0, 0, 0, 0, 0, 0, 0x50, 0x43 |
.p2align 4,,15 |
.globl _frexp |
.def _frexp; .scl 2; .type 32; .endef |
_frexp: |
movl 4(%esp), %ecx |
movl 8(%esp), %eax |
movl %eax, %edx |
andl $0x7fffffff, %eax |
orl %eax, %ecx |
jz 1f |
xorl %ecx, %ecx |
cmpl $0x7ff00000, %eax |
jae 1f |
cmpl $0x00100000, %eax |
jae 2f |
fld 4(%esp) |
fmull two54 |
movl $-54, %ecx |
fstpl 4(%esp) |
fwait |
movl 8(%esp), %eax |
movl %eax, %edx |
andl $0x7fffffff, %eax |
2: |
shrl $20, %eax |
andl $0x800fffff, %edx |
subl $1022, %eax |
orl $0x3fe00000, %edx |
addl %eax, %ecx |
movl %edx, 8(%esp) |
/* Store %ecx in the variable pointed to by the second argument, |
get the factor from the stack and return. */ |
1: |
movl 12(%esp), %eax |
fldl 4(%esp) |
movl %ecx, (%eax) |
ret |
/programs/develop/libraries/newlib/math/frexpf.c |
---|
0,0 → 1,3 |
#include <math.h> |
float frexpf (float x, int* expn) |
{return (float)frexp(x, expn);} |
/programs/develop/libraries/newlib/math/frexpl.S |
---|
0,0 → 1,71 |
/* |
Cephes Math Library Release 2.7: May, 1998 |
Copyright 1984, 1987, 1988, 1992, 1998 by Stephen L. Moshier |
Extracted from floorl.387 for use in libmingwex.a by |
Danny Smith <dannysmith@users.sourceforge.net> |
2002-06-20 |
*/ |
/* |
* frexpl(long double x, int* expnt) extracts the exponent from x. |
* It returns an integer power of two to expnt and the significand |
* between 0.5 and 1 to y. Thus x = y * 2**expn. |
*/ |
.align 2 |
.globl _frexpl |
_frexpl: |
pushl %ebp |
movl %esp,%ebp |
subl $24,%esp |
pushl %esi |
pushl %ebx |
fldt 8(%ebp) |
movl 20(%ebp),%ebx |
fld %st(0) |
fstpt -12(%ebp) |
leal -4(%ebp),%ecx |
movw -4(%ebp),%dx |
andl $32767,%edx |
jne L25 |
fldz |
fucompp |
fnstsw %ax |
andb $68,%ah |
xorb $64,%ah |
jne L21 |
movl $0,(%ebx) |
fldz |
jmp L24 |
.align 2,0x90 |
.align 2,0x90 |
L21: |
fldt -12(%ebp) |
fadd %st(0),%st |
fstpt -12(%ebp) |
decl %edx |
movw (%ecx),%si |
andl $32767,%esi |
jne L22 |
cmpl $-66,%edx |
jg L21 |
L22: |
addl %esi,%edx |
jmp L19 |
.align 2,0x90 |
L25: |
fstp %st(0) |
L19: |
addl $-16382,%edx |
movl %edx,(%ebx) |
movw (%ecx),%ax |
andl $-32768,%eax |
orl $16382,%eax |
movw %ax,(%ecx) |
fldt -12(%ebp) |
L24: |
leal -32(%ebp),%esp |
popl %ebx |
popl %esi |
leave |
ret |
/programs/develop/libraries/newlib/math/fucom.c |
---|
0,0 → 1,11 |
int |
__fp_unordered_compare (long double x, long double y){ |
unsigned short retval; |
__asm__ ( |
"fucom %%st(1);" |
"fnstsw;" |
: "=a" (retval) |
: "t" (x), "u" (y) |
); |
return retval; |
} |
/programs/develop/libraries/newlib/math/hypotf.c |
---|
0,0 → 1,75 |
#include <math.h> |
#include "fdlibm.h" |
float hypotf (float x, float y) |
{ |
double a=x,b=y,t1,t2,y1,y2,w; |
__int32_t j,k,ha,hb; |
GET_HIGH_WORD(ha,x); |
ha &= 0x7fffffff; |
GET_HIGH_WORD(hb,y); |
hb &= 0x7fffffff; |
if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} |
SET_HIGH_WORD(a,ha); /* a <- |a| */ |
SET_HIGH_WORD(b,hb); /* b <- |b| */ |
if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */ |
k=0; |
if(ha > 0x5f300000) { /* a>2**500 */ |
if(ha >= 0x7ff00000) { /* Inf or NaN */ |
__uint32_t low; |
w = a+b; /* for sNaN */ |
GET_LOW_WORD(low,a); |
if(((ha&0xfffff)|low)==0) w = a; |
GET_LOW_WORD(low,b); |
if(((hb^0x7ff00000)|low)==0) w = b; |
return w; |
} |
/* scale a and b by 2**-600 */ |
ha -= 0x25800000; hb -= 0x25800000; k += 600; |
SET_HIGH_WORD(a,ha); |
SET_HIGH_WORD(b,hb); |
} |
if(hb < 0x20b00000) { /* b < 2**-500 */ |
if(hb <= 0x000fffff) { /* subnormal b or 0 */ |
__uint32_t low; |
GET_LOW_WORD(low,b); |
if((hb|low)==0) return a; |
t1=0; |
SET_HIGH_WORD(t1,0x7fd00000); /* t1=2^1022 */ |
b *= t1; |
a *= t1; |
k -= 1022; |
} else { /* scale a and b by 2^600 */ |
ha += 0x25800000; /* a *= 2^600 */ |
hb += 0x25800000; /* b *= 2^600 */ |
k -= 600; |
SET_HIGH_WORD(a,ha); |
SET_HIGH_WORD(b,hb); |
} |
} |
/* medium size a and b */ |
w = a-b; |
if (w>b) { |
t1 = 0; |
SET_HIGH_WORD(t1,ha); |
t2 = a-t1; |
w = sqrt(t1*t1-(b*(-b)-t2*(a+t1))); |
} else { |
a = a+a; |
y1 = 0; |
SET_HIGH_WORD(y1,hb); |
y2 = b - y1; |
t1 = 0; |
SET_HIGH_WORD(t1,ha+0x00100000); |
t2 = a - t1; |
w = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); |
} |
if(k!=0) { |
__uint32_t high; |
t1 = 1.0; |
GET_HIGH_WORD(high,t1); |
SET_HIGH_WORD(t1,high+(k<<20)); |
return t1*w; |
} else return w; |
} |
/programs/develop/libraries/newlib/math/hypotl.c |
---|
0,0 → 1,73 |
#include <math.h> |
#include <float.h> |
#include <errno.h> |
/* |
This implementation is based largely on Cephes library |
function cabsl (cmplxl.c), which bears the following notice: |
Cephes Math Library Release 2.1: January, 1989 |
Copyright 1984, 1987, 1989 by Stephen L. Moshier |
Direct inquiries to 30 Frost Street, Cambridge, MA 02140 |
*/ |
/* |
Modified for use in libmingwex.a |
02 Sept 2002 Danny Smith <dannysmith@users.sourceforege.net> |
Calls to ldexpl replaced by logbl and calls to frexpl replaced |
by scalbnl to avoid duplicated range checks. |
*/ |
extern long double __INFL; |
#define PRECL 32 |
long double |
hypotl (long double x, long double y) |
{ |
int exx; |
int eyy; |
int scale; |
long double xx =fabsl(x); |
long double yy =fabsl(y); |
if (!isfinite(xx) || !isfinite(yy)) |
return xx + yy; /* Return INF or NAN. */ |
if (xx == 0.0L) |
return yy; |
if (yy == 0.0L) |
return xx; |
/* Get exponents */ |
exx = logbl (xx); |
eyy = logbl (yy); |
/* Check if large differences in scale */ |
scale = exx - eyy; |
if ( scale > PRECL) |
return xx; |
if ( scale < -PRECL) |
return yy; |
/* Exponent of approximate geometric mean (x 2) */ |
scale = (exx + eyy) >> 1; |
/* Rescale: Geometric mean is now about 2 */ |
x = scalbnl(xx, -scale); |
y = scalbnl(yy, -scale); |
xx = sqrtl(x * x + y * y); |
/* Check for overflow and underflow */ |
exx = logbl(xx); |
exx += scale; |
if (exx > LDBL_MAX_EXP) |
{ |
errno = ERANGE; |
return __INFL; |
} |
if (exx < LDBL_MIN_EXP) |
return 0.0L; |
/* Undo scaling */ |
return (scalbnl (xx, scale)); |
} |
/programs/develop/libraries/newlib/math/ilogb.S |
---|
0,0 → 1,37 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "ilogb.S" |
.text |
.align 4 |
.globl _ilogb |
.def _ilogb; .scl 2; .type 32; .endef |
_ilogb: |
fldl 4(%esp) |
/* I added the following ugly construct because ilogb(+-Inf) is |
required to return INT_MAX in ISO C99. |
-- jakub@redhat.com. */ |
fxam /* Is NaN or +-Inf? */ |
fstsw %ax |
movb $0x45, %dh |
andb %ah, %dh |
cmpb $0x05, %dh |
je 1f /* Is +-Inf, jump. */ |
fxtract |
pushl %eax |
fstp %st |
fistpl (%esp) |
fwait |
popl %eax |
ret |
1: fstp %st |
movl $0x7fffffff, %eax |
ret |
/programs/develop/libraries/newlib/math/ilogbf.S |
---|
0,0 → 1,35 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "ilogbf.S" |
.text |
.align 4 |
.globl _ilogbf |
.def _ilogbf; .scl 2; .type 32; .endef |
_ilogbf: |
flds 4(%esp) |
/* I added the following ugly construct because ilogb(+-Inf) is |
required to return INT_MAX in ISO C99. |
-- jakub@redhat.com. */ |
fxam /* Is NaN or +-Inf? */ |
fstsw %ax |
movb $0x45, %dh |
andb %ah, %dh |
cmpb $0x05, %dh |
je 1f /* Is +-Inf, jump. */ |
fxtract |
pushl %eax |
fstp %st |
fistpl (%esp) |
fwait |
popl %eax |
ret |
1: fstp %st |
movl $0x7fffffff, %eax |
ret |
/programs/develop/libraries/newlib/math/ilogbl.S |
---|
0,0 → 1,36 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* Public domain. |
*/ |
.file "ilogbl.S" |
.text |
.align 4 |
.globl _ilogbl |
.def _ilogbl; .scl 2; .type 32; .endef |
_ilogbl: |
fldt 4(%esp) |
/* I added the following ugly construct because ilogb(+-Inf) is |
required to return INT_MAX in ISO C99. |
-- jakub@redhat.com. */ |
fxam /* Is NaN or +-Inf? */ |
fstsw %ax |
movb $0x45, %dh |
andb %ah, %dh |
cmpb $0x05, %dh |
je 1f /* Is +-Inf, jump. */ |
fxtract |
pushl %eax |
fstp %st |
fistpl (%esp) |
fwait |
popl %eax |
ret |
1: fstp %st |
movl $0x7fffffff, %eax |
ret |
/programs/develop/libraries/newlib/math/isnan.c |
---|
0,0 → 1,14 |
#include <math.h> |
int |
__isnan (double _x) |
{ |
unsigned short _sw; |
__asm__ ("fxam;" |
"fstsw %%ax": "=a" (_sw) : "t" (_x)); |
return (_sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) |
== FP_NAN; |
} |
#undef isnan |
int __attribute__ ((alias ("__isnan"))) isnan (double); |
/programs/develop/libraries/newlib/math/isnanf.c |
---|
0,0 → 1,12 |
#include <math.h> |
int |
__isnanf (float _x) |
{ |
unsigned short _sw; |
__asm__ ("fxam;" |
"fstsw %%ax": "=a" (_sw) : "t" (_x) ); |
return (_sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) |
== FP_NAN; |
} |
int __attribute__ ((alias ("__isnanf"))) isnanf (float); |
/programs/develop/libraries/newlib/math/isnanl.c |
---|
0,0 → 1,13 |
#include <math.h> |
int |
__isnanl (long double _x) |
{ |
unsigned short _sw; |
__asm__ ("fxam;" |
"fstsw %%ax": "=a" (_sw) : "t" (_x)); |
return (_sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) |
== FP_NAN; |
} |
int __attribute__ ((alias ("__isnanl"))) isnanl (long double); |
/programs/develop/libraries/newlib/math/ldexp.c |
---|
0,0 → 1,19 |
#include <math.h> |
#include <errno.h> |
double ldexp(double x, int expn) |
{ |
double res; |
if (!isfinite (x) || x == 0.0L) |
return x; |
__asm__ ("fscale" |
: "=t" (res) |
: "0" (x), "u" ((double) expn)); |
// if (!isfinite (res) || res == 0.0L) |
// errno = ERANGE; |
return res; |
} |
/programs/develop/libraries/newlib/math/ldexpf.c |
---|
0,0 → 1,3 |
#include <math.h> |
float ldexpf (float x, int expn) |
{return (float) ldexp (x, expn);} |
/programs/develop/libraries/newlib/math/ldexpl.c |
---|
0,0 → 1,19 |
#include <math.h> |
#include <errno.h> |
long double ldexpl(long double x, int expn) |
{ |
long double res; |
if (!isfinite (x) || x == 0.0L) |
return x; |
__asm__ ("fscale" |
: "=t" (res) |
: "0" (x), "u" ((long double) expn)); |
if (!isfinite (res) || res == 0.0L) |
errno = ERANGE; |
return res; |
} |
/programs/develop/libraries/newlib/math/lgamma.c |
---|
0,0 → 1,369 |
/* lgam() |
* |
* Natural logarithm of gamma function |
* |
* |
* |
* SYNOPSIS: |
* |
* double x, y, __lgamma_r(); |
* int* sgngam; |
* y = __lgamma_r( x, sgngam ); |
* |
* double x, y, lgamma(); |
* y = lgamma( x); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns the base e (2.718...) logarithm of the absolute |
* value of the gamma function of the argument. In the reentrant |
* version, the sign (+1 or -1) of the gamma function is returned |
* in the variable referenced by sgngam. |
* |
* For arguments greater than 13, the logarithm of the gamma |
* function is approximated by the logarithmic version of |
* Stirling's formula using a polynomial approximation of |
* degree 4. Arguments between -33 and +33 are reduced by |
* recurrence to the interval [2,3] of a rational approximation. |
* The cosecant reflection formula is employed for arguments |
* less than -33. |
* |
* Arguments greater than MAXLGM return MAXNUM and an error |
* message. MAXLGM = 2.035093e36 for DEC |
* arithmetic or 2.556348e305 for IEEE arithmetic. |
* |
* |
* |
* ACCURACY: |
* |
* |
* arithmetic domain # trials peak rms |
* DEC 0, 3 7000 5.2e-17 1.3e-17 |
* DEC 2.718, 2.035e36 5000 3.9e-17 9.9e-18 |
* IEEE 0, 3 28000 5.4e-16 1.1e-16 |
* IEEE 2.718, 2.556e305 40000 3.5e-16 8.3e-17 |
* The error criterion was relative when the function magnitude |
* was greater than one but absolute when it was less than one. |
* |
* The following test used the relative error criterion, though |
* at certain points the relative error could be much higher than |
* indicated. |
* IEEE -200, -4 10000 4.8e-16 1.3e-16 |
* |
*/ |
/* |
* Cephes Math Library Release 2.8: June, 2000 |
* Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier |
*/ |
/* |
* 26-11-2002 Modified for mingw. |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifndef __MINGW32__ |
#include "mconf.h" |
#ifdef ANSIPROT |
extern double pow ( double, double ); |
extern double log ( double ); |
extern double exp ( double ); |
extern double sin ( double ); |
extern double polevl ( double, void *, int ); |
extern double p1evl ( double, void *, int ); |
extern double floor ( double ); |
extern double fabs ( double ); |
extern int isnan ( double ); |
extern int isfinite ( double ); |
#else |
double pow(), log(), exp(), sin(), polevl(), p1evl(), floor(), fabs(); |
int isnan(), isfinite(); |
#endif |
#ifdef INFINITIES |
extern double INFINITY; |
#endif |
#ifdef NANS |
extern double NAN; |
#endif |
#else /* __MINGW32__ */ |
#include "cephes_mconf.h" |
#endif /* __MINGW32__ */ |
/* A[]: Stirling's formula expansion of log gamma |
* B[], C[]: log gamma function between 2 and 3 |
*/ |
#ifdef UNK |
static double A[] = { |
8.11614167470508450300E-4, |
-5.95061904284301438324E-4, |
7.93650340457716943945E-4, |
-2.77777777730099687205E-3, |
8.33333333333331927722E-2 |
}; |
static double B[] = { |
-1.37825152569120859100E3, |
-3.88016315134637840924E4, |
-3.31612992738871184744E5, |
-1.16237097492762307383E6, |
-1.72173700820839662146E6, |
-8.53555664245765465627E5 |
}; |
static double C[] = { |
/* 1.00000000000000000000E0, */ |
-3.51815701436523470549E2, |
-1.70642106651881159223E4, |
-2.20528590553854454839E5, |
-1.13933444367982507207E6, |
-2.53252307177582951285E6, |
-2.01889141433532773231E6 |
}; |
/* log( sqrt( 2*pi ) ) */ |
static double LS2PI = 0.91893853320467274178; |
#define MAXLGM 2.556348e305 |
static double LOGPI = 1.14472988584940017414; |
#endif |
#ifdef DEC |
static const unsigned short A[] = { |
0035524,0141201,0034633,0031405, |
0135433,0176755,0126007,0045030, |
0035520,0006371,0003342,0172730, |
0136066,0005540,0132605,0026407, |
0037252,0125252,0125252,0125132 |
}; |
static const unsigned short B[] = { |
0142654,0044014,0077633,0035410, |
0144027,0110641,0125335,0144760, |
0144641,0165637,0142204,0047447, |
0145215,0162027,0146246,0155211, |
0145322,0026110,0010317,0110130, |
0145120,0061472,0120300,0025363 |
}; |
static const unsigned short C[] = { |
/*0040200,0000000,0000000,0000000*/ |
0142257,0164150,0163630,0112622, |
0143605,0050153,0156116,0135272, |
0144527,0056045,0145642,0062332, |
0145213,0012063,0106250,0001025, |
0145432,0111254,0044577,0115142, |
0145366,0071133,0050217,0005122 |
}; |
/* log( sqrt( 2*pi ) ) */ |
static const unsigned short LS2P[] = {040153,037616,041445,0172645,}; |
#define LS2PI *(double *)LS2P |
#define MAXLGM 2.035093e36 |
static const unsigned short LPI[4] = { |
0040222,0103202,0043475,0006750, |
}; |
#define LOGPI *(double *)LPI |
#endif |
#ifdef IBMPC |
static const unsigned short A[] = { |
0x6661,0x2733,0x9850,0x3f4a, |
0xe943,0xb580,0x7fbd,0xbf43, |
0x5ebb,0x20dc,0x019f,0x3f4a, |
0xa5a1,0x16b0,0xc16c,0xbf66, |
0x554b,0x5555,0x5555,0x3fb5 |
}; |
static const unsigned short B[] = { |
0x6761,0x8ff3,0x8901,0xc095, |
0xb93e,0x355b,0xf234,0xc0e2, |
0x89e5,0xf890,0x3d73,0xc114, |
0xdb51,0xf994,0xbc82,0xc131, |
0xf20b,0x0219,0x4589,0xc13a, |
0x055e,0x5418,0x0c67,0xc12a |
}; |
static const unsigned short C[] = { |
/*0x0000,0x0000,0x0000,0x3ff0,*/ |
0x12b2,0x1cf3,0xfd0d,0xc075, |
0xd757,0x7b89,0xaa0d,0xc0d0, |
0x4c9b,0xb974,0xeb84,0xc10a, |
0x0043,0x7195,0x6286,0xc131, |
0xf34c,0x892f,0x5255,0xc143, |
0xe14a,0x6a11,0xce4b,0xc13e |
}; |
/* log( sqrt( 2*pi ) ) */ |
static const union |
{ |
unsigned short s[4]; |
double d; |
} ls2p = {{0xbeb5,0xc864,0x67f1,0x3fed}}; |
#define LS2PI (ls2p.d) |
#define MAXLGM 2.556348e305 |
/* log (pi) */ |
static const union |
{ |
unsigned short s[4]; |
double d; |
} lpi = {{0xa1bd,0x48e7,0x50d0,0x3ff2}}; |
#define LOGPI (lpi.d) |
#endif |
#ifdef MIEEE |
static const unsigned short A[] = { |
0x3f4a,0x9850,0x2733,0x6661, |
0xbf43,0x7fbd,0xb580,0xe943, |
0x3f4a,0x019f,0x20dc,0x5ebb, |
0xbf66,0xc16c,0x16b0,0xa5a1, |
0x3fb5,0x5555,0x5555,0x554b |
}; |
static const unsigned short B[] = { |
0xc095,0x8901,0x8ff3,0x6761, |
0xc0e2,0xf234,0x355b,0xb93e, |
0xc114,0x3d73,0xf890,0x89e5, |
0xc131,0xbc82,0xf994,0xdb51, |
0xc13a,0x4589,0x0219,0xf20b, |
0xc12a,0x0c67,0x5418,0x055e |
}; |
static const unsigned short C[] = { |
0xc075,0xfd0d,0x1cf3,0x12b2, |
0xc0d0,0xaa0d,0x7b89,0xd757, |
0xc10a,0xeb84,0xb974,0x4c9b, |
0xc131,0x6286,0x7195,0x0043, |
0xc143,0x5255,0x892f,0xf34c, |
0xc13e,0xce4b,0x6a11,0xe14a |
}; |
/* log( sqrt( 2*pi ) ) */ |
static const union |
{ |
unsigned short s[4]; |
double d; |
} ls2p = {{0x3fed,0x67f1,0xc864,0xbeb5}}; |
#define LS2PI ls2p.d |
#define MAXLGM 2.556348e305 |
/* log (pi) */ |
static const union |
{ |
unsigned short s[4]; |
double d; |
} lpi = {{0x3ff2, 0x50d0, 0x48e7, 0xa1bd}}; |
#define LOGPI (lpi.d) |
#endif |
/* Logarithm of gamma function */ |
/* Reentrant version */ |
double __lgamma_r(double x, int* sgngam) |
{ |
double p, q, u, w, z; |
int i; |
*sgngam = 1; |
#ifdef NANS |
if( isnan(x) ) |
return(x); |
#endif |
#ifdef INFINITIES |
if( !isfinite(x) ) |
return(INFINITY); |
#endif |
if( x < -34.0 ) |
{ |
q = -x; |
w = __lgamma_r(q, sgngam); /* note this modifies sgngam! */ |
p = floor(q); |
if( p == q ) |
{ |
lgsing: |
_SET_ERRNO(EDOM); |
mtherr( "lgam", SING ); |
#ifdef INFINITIES |
return (INFINITY); |
#else |
return (MAXNUM); |
#endif |
} |
i = p; |
if( (i & 1) == 0 ) |
*sgngam = -1; |
else |
*sgngam = 1; |
z = q - p; |
if( z > 0.5 ) |
{ |
p += 1.0; |
z = p - q; |
} |
z = q * sin( PI * z ); |
if( z == 0.0 ) |
goto lgsing; |
/* z = log(PI) - log( z ) - w;*/ |
z = LOGPI - log( z ) - w; |
return( z ); |
} |
if( x < 13.0 ) |
{ |
z = 1.0; |
p = 0.0; |
u = x; |
while( u >= 3.0 ) |
{ |
p -= 1.0; |
u = x + p; |
z *= u; |
} |
while( u < 2.0 ) |
{ |
if( u == 0.0 ) |
goto lgsing; |
z /= u; |
p += 1.0; |
u = x + p; |
} |
if( z < 0.0 ) |
{ |
*sgngam = -1; |
z = -z; |
} |
else |
*sgngam = 1; |
if( u == 2.0 ) |
return( log(z) ); |
p -= 2.0; |
x = x + p; |
p = x * polevl( x, B, 5 ) / p1evl( x, C, 6); |
return( log(z) + p ); |
} |
if( x > MAXLGM ) |
{ |
_SET_ERRNO(ERANGE); |
mtherr( "lgamma", OVERFLOW ); |
#ifdef INFINITIES |
return( *sgngam * INFINITY ); |
#else |
return( *sgngam * MAXNUM ); |
#endif |
} |
q = ( x - 0.5 ) * log(x) - x + LS2PI; |
if( x > 1.0e8 ) |
return( q ); |
p = 1.0/(x*x); |
if( x >= 1000.0 ) |
q += (( 7.9365079365079365079365e-4 * p |
- 2.7777777777777777777778e-3) *p |
+ 0.0833333333333333333333) / x; |
else |
q += polevl( p, A, 4 ) / x; |
return( q ); |
} |
/* This is the C99 version */ |
double lgamma(double x) |
{ |
int local_sgngam=0; |
return (__lgamma_r(x, &local_sgngam)); |
} |
/programs/develop/libraries/newlib/math/lgammaf.c |
---|
0,0 → 1,253 |
/* lgamf() |
* |
* Natural logarithm of gamma function |
* |
* |
* |
* SYNOPSIS: |
* |
* float x, y, __lgammaf_r(); |
* int* sgngamf; |
* y = __lgammaf_r( x, sgngamf ); |
* |
* float x, y, lgammaf(); |
* y = lgammaf( x); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns the base e (2.718...) logarithm of the absolute |
* value of the gamma function of the argument. In the reentrant |
* version the sign (+1 or -1) of the gamma function is returned in |
* variable referenced by sgngamf. |
* |
* For arguments greater than 6.5, the logarithm of the gamma |
* function is approximated by the logarithmic version of |
* Stirling's formula. Arguments between 0 and +6.5 are reduced by |
* by recurrence to the interval [.75,1.25] or [1.5,2.5] of a rational |
* approximation. The cosecant reflection formula is employed for |
* arguments less than zero. |
* |
* Arguments greater than MAXLGM = 2.035093e36 return MAXNUM and an |
* error message. |
* |
* |
* |
* ACCURACY: |
* |
* |
* |
* arithmetic domain # trials peak rms |
* IEEE -100,+100 500,000 7.4e-7 6.8e-8 |
* The error criterion was relative when the function magnitude |
* was greater than one but absolute when it was less than one. |
* The routine has low relative error for positive arguments. |
* |
* The following test used the relative error criterion. |
* IEEE -2, +3 100000 4.0e-7 5.6e-8 |
* |
*/ |
/* |
Cephes Math Library Release 2.7: July, 1998 |
Copyright 1984, 1987, 1989, 1992, 1998 by Stephen L. Moshier |
*/ |
/* |
26-11-2002 Modified for mingw. |
Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
/* log gamma(x+2), -.5 < x < .5 */ |
static const float B[] = { |
6.055172732649237E-004, |
-1.311620815545743E-003, |
2.863437556468661E-003, |
-7.366775108654962E-003, |
2.058355474821512E-002, |
-6.735323259371034E-002, |
3.224669577325661E-001, |
4.227843421859038E-001 |
}; |
/* log gamma(x+1), -.25 < x < .25 */ |
static const float C[] = { |
1.369488127325832E-001, |
-1.590086327657347E-001, |
1.692415923504637E-001, |
-2.067882815621965E-001, |
2.705806208275915E-001, |
-4.006931650563372E-001, |
8.224670749082976E-001, |
-5.772156501719101E-001 |
}; |
/* log( sqrt( 2*pi ) ) */ |
static const float LS2PI = 0.91893853320467274178; |
#define MAXLGM 2.035093e36 |
static const float PIINV = 0.318309886183790671538; |
#ifndef __MINGW32__ |
#include "mconf.h" |
float floorf(float); |
float polevlf( float, float *, int ); |
float p1evlf( float, float *, int ); |
#else |
#include "cephes_mconf.h" |
#endif |
/* Reentrant version */ |
/* Logarithm of gamma function */ |
float __lgammaf_r( float x, int* sgngamf ) |
{ |
float p, q, w, z; |
float nx, tx; |
int i, direction; |
*sgngamf = 1; |
#ifdef NANS |
if( isnan(x) ) |
return(x); |
#endif |
#ifdef INFINITIES |
if( !isfinite(x) ) |
return(x); |
#endif |
if( x < 0.0 ) |
{ |
q = -x; |
w = __lgammaf_r(q, sgngamf); /* note this modifies sgngam! */ |
p = floorf(q); |
if( p == q ) |
{ |
lgsing: |
_SET_ERRNO(EDOM); |
mtherr( "lgamf", SING ); |
#ifdef INFINITIES |
return (INFINITYF); |
#else |
return( *sgngamf * MAXNUMF ); |
#endif |
} |
i = p; |
if( (i & 1) == 0 ) |
*sgngamf = -1; |
else |
*sgngamf = 1; |
z = q - p; |
if( z > 0.5 ) |
{ |
p += 1.0; |
z = p - q; |
} |
z = q * sinf( PIF * z ); |
if( z == 0.0 ) |
goto lgsing; |
z = -logf( PIINV*z ) - w; |
return( z ); |
} |
if( x < 6.5 ) |
{ |
direction = 0; |
z = 1.0; |
tx = x; |
nx = 0.0; |
if( x >= 1.5 ) |
{ |
while( tx > 2.5 ) |
{ |
nx -= 1.0; |
tx = x + nx; |
z *=tx; |
} |
x += nx - 2.0; |
iv1r5: |
p = x * polevlf( x, B, 7 ); |
goto cont; |
} |
if( x >= 1.25 ) |
{ |
z *= x; |
x -= 1.0; /* x + 1 - 2 */ |
direction = 1; |
goto iv1r5; |
} |
if( x >= 0.75 ) |
{ |
x -= 1.0; |
p = x * polevlf( x, C, 7 ); |
q = 0.0; |
goto contz; |
} |
while( tx < 1.5 ) |
{ |
if( tx == 0.0 ) |
goto lgsing; |
z *=tx; |
nx += 1.0; |
tx = x + nx; |
} |
direction = 1; |
x += nx - 2.0; |
p = x * polevlf( x, B, 7 ); |
cont: |
if( z < 0.0 ) |
{ |
*sgngamf = -1; |
z = -z; |
} |
else |
{ |
*sgngamf = 1; |
} |
q = logf(z); |
if( direction ) |
q = -q; |
contz: |
return( p + q ); |
} |
if( x > MAXLGM ) |
{ |
_SET_ERRNO(ERANGE); |
mtherr( "lgamf", OVERFLOW ); |
#ifdef INFINITIES |
return( *sgngamf * INFINITYF ); |
#else |
return( *sgngamf * MAXNUMF ); |
#endif |
} |
/* Note, though an asymptotic formula could be used for x >= 3, |
* there is cancellation error in the following if x < 6.5. */ |
q = LS2PI - x; |
q += ( x - 0.5 ) * logf(x); |
if( x <= 1.0e4 ) |
{ |
z = 1.0/x; |
p = z * z; |
q += (( 6.789774945028216E-004 * p |
- 2.769887652139868E-003 ) * p |
+ 8.333316229807355E-002 ) * z; |
} |
return( q ); |
} |
/* This is the C99 version */ |
float lgammaf(float x) |
{ |
int local_sgngamf=0; |
return (__lgammaf_r(x, &local_sgngamf)); |
} |
/programs/develop/libraries/newlib/math/lgammal.c |
---|
0,0 → 1,416 |
/* lgaml() |
* |
* Natural logarithm of gamma function |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, __lgammal_r(); |
* int* sgngaml; |
* y = __lgammal_r( x, sgngaml ); |
* |
* long double x, y, lgammal(); |
* y = lgammal( x); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns the base e (2.718...) logarithm of the absolute |
* value of the gamma function of the argument. In the reentrant |
* version, the sign (+1 or -1) of the gamma function is returned |
* in the variable referenced by sgngaml. |
* |
* For arguments greater than 33, the logarithm of the gamma |
* function is approximated by the logarithmic version of |
* Stirling's formula using a polynomial approximation of |
* degree 4. Arguments between -33 and +33 are reduced by |
* recurrence to the interval [2,3] of a rational approximation. |
* The cosecant reflection formula is employed for arguments |
* less than -33. |
* |
* Arguments greater than MAXLGML (10^4928) return MAXNUML. |
* |
* |
* |
* ACCURACY: |
* |
* |
* arithmetic domain # trials peak rms |
* IEEE -40, 40 100000 2.2e-19 4.6e-20 |
* IEEE 10^-2000,10^+2000 20000 1.6e-19 3.3e-20 |
* The error criterion was relative when the function magnitude |
* was greater than one but absolute when it was less than one. |
* |
*/ |
/* |
* Copyright 1994 by Stephen L. Moshier |
*/ |
/* |
* 26-11-2002 Modified for mingw. |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifndef __MINGW32__ |
#include "mconf.h" |
#ifdef ANSIPROT |
extern long double fabsl ( long double ); |
extern long double lgaml ( long double ); |
extern long double logl ( long double ); |
extern long double expl ( long double ); |
extern long double gammal ( long double ); |
extern long double sinl ( long double ); |
extern long double floorl ( long double ); |
extern long double powl ( long double, long double ); |
extern long double polevll ( long double, void *, int ); |
extern long double p1evll ( long double, void *, int ); |
extern int isnanl ( long double ); |
extern int isfinitel ( long double ); |
#else |
long double fabsl(), lgaml(), logl(), expl(), gammal(), sinl(); |
long double floorl(), powl(), polevll(), p1evll(), isnanl(), isfinitel(); |
#endif |
#ifdef INFINITIES |
extern long double INFINITYL; |
#endif |
#ifdef NANS |
extern long double NANL; |
#endif |
#else /* __MINGW32__ */ |
#include "cephes_mconf.h" |
#endif /* __MINGW32__ */ |
#if UNK |
static long double S[9] = { |
-1.193945051381510095614E-3L, |
7.220599478036909672331E-3L, |
-9.622023360406271645744E-3L, |
-4.219773360705915470089E-2L, |
1.665386113720805206758E-1L, |
-4.200263503403344054473E-2L, |
-6.558780715202540684668E-1L, |
5.772156649015328608253E-1L, |
1.000000000000000000000E0L, |
}; |
#endif |
#if IBMPC |
static const unsigned short S[] = { |
0xbaeb,0xd6d3,0x25e5,0x9c7e,0xbff5, XPD |
0xfe9a,0xceb4,0xc74e,0xec9a,0x3ff7, XPD |
0x9225,0xdfef,0xb0e9,0x9da5,0xbff8, XPD |
0x10b0,0xec17,0x87dc,0xacd7,0xbffa, XPD |
0x6b8d,0x7515,0x1905,0xaa89,0x3ffc, XPD |
0xf183,0x126b,0xf47d,0xac0a,0xbffa, XPD |
0x7bf6,0x57d1,0xa013,0xa7e7,0xbffe, XPD |
0xc7a9,0x7db0,0x67e3,0x93c4,0x3ffe, XPD |
0x0000,0x0000,0x0000,0x8000,0x3fff, XPD |
}; |
#endif |
#if MIEEE |
static long S[27] = { |
0xbff50000,0x9c7e25e5,0xd6d3baeb, |
0x3ff70000,0xec9ac74e,0xceb4fe9a, |
0xbff80000,0x9da5b0e9,0xdfef9225, |
0xbffa0000,0xacd787dc,0xec1710b0, |
0x3ffc0000,0xaa891905,0x75156b8d, |
0xbffa0000,0xac0af47d,0x126bf183, |
0xbffe0000,0xa7e7a013,0x57d17bf6, |
0x3ffe0000,0x93c467e3,0x7db0c7a9, |
0x3fff0000,0x80000000,0x00000000, |
}; |
#endif |
#if UNK |
static long double SN[9] = { |
1.133374167243894382010E-3L, |
7.220837261893170325704E-3L, |
9.621911155035976733706E-3L, |
-4.219773343731191721664E-2L, |
-1.665386113944413519335E-1L, |
-4.200263503402112910504E-2L, |
6.558780715202536547116E-1L, |
5.772156649015328608727E-1L, |
-1.000000000000000000000E0L, |
}; |
#endif |
#if IBMPC |
static const unsigned SN[] = { |
0x5dd1,0x02de,0xb9f7,0x948d,0x3ff5, XPD |
0x989b,0xdd68,0xc5f1,0xec9c,0x3ff7, XPD |
0x2ca1,0x18f0,0x386f,0x9da5,0x3ff8, XPD |
0x783f,0x41dd,0x87d1,0xacd7,0xbffa, XPD |
0x7a5b,0xd76d,0x1905,0xaa89,0xbffc, XPD |
0x7f64,0x1234,0xf47d,0xac0a,0xbffa, XPD |
0x5e26,0x57d1,0xa013,0xa7e7,0x3ffe, XPD |
0xc7aa,0x7db0,0x67e3,0x93c4,0x3ffe, XPD |
0x0000,0x0000,0x0000,0x8000,0xbfff, XPD |
}; |
#endif |
#if MIEEE |
static long SN[27] = { |
0x3ff50000,0x948db9f7,0x02de5dd1, |
0x3ff70000,0xec9cc5f1,0xdd68989b, |
0x3ff80000,0x9da5386f,0x18f02ca1, |
0xbffa0000,0xacd787d1,0x41dd783f, |
0xbffc0000,0xaa891905,0xd76d7a5b, |
0xbffa0000,0xac0af47d,0x12347f64, |
0x3ffe0000,0xa7e7a013,0x57d15e26, |
0x3ffe0000,0x93c467e3,0x7db0c7aa, |
0xbfff0000,0x80000000,0x00000000, |
}; |
#endif |
/* A[]: Stirling's formula expansion of log gamma |
* B[], C[]: log gamma function between 2 and 3 |
*/ |
/* log gamma(x) = ( x - 0.5 ) * log(x) - x + LS2PI + 1/x A(1/x^2) |
* x >= 8 |
* Peak relative error 1.51e-21 |
* Relative spread of error peaks 5.67e-21 |
*/ |
#if UNK |
static long double A[7] = { |
4.885026142432270781165E-3L, |
-1.880801938119376907179E-3L, |
8.412723297322498080632E-4L, |
-5.952345851765688514613E-4L, |
7.936507795855070755671E-4L, |
-2.777777777750349603440E-3L, |
8.333333333333331447505E-2L, |
}; |
#endif |
#if IBMPC |
static const unsigned short A[] = { |
0xd984,0xcc08,0x91c2,0xa012,0x3ff7, XPD |
0x3d91,0x0304,0x3da1,0xf685,0xbff5, XPD |
0x3bdc,0xaad1,0xd492,0xdc88,0x3ff4, XPD |
0x8b20,0x9fce,0x844e,0x9c09,0xbff4, XPD |
0xf8f2,0x30e5,0x0092,0xd00d,0x3ff4, XPD |
0x4d88,0x03a8,0x60b6,0xb60b,0xbff6, XPD |
0x9fcc,0xaaaa,0xaaaa,0xaaaa,0x3ffb, XPD |
}; |
#endif |
#if MIEEE |
static long A[21] = { |
0x3ff70000,0xa01291c2,0xcc08d984, |
0xbff50000,0xf6853da1,0x03043d91, |
0x3ff40000,0xdc88d492,0xaad13bdc, |
0xbff40000,0x9c09844e,0x9fce8b20, |
0x3ff40000,0xd00d0092,0x30e5f8f2, |
0xbff60000,0xb60b60b6,0x03a84d88, |
0x3ffb0000,0xaaaaaaaa,0xaaaa9fcc, |
}; |
#endif |
/* log gamma(x+2) = x B(x)/C(x) |
* 0 <= x <= 1 |
* Peak relative error 7.16e-22 |
* Relative spread of error peaks 4.78e-20 |
*/ |
#if UNK |
static long double B[7] = { |
-2.163690827643812857640E3L, |
-8.723871522843511459790E4L, |
-1.104326814691464261197E6L, |
-6.111225012005214299996E6L, |
-1.625568062543700591014E7L, |
-2.003937418103815175475E7L, |
-8.875666783650703802159E6L, |
}; |
static long double C[7] = { |
/* 1.000000000000000000000E0L,*/ |
-5.139481484435370143617E2L, |
-3.403570840534304670537E4L, |
-6.227441164066219501697E5L, |
-4.814940379411882186630E6L, |
-1.785433287045078156959E7L, |
-3.138646407656182662088E7L, |
-2.099336717757895876142E7L, |
}; |
#endif |
#if IBMPC |
static const unsigned short B[] = { |
0x9557,0x4995,0x0da1,0x873b,0xc00a, XPD |
0xfe44,0x9af8,0x5b8c,0xaa63,0xc00f, XPD |
0x5aa8,0x7cf5,0x3684,0x86ce,0xc013, XPD |
0x259a,0x258c,0xf206,0xba7f,0xc015, XPD |
0xbe18,0x1ca3,0xc0a0,0xf80a,0xc016, XPD |
0x168f,0x2c42,0x6717,0x98e3,0xc017, XPD |
0x2051,0x9d55,0x92c8,0x876e,0xc016, XPD |
}; |
static const unsigned short C[] = { |
/*0x0000,0x0000,0x0000,0x8000,0x3fff, XPD*/ |
0xaa77,0xcf2f,0xae76,0x807c,0xc008, XPD |
0xb280,0x0d74,0xb55a,0x84f3,0xc00e, XPD |
0xa505,0xcd30,0x81dc,0x9809,0xc012, XPD |
0x3369,0x4246,0xb8c2,0x92f0,0xc015, XPD |
0x63cf,0x6aee,0xbe6f,0x8837,0xc017, XPD |
0x26bb,0xccc7,0xb009,0xef75,0xc017, XPD |
0x462b,0xbae8,0xab96,0xa02a,0xc017, XPD |
}; |
#endif |
#if MIEEE |
static long B[21] = { |
0xc00a0000,0x873b0da1,0x49959557, |
0xc00f0000,0xaa635b8c,0x9af8fe44, |
0xc0130000,0x86ce3684,0x7cf55aa8, |
0xc0150000,0xba7ff206,0x258c259a, |
0xc0160000,0xf80ac0a0,0x1ca3be18, |
0xc0170000,0x98e36717,0x2c42168f, |
0xc0160000,0x876e92c8,0x9d552051, |
}; |
static long C[21] = { |
/*0x3fff0000,0x80000000,0x00000000,*/ |
0xc0080000,0x807cae76,0xcf2faa77, |
0xc00e0000,0x84f3b55a,0x0d74b280, |
0xc0120000,0x980981dc,0xcd30a505, |
0xc0150000,0x92f0b8c2,0x42463369, |
0xc0170000,0x8837be6f,0x6aee63cf, |
0xc0170000,0xef75b009,0xccc726bb, |
0xc0170000,0xa02aab96,0xbae8462b, |
}; |
#endif |
/* log( sqrt( 2*pi ) ) */ |
static const long double LS2PI = 0.91893853320467274178L; |
#define MAXLGM 1.04848146839019521116e+4928L |
/* Logarithm of gamma function */ |
/* Reentrant version */ |
long double __lgammal_r(long double x, int* sgngaml) |
{ |
long double p, q, w, z, f, nx; |
int i; |
*sgngaml = 1; |
#ifdef NANS |
if( isnanl(x) ) |
return(NANL); |
#endif |
#ifdef INFINITIES |
if( !isfinitel(x) ) |
return(INFINITYL); |
#endif |
if( x < -34.0L ) |
{ |
q = -x; |
w = __lgammal_r(q, sgngaml); /* note this modifies sgngam! */ |
p = floorl(q); |
if( p == q ) |
{ |
lgsing: |
_SET_ERRNO(EDOM); |
mtherr( "lgammal", SING ); |
#ifdef INFINITIES |
return (INFINITYL); |
#else |
return (MAXNUML); |
#endif |
} |
i = p; |
if( (i & 1) == 0 ) |
*sgngaml = -1; |
else |
*sgngaml = 1; |
z = q - p; |
if( z > 0.5L ) |
{ |
p += 1.0L; |
z = p - q; |
} |
z = q * sinl( PIL * z ); |
if( z == 0.0L ) |
goto lgsing; |
/* z = LOGPI - logl( z ) - w; */ |
z = logl( PIL/z ) - w; |
return( z ); |
} |
if( x < 13.0L ) |
{ |
z = 1.0L; |
nx = floorl( x + 0.5L ); |
f = x - nx; |
while( x >= 3.0L ) |
{ |
nx -= 1.0L; |
x = nx + f; |
z *= x; |
} |
while( x < 2.0L ) |
{ |
if( fabsl(x) <= 0.03125 ) |
goto lsmall; |
z /= nx + f; |
nx += 1.0L; |
x = nx + f; |
} |
if( z < 0.0L ) |
{ |
*sgngaml = -1; |
z = -z; |
} |
else |
*sgngaml = 1; |
if( x == 2.0L ) |
return( logl(z) ); |
x = (nx - 2.0L) + f; |
p = x * polevll( x, B, 6 ) / p1evll( x, C, 7); |
return( logl(z) + p ); |
} |
if( x > MAXLGM ) |
{ |
_SET_ERRNO(ERANGE); |
mtherr( "lgammal", OVERFLOW ); |
#ifdef INFINITIES |
return( *sgngaml * INFINITYL ); |
#else |
return( *sgngaml * MAXNUML ); |
#endif |
} |
q = ( x - 0.5L ) * logl(x) - x + LS2PI; |
if( x > 1.0e10L ) |
return(q); |
p = 1.0L/(x*x); |
q += polevll( p, A, 6 ) / x; |
return( q ); |
lsmall: |
if( x == 0.0L ) |
goto lgsing; |
if( x < 0.0L ) |
{ |
x = -x; |
q = z / (x * polevll( x, SN, 8 )); |
} |
else |
q = z / (x * polevll( x, S, 8 )); |
if( q < 0.0L ) |
{ |
*sgngaml = -1; |
q = -q; |
} |
else |
*sgngaml = 1; |
q = logl( q ); |
return(q); |
} |
/* This is the C99 version */ |
long double lgammal(long double x) |
{ |
int local_sgngaml=0; |
return (__lgammal_r(x, &local_sgngaml)); |
} |
/programs/develop/libraries/newlib/math/llrint.c |
---|
0,0 → 1,10 |
#include <math.h> |
long long llrint (double x) |
{ |
long long retval; |
__asm__ __volatile__ \ |
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ |
return retval; |
} |
/programs/develop/libraries/newlib/math/llrintf.c |
---|
0,0 → 1,9 |
#include <math.h> |
long long llrintf (float x) |
{ |
long long retval; |
__asm__ __volatile__ \ |
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ |
return retval; |
} |
/programs/develop/libraries/newlib/math/llrintl.c |
---|
0,0 → 1,10 |
#include <math.h> |
long long llrintl (long double x) |
{ |
long long retval; |
__asm__ __volatile__ \ |
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ |
return retval; |
} |
/programs/develop/libraries/newlib/math/log.S |
---|
0,0 → 1,38 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. |
*/ |
.file "log.s" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _log |
.def _log; .scl 2; .type 32; .endef |
_log: |
fldln2 /* log(2) */ |
fldl 4(%esp) /* x : log(2) */ |
fld %st /* x : x : log(2) */ |
fsubl one /* x-1 : x : log(2) */ |
fld %st /* x-1 : x-1 : x : log(2) */ |
fabs /* |x-1| : x-1 : x : log(2) */ |
fcompl limit /* x-1 : x : log(2) */ |
fnstsw /* x-1 : x : log(2) */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : log(2) */ |
fyl2xp1 /* log(x) */ |
ret |
2: fstp %st(0) /* x : log(2) */ |
fyl2x /* log(x) */ |
ret |
/programs/develop/libraries/newlib/math/log10.S |
---|
0,0 → 1,48 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Adapted for float type by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. |
*/ |
.file "log10.s" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _log10 |
.def _log10; .scl 2; .type 32; .endef |
_log10: |
fldlg2 /* log10(2) */ |
fldl 4(%esp) /* x : log10(2) */ |
fxam |
fnstsw |
fld %st /* x : x : log10(2) */ |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: fsubl one /* x-1 : x : log10(2) */ |
fld %st /* x-1 : x-1 : x : log10(2) */ |
fabs /* |x-1| : x-1 : x : log10(2) */ |
fcompl limit /* x-1 : x : log10(2) */ |
fnstsw /* x-1 : x : log10(2) */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : log10(2) */ |
fyl2xp1 /* log10(x) */ |
ret |
2: fstp %st(0) /* x : log10(2) */ |
fyl2x /* log10(x) */ |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/log10f.S |
---|
0,0 → 1,48 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Adapted for float type by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. |
*/ |
.file "log10f.S" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _log10f |
.def _log10f; .scl 2; .type 32; .endef |
_log10f: |
fldlg2 /* log10(2) */ |
flds 4(%esp) /* x : log10(2) */ |
fxam |
fnstsw |
fld %st /* x : x : log10(2) */ |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: fsubl one /* x-1 : x : log10(2) */ |
fld %st /* x-1 : x-1 : x : log10(2) */ |
fabs /* |x-1| : x-1 : x : log10(2) */ |
fcompl limit /* x-1 : x : log10(2) */ |
fnstsw /* x-1 : x : log10(2) */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : log10(2) */ |
fyl2xp1 /* log10(x) */ |
ret |
2: fstp %st(0) /* x : log10(2) */ |
fyl2x /* log10(x) */ |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/log10l.S |
---|
0,0 → 1,52 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "log10l.S" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _log10l |
.def _log10l; .scl 2; .type 32; .endef |
_log10l: |
fldlg2 /* log10(2) */ |
fldt 4(%esp) /* x : log10(2) */ |
fxam |
fnstsw |
fld %st /* x : x : log10(2) */ |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: fsubl one /* x-1 : x : log10(2) */ |
fld %st /* x-1 : x-1 : x : log10(2) */ |
fabs /* |x-1| : x-1 : x : log10(2) */ |
fcompl limit /* x-1 : x : log10(2) */ |
fnstsw /* x-1 : x : log10(2) */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : log10(2) */ |
fyl2xp1 /* log10(x) */ |
ret |
2: fstp %st(0) /* x : log10(2) */ |
fyl2x /* log10(x) */ |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/log1p.S |
---|
0,0 → 1,47 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "log1p.S" |
.text |
.align 4 |
/* The fyl2xp1 can only be used for values in |
-1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 |
0.29 is a safe value. |
*/ |
limit: .double 0.29 |
one: .double 1.0 |
/* |
* Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29, |
* otherwise fyl2x with the needed extra computation. |
*/ |
.globl _log1p; |
.def _log1p; .scl 2; .type 32; .endef |
_log1p: |
fldln2 |
fldl 4(%esp) |
fxam |
fnstsw |
fld %st |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: fabs |
fcompl limit |
fnstsw |
sahf |
jc 2f |
faddl one |
fyl2x |
ret |
2: fyl2xp1 |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/log1pf.S |
---|
0,0 → 1,47 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "log1pf.S" |
.text |
.align 4 |
/* The fyl2xp1 can only be used for values in |
-1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 |
0.29 is a safe value. |
*/ |
limit: .float 0.29 |
one: .float 1.0 |
/* |
* Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29, |
* otherwise fyl2x with the needed extra computation. |
*/ |
.globl _log1pf; |
.def _log1pf; .scl 2; .type 32; .endef |
_log1pf: |
fldln2 |
flds 4(%esp) |
fxam |
fnstsw |
fld %st |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: fabs |
fcomps limit |
fnstsw |
sahf |
jc 2f |
fadds one |
fyl2x |
ret |
2: fyl2xp1 |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/log1pl.S |
---|
0,0 → 1,54 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "log1pl.S" |
.text |
.align 4 |
/* The fyl2xp1 can only be used for values in |
-1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 |
0.29 is a safe value. |
*/ |
limit: .tfloat 0.29 |
/* Please note: we use a double value here. Since 1.0 has |
an exact representation this does not effect the accuracy |
but it helps to optimize the code. */ |
one: .double 1.0 |
/* |
* Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29, |
* otherwise fyl2x with the needed extra computation. |
*/ |
.globl _log1pl; |
.def _log1pl; .scl 2; .type 32; .endef |
_log1pl: |
fldln2 |
fldt 4(%esp) |
fxam |
fnstsw |
fld %st |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: |
fabs |
fldt limit |
fcompp |
fnstsw |
sahf |
jnc 2f |
faddl one |
fyl2x |
ret |
2: fyl2xp1 |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/log2.S |
---|
0,0 → 1,51 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Adapted for use as log2 by Ulrich Drepper <drepper@cygnus.com>. |
* Public domain. |
* |
* Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "log2.S" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _log2 |
.def _log2; .scl 2; .type 32; .endef |
_log2: |
fldl one |
fldl 4(%esp) /* x : 1 */ |
fxam |
fnstsw |
fld %st /* x : x : 1 */ |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: fsub %st(2), %st /* x-1 : x : 1 */ |
fld %st /* x-1 : x-1 : x : 1 */ |
fabs /* |x-1| : x-1 : x : 1 */ |
fcompl limit /* x-1 : x : 1 */ |
fnstsw /* x-1 : x : 1 */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : 1 */ |
fyl2xp1 /* log(x) */ |
ret |
2: fstp %st(0) /* x : 1 */ |
fyl2x /* log(x) */ |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/log2f.S |
---|
0,0 → 1,51 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Adapted for use as log2 by Ulrich Drepper <drepper@cygnus.com>. |
* Public domain. |
* |
* Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "log2f.S" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _log2f |
.def _log2f; .scl 2; .type 32; .endef |
_log2f: |
fldl one |
flds 4(%esp) /* x : 1 */ |
fxam |
fnstsw |
fld %st /* x : x : 1 */ |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: fsub %st(2), %st /* x-1 : x : 1 */ |
fld %st /* x-1 : x-1 : x : 1 */ |
fabs /* |x-1| : x-1 : x : 1 */ |
fcompl limit /* x-1 : x : 1 */ |
fnstsw /* x-1 : x : 1 */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : 1 */ |
fyl2xp1 /* log(x) */ |
ret |
2: fstp %st(0) /* x : 1 */ |
fyl2x /* log(x) */ |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/log2l.S |
---|
0,0 → 1,48 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Adapted for use as log2 by Ulrich Drepper <drepper@cygnus.com>. |
* Public domain. |
* |
* Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. |
*/ |
.file "log2l.S" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _log2l |
.def _log2l; .scl 2; .type 32; .endef |
_log2l: |
fldl one |
fldt 4(%esp) /* x : 1 */ |
fxam |
fnstsw |
fld %st /* x : x : 1 */ |
sahf |
jc 3f /* in case x is NaN or ±Inf */ |
4: fsub %st(2), %st /* x-1 : x : 1 */ |
fld %st /* x-1 : x-1 : x : 1 */ |
fabs /* |x-1| : x-1 : x : 1 */ |
fcompl limit /* x-1 : x : 1 */ |
fnstsw /* x-1 : x : 1 */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : 1 */ |
fyl2xp1 /* log(x) */ |
ret |
2: fstp %st(0) /* x : 1 */ |
fyl2x /* log(x) */ |
ret |
3: jp 4b /* in case x is ±Inf */ |
fstp %st(1) |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/logb.c |
---|
0,0 → 1,16 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* Public domain. |
*/ |
#include <math.h> |
double |
logb (double x) |
{ |
double res; |
asm ("fxtract\n\t" |
"fstp %%st" : "=t" (res) : "0" (x)); |
return res; |
} |
/programs/develop/libraries/newlib/math/logbf.c |
---|
0,0 → 1,16 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* Public domain. |
*/ |
#include <math.h> |
float |
logbf (float x) |
{ |
float res; |
asm ("fxtract\n\t" |
"fstp %%st" : "=t" (res) : "0" (x)); |
return res; |
} |
/programs/develop/libraries/newlib/math/logbl.c |
---|
0,0 → 1,17 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* Public domain. |
*/ |
#include <math.h> |
long double |
logbl (long double x) |
{ |
long double res; |
asm ("fxtract\n\t" |
"fstp %%st" : "=t" (res) : "0" (x)); |
return res; |
} |
/programs/develop/libraries/newlib/math/logf.S |
---|
0,0 → 1,39 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Adapted for float by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>. |
*/ |
.file "logf.S" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _logf |
.def _logf; .scl 2; .type 32; .endef |
_logf: |
fldln2 /* log(2) */ |
flds 4(%esp) /* x : log(2) */ |
fld %st /* x : x : log(2) */ |
fsubl one /* x-1 : x : log(2) */ |
fld %st /* x-1 : x-1 : x : log(2) */ |
fabs /* |x-1| : x-1 : x : log(2) */ |
fcompl limit /* x-1 : x : log(2) */ |
fnstsw /* x-1 : x : log(2) */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : log(2) */ |
fyl2xp1 /* log(x) */ |
ret |
2: fstp %st(0) /* x : log(2) */ |
fyl2x /* log(x) */ |
ret |
/programs/develop/libraries/newlib/math/logl.S |
---|
0,0 → 1,40 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "logl.S" |
.text |
.align 4 |
one: .double 1.0 |
/* It is not important that this constant is precise. It is only |
a value which is known to be on the safe side for using the |
fyl2xp1 instruction. */ |
limit: .double 0.29 |
.text |
.align 4 |
.globl _logl |
.def _logl; .scl 2; .type 32; .endef |
_logl: |
fldln2 /* log(2) */ |
fldt 4(%esp) /* x : log(2) */ |
fld %st /* x : x : log(2) */ |
fsubl one /* x-1 : x : log(2) */ |
fld %st /* x-1 : x-1 : x : log(2) */ |
fabs /* |x-1| : x-1 : x : log(2) */ |
fcompl limit /* x-1 : x : log(2) */ |
fnstsw /* x-1 : x : log(2) */ |
andb $0x45, %ah |
jz 2f |
fstp %st(1) /* x-1 : log(2) */ |
fyl2xp1 /* log(x) */ |
ret |
2: fstp %st(0) /* x : log(2) */ |
fyl2x /* log(x) */ |
ret |
/programs/develop/libraries/newlib/math/lrint.c |
---|
0,0 → 1,9 |
#include <math.h> |
long lrint (double x) |
{ |
long retval; |
__asm__ __volatile__ \ |
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ |
return retval; |
} |
/programs/develop/libraries/newlib/math/lrintf.c |
---|
0,0 → 1,9 |
#include <math.h> |
long lrintf (float x) |
{ |
long retval; |
__asm__ __volatile__ \ |
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ |
return retval; |
} |
/programs/develop/libraries/newlib/math/lrintl.c |
---|
0,0 → 1,10 |
#include <math.h> |
long lrintl (long double x) |
{ |
long retval; |
__asm__ __volatile__ \ |
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ |
return retval; |
} |
/programs/develop/libraries/newlib/math/lround_generic.c |
---|
0,0 → 1,64 |
/* |
* lround_generic.c |
* |
* $Id: lround_generic.c,v 1.1 2008/06/03 18:42:21 keithmarshall Exp $ |
* |
* Provides a generic implementation for the `lround()', `lroundf()', |
* `lroundl()', `llround()', `llroundf()' and `llroundl()' functions; |
* compile with `-D FUNCTION=name', with `name' set to each of these |
* six in turn, to create separate object files for each of the six |
* functions. |
* |
* Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
* |
* This is free software. You may redistribute and/or modify it as you |
* see fit, without restriction of copyright. |
* |
* This software is provided "as is", in the hope that it may be useful, |
* but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of |
* MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no |
* time will the author accept any form of liability for any damages, |
* however caused, resulting from the use of this software. |
* |
*/ |
#ifndef FUNCTION |
/* |
* Normally specified with `-D FUNCTION=name', on the command line. |
* Valid FUNCTION names are `lround', `lroundf', `lroundl', `llround' |
* `llroundf' and `llroundl'; specifying anything else will most likely |
* cause a compilation error. If user did not specify an appropriate |
* FUNCTION name, default to `lround'. |
*/ |
#define FUNCTION lround |
#endif |
#include "round_internal.h" |
#include <limits.h> |
#include <errno.h> |
/* Generic implementation. |
* The user is required to specify the FUNCTION name; |
* the RETURN_TYPE and INPUT_TYPE macros resolve to appropriate |
* type declarations, to match the selected FUNCTION prototype, |
* while RETURN_MAX and RETURN_MIN map to the correspondingly |
* appropriate limits.h manifest values, to establish the |
* valid range for the RETURN_TYPE. |
*/ |
RETURN_TYPE FUNCTION( INPUT_TYPE x ) |
{ |
if( !isfinite( x ) || !isfinite( x = round_internal( x ) ) |
|| (x > MAX_RETURN_VALUE) || (x < MIN_RETURN_VALUE) ) |
/* |
* Undefined behaviour... |
* POSIX requires us to report a domain error; ANSI C99 says we |
* _may_ report a range error, and previous MinGW implementation |
* set `errno = ERANGE' here; we change that, conforming to the |
* stricter requiremment of the POSIX standard. |
*/ |
errno = EDOM; |
return (RETURN_TYPE)(x); |
} |
/* $RCSfile: lround_generic.c,v $$Revision: 1.1 $: end of file */ |
/programs/develop/libraries/newlib/math/modff.c |
---|
0,0 → 1,22 |
#include <fenv.h> |
#include <math.h> |
#include <errno.h> |
#define FE_ROUNDING_MASK \ |
(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO) |
float |
modff (float value, float* iptr) |
{ |
float int_part; |
unsigned short saved_cw; |
unsigned short tmp_cw; |
/* truncate */ |
asm ("fnstcw %0;" : "=m" (saved_cw)); /* save control word */ |
tmp_cw = (saved_cw & ~FE_ROUNDING_MASK) | FE_TOWARDZERO; |
asm ("fldcw %0;" : : "m" (tmp_cw)); |
asm ("frndint;" : "=t" (int_part) : "0" (value)); /* round */ |
asm ("fldcw %0;" : : "m" (saved_cw)); /* restore saved cw */ |
if (iptr) |
*iptr = int_part; |
return (isinf (value) ? 0.0F : value - int_part); |
} |
/programs/develop/libraries/newlib/math/modfl.c |
---|
0,0 → 1,22 |
#include <fenv.h> |
#include <math.h> |
#include <errno.h> |
#define FE_ROUNDING_MASK \ |
(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO) |
long double |
modfl (long double value, long double* iptr) |
{ |
long double int_part; |
unsigned short saved_cw; |
unsigned short tmp_cw; |
/* truncate */ |
asm ("fnstcw %0;" : "=m" (saved_cw)); /* save control word */ |
tmp_cw = (saved_cw & ~FE_ROUNDING_MASK) | FE_TOWARDZERO; |
asm ("fldcw %0;" : : "m" (tmp_cw)); |
asm ("frndint;" : "=t" (int_part) : "0" (value)); /* round */ |
asm ("fldcw %0;" : : "m" (saved_cw)); /* restore saved cw */ |
if (iptr) |
*iptr = int_part; |
return (isinf (value) ? 0.0L : value - int_part); |
} |
/programs/develop/libraries/newlib/math/nearbyint.S |
---|
0,0 → 1,30 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for use as nearbyint by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "nearbyint.S" |
.text |
.align 4 |
.globl _nearbyint |
.def _nearbyint; .scl 2; .type 32; .endef |
_nearbyint: |
fldl 4(%esp) |
pushl %eax |
pushl %ecx |
fnstcw (%esp) |
movl (%esp), %eax |
orl $0x20, %eax |
movl %eax, 4(%esp) |
fldcw 4(%esp) |
frndint |
fclex |
fldcw (%esp) |
popl %ecx |
popl %eax |
ret |
/programs/develop/libraries/newlib/math/nearbyintf.S |
---|
0,0 → 1,29 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Adapted for use as nearbyint by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "nearbyintf.S" |
.text |
.align 4 |
.globl _nearbyintf |
.def _nearbyintf; .scl 2; .type 32; .endef |
_nearbyintf: |
flds 4(%esp) |
pushl %eax |
pushl %ecx |
fnstcw (%esp) |
movl (%esp), %eax |
orl $0x20, %eax |
movl %eax, 4(%esp) |
fldcw 4(%esp) |
frndint |
fclex |
fldcw (%esp) |
popl %ecx |
popl %eax |
ret |
/programs/develop/libraries/newlib/math/nearbyintl.S |
---|
0,0 → 1,30 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adaptedfor use as nearbyint by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "nearbyintl.S" |
.text |
.align 4 |
.globl _nearbyintl |
.def _nearbyintl; .scl 2; .type 32; .endef |
_nearbyintl: |
fldt 4(%esp) |
pushl %eax |
pushl %ecx |
fnstcw (%esp) |
movl (%esp), %eax |
orl $0x20, %eax |
movl %eax, 4(%esp) |
fldcw 4(%esp) |
frndint |
fclex |
fldcw (%esp) |
popl %ecx |
popl %eax |
ret |
/programs/develop/libraries/newlib/math/nextafterf.c |
---|
0,0 → 1,27 |
#include <math.h> |
float |
nextafterf (float x, float y) |
{ |
union |
{ |
float f; |
unsigned int i; |
} u; |
if (isnan (y) || isnan (x)) |
return x + y; |
if (x == y ) |
/* nextafter (0.0, -O.0) should return -0.0. */ |
return y; |
u.f = x; |
if (x == 0.0F) |
{ |
u.i = 1; |
return y > 0.0F ? u.f : -u.f; |
} |
if (((x > 0.0F) ^ (y > x)) == 0) |
u.i++; |
else |
u.i--; |
return u.f; |
} |
/programs/develop/libraries/newlib/math/nextafterl.c |
---|
0,0 → 1,65 |
/* |
nextafterl.c |
Contributed by Danny Smith <dannysmith@users.sourceforge.net> |
No copyright claimed, absolutely no warranties. |
2005-05-09 |
*/ |
#include <math.h> |
long double |
nextafterl (long double x, long double y) |
{ |
union { |
long double ld; |
struct { |
unsigned long long mantissa; |
unsigned short expn; |
unsigned short pad; |
} __attribute__ ((packed)) parts; |
} u; |
/* The normal bit is explicit for long doubles, unlike |
float and double. */ |
static const unsigned long long normal_bit = 0x8000000000000000ull; |
if (isnan (y) || isnan (x)) |
return x + y; |
if (x == y ) |
/* nextafter (0.0, -O.0) should return -0.0. */ |
return y; |
u.ld = x; |
if (x == 0.0L) |
{ |
u.parts.mantissa = 1ull; |
return y > 0.0L ? u.ld : -u.ld; |
} |
if (((x > 0.0L) ^ (y > x)) == 0) |
{ |
u.parts.mantissa++; |
if ((u.parts.mantissa & ~normal_bit) == 0ull) |
u.parts.expn++; |
} |
else |
{ |
if ((u.parts.mantissa & ~normal_bit) == 0ull) |
u.parts.expn--; |
u.parts.mantissa--; |
} |
/* If we have updated the expn of a normal number, |
or moved from denormal to normal, [re]set the normal bit. */ |
if (u.parts.expn & 0x7fff) |
u.parts.mantissa |= normal_bit; |
return u.ld; |
} |
/* nexttowardl is the same function with a different name. */ |
long double |
nexttowardl (long double, long double) __attribute__ ((alias("nextafterl"))); |
/programs/develop/libraries/newlib/math/nexttoward.c |
---|
0,0 → 1,42 |
/* |
nexttoward.c |
Contributed by Danny Smith <dannysmith@users.sourceforge.net> |
No copyright claimed, absolutely no warranties. |
2005-05-10 |
*/ |
#include <math.h> |
double |
nexttoward (double x, long double y) |
{ |
union |
{ |
double d; |
unsigned long long ll; |
} u; |
long double xx = x; |
if (isnan (y) || isnan (x)) |
return x + y; |
if (xx == y) |
/* nextafter (0.0, -O.0) should return -0.0. */ |
return y; |
u.d = x; |
if (x == 0.0) |
{ |
u.ll = 1; |
return y > 0.0L ? u.d : -u.d; |
} |
/* Non-extended encodings are lexicographically ordered, |
with implicit "normal" bit. */ |
if (((x > 0.0) ^ (y > xx)) == 0) |
u.ll++; |
else |
u.ll--; |
return u.d; |
} |
/programs/develop/libraries/newlib/math/nexttowardf.c |
---|
0,0 → 1,38 |
/* |
nexttowardf.c |
Contributed by Danny Smith <dannysmith@users.sourceforge.net> |
No copyright claimed, absolutely no warranties. |
2005-05-10 |
*/ |
#include <math.h> |
float |
nexttowardf (float x, long double y) |
{ |
union |
{ |
float f; |
unsigned int i; |
} u; |
long double xx = x; |
if (isnan (y) || isnan (x)) |
return x + y; |
if (xx == y ) |
/* nextafter (0.0, -O.0) should return -0.0. */ |
return y; |
u.f = x; |
if (x == 0.0F) |
{ |
u.i = 1; |
return y > 0.0L ? u.f : -u.f; |
} |
if (((x > 0.0F) ^ (y > xx)) == 0) |
u.i++; |
else |
u.i--; |
return u.f; |
} |
/programs/develop/libraries/newlib/math/op-1.h |
---|
0,0 → 1,302 |
/* Software floating-point emulation. |
Basic one-word fraction declaration and manipulation. |
Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz), |
David S. Miller (davem@redhat.com) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f |
#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f) |
#define _FP_FRAC_SET_1(X,I) (X##_f = I) |
#define _FP_FRAC_HIGH_1(X) (X##_f) |
#define _FP_FRAC_LOW_1(X) (X##_f) |
#define _FP_FRAC_WORD_1(X,w) (X##_f) |
#define _FP_FRAC_ADDI_1(X,I) (X##_f += I) |
#define _FP_FRAC_SLL_1(X,N) \ |
do { \ |
if (__builtin_constant_p(N) && (N) == 1) \ |
X##_f += X##_f; \ |
else \ |
X##_f <<= (N); \ |
} while (0) |
#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N) |
/* Right shift with sticky-lsb. */ |
#define _FP_FRAC_SRST_1(X,S,N,sz) __FP_FRAC_SRST_1(X##_f, S, N, sz) |
#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz) |
#define __FP_FRAC_SRST_1(X,S,N,sz) \ |
do { \ |
S = (__builtin_constant_p(N) && (N) == 1 \ |
? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0); \ |
X = X >> (N); \ |
} while (0) |
#define __FP_FRAC_SRS_1(X,N,sz) \ |
(X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \ |
? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0))) |
#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f) |
#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f) |
#define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f) |
#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f) |
/* Predicates */ |
#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0) |
#define _FP_FRAC_ZEROP_1(X) (X##_f == 0) |
#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs) |
#define _FP_FRAC_CLEAR_OVERP_1(fs,X) (X##_f &= ~_FP_OVERFLOW_##fs) |
#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f) |
#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f) |
#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f) |
#define _FP_ZEROFRAC_1 0 |
#define _FP_MINFRAC_1 1 |
#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE)0) |
/* |
* Unpack the raw bits of a native fp value. Do not classify or |
* normalize the data. |
*/ |
#define _FP_UNPACK_RAW_1(fs, X, val) \ |
do { \ |
union _FP_UNION_##fs _flo; _flo.flt = (val); \ |
\ |
X##_f = _flo.bits.frac; \ |
X##_e = _flo.bits.exp; \ |
X##_s = _flo.bits.sign; \ |
} while (0) |
#define _FP_UNPACK_RAW_1_P(fs, X, val) \ |
do { \ |
union _FP_UNION_##fs *_flo = \ |
(union _FP_UNION_##fs *)(val); \ |
\ |
X##_f = _flo->bits.frac; \ |
X##_e = _flo->bits.exp; \ |
X##_s = _flo->bits.sign; \ |
} while (0) |
/* |
* Repack the raw bits of a native fp value. |
*/ |
#define _FP_PACK_RAW_1(fs, val, X) \ |
do { \ |
union _FP_UNION_##fs _flo; \ |
\ |
_flo.bits.frac = X##_f; \ |
_flo.bits.exp = X##_e; \ |
_flo.bits.sign = X##_s; \ |
\ |
(val) = _flo.flt; \ |
} while (0) |
#define _FP_PACK_RAW_1_P(fs, val, X) \ |
do { \ |
union _FP_UNION_##fs *_flo = \ |
(union _FP_UNION_##fs *)(val); \ |
\ |
_flo->bits.frac = X##_f; \ |
_flo->bits.exp = X##_e; \ |
_flo->bits.sign = X##_s; \ |
} while (0) |
/* |
* Multiplication algorithms: |
*/ |
/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the |
multiplication immediately. */ |
#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \ |
do { \ |
R##_f = X##_f * Y##_f; \ |
/* Normalize since we know where the msb of the multiplicands \ |
were (bit B), we know that the msb of the of the product is \ |
at either 2B or 2B-1. */ \ |
_FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits); \ |
} while (0) |
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ |
#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \ |
do { \ |
_FP_W_TYPE _Z_f0, _Z_f1; \ |
doit(_Z_f1, _Z_f0, X##_f, Y##_f); \ |
/* Normalize since we know where the msb of the multiplicands \ |
were (bit B), we know that the msb of the of the product is \ |
at either 2B or 2B-1. */ \ |
_FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits); \ |
R##_f = _Z_f0; \ |
} while (0) |
/* Finally, a simple widening multiply algorithm. What fun! */ |
#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \ |
do { \ |
_FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \ |
\ |
/* split the words in half */ \ |
_xh = X##_f >> (_FP_W_TYPE_SIZE/2); \ |
_xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \ |
_yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \ |
_yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \ |
\ |
/* multiply the pieces */ \ |
_z_f0 = _xl * _yl; \ |
_a_f0 = _xh * _yl; \ |
_a_f1 = _xl * _yh; \ |
_z_f1 = _xh * _yh; \ |
\ |
/* reassemble into two full words */ \ |
if ((_a_f0 += _a_f1) < _a_f1) \ |
_z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \ |
_a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \ |
_a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \ |
_FP_FRAC_ADD_2(_z, _z, _a); \ |
\ |
/* normalize */ \ |
_FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits); \ |
R##_f = _z_f0; \ |
} while (0) |
/* |
* Division algorithms: |
*/ |
/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the |
division immediately. Give this macro either _FP_DIV_HELP_imm for |
C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you |
choose will depend on what the compiler does with divrem4. */ |
#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \ |
do { \ |
_FP_W_TYPE _q, _r; \ |
X##_f <<= (X##_f < Y##_f \ |
? R##_e--, _FP_WFRACBITS_##fs \ |
: _FP_WFRACBITS_##fs - 1); \ |
doit(_q, _r, X##_f, Y##_f); \ |
R##_f = _q | (_r != 0); \ |
} while (0) |
/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd |
that may be useful in this situation. This first is for a primitive |
that requires normalization, the second for one that does not. Look |
for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */ |
#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \ |
do { \ |
_FP_W_TYPE _nh, _nl, _q, _r, _y; \ |
\ |
/* Normalize Y -- i.e. make the most significant bit set. */ \ |
_y = Y##_f << _FP_WFRACXBITS_##fs; \ |
\ |
/* Shift X op correspondingly high, that is, up one full word. */ \ |
if (X##_f < Y##_f) \ |
{ \ |
R##_e--; \ |
_nl = 0; \ |
_nh = X##_f; \ |
} \ |
else \ |
{ \ |
_nl = X##_f << (_FP_W_TYPE_SIZE - 1); \ |
_nh = X##_f >> 1; \ |
} \ |
\ |
udiv_qrnnd(_q, _r, _nh, _nl, _y); \ |
R##_f = _q | (_r != 0); \ |
} while (0) |
#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \ |
do { \ |
_FP_W_TYPE _nh, _nl, _q, _r; \ |
if (X##_f < Y##_f) \ |
{ \ |
R##_e--; \ |
_nl = X##_f << _FP_WFRACBITS_##fs; \ |
_nh = X##_f >> _FP_WFRACXBITS_##fs; \ |
} \ |
else \ |
{ \ |
_nl = X##_f << (_FP_WFRACBITS_##fs - 1); \ |
_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \ |
} \ |
udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \ |
R##_f = _q | (_r != 0); \ |
} while (0) |
/* |
* Square root algorithms: |
* We have just one right now, maybe Newton approximation |
* should be added for those machines where division is fast. |
*/ |
#define _FP_SQRT_MEAT_1(R, S, T, X, q) \ |
do { \ |
while (q != _FP_WORK_ROUND) \ |
{ \ |
T##_f = S##_f + q; \ |
if (T##_f <= X##_f) \ |
{ \ |
S##_f = T##_f + q; \ |
X##_f -= T##_f; \ |
R##_f += q; \ |
} \ |
_FP_FRAC_SLL_1(X, 1); \ |
q >>= 1; \ |
} \ |
if (X##_f) \ |
{ \ |
if (S##_f < X##_f) \ |
R##_f |= _FP_WORK_ROUND; \ |
R##_f |= _FP_WORK_STICKY; \ |
} \ |
} while (0) |
/* |
* Assembly/disassembly for converting to/from integral types. |
* No shifting or overflow handled here. |
*/ |
#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f) |
#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r) |
/* |
* Convert FP values between word sizes |
*/ |
#define _FP_FRAC_COPY_1_1(D, S) (D##_f = S##_f) |
/programs/develop/libraries/newlib/math/op-2.h |
---|
0,0 → 1,617 |
/* Software floating-point emulation. |
Basic two-word fraction declaration and manipulation. |
Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz), |
David S. Miller (davem@redhat.com) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1 |
#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1) |
#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I) |
#define _FP_FRAC_HIGH_2(X) (X##_f1) |
#define _FP_FRAC_LOW_2(X) (X##_f0) |
#define _FP_FRAC_WORD_2(X,w) (X##_f##w) |
#define _FP_FRAC_SLL_2(X,N) \ |
(void)(((N) < _FP_W_TYPE_SIZE) \ |
? ({ \ |
if (__builtin_constant_p(N) && (N) == 1) \ |
{ \ |
X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \ |
X##_f0 += X##_f0; \ |
} \ |
else \ |
{ \ |
X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \ |
X##_f0 <<= (N); \ |
} \ |
0; \ |
}) \ |
: ({ \ |
X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \ |
X##_f0 = 0; \ |
})) |
#define _FP_FRAC_SRL_2(X,N) \ |
(void)(((N) < _FP_W_TYPE_SIZE) \ |
? ({ \ |
X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \ |
X##_f1 >>= (N); \ |
}) \ |
: ({ \ |
X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \ |
X##_f1 = 0; \ |
})) |
/* Right shift with sticky-lsb. */ |
#define _FP_FRAC_SRST_2(X,S, N,sz) \ |
(void)(((N) < _FP_W_TYPE_SIZE) \ |
? ({ \ |
S = (__builtin_constant_p(N) && (N) == 1 \ |
? X##_f0 & 1 \ |
: (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0); \ |
X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N)); \ |
X##_f1 >>= (N); \ |
}) \ |
: ({ \ |
S = ((((N) == _FP_W_TYPE_SIZE \ |
? 0 \ |
: (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \ |
| X##_f0) != 0); \ |
X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE)); \ |
X##_f1 = 0; \ |
})) |
#define _FP_FRAC_SRS_2(X,N,sz) \ |
(void)(((N) < _FP_W_TYPE_SIZE) \ |
? ({ \ |
X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \ |
(__builtin_constant_p(N) && (N) == 1 \ |
? X##_f0 & 1 \ |
: (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \ |
X##_f1 >>= (N); \ |
}) \ |
: ({ \ |
X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \ |
((((N) == _FP_W_TYPE_SIZE \ |
? 0 \ |
: (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \ |
| X##_f0) != 0)); \ |
X##_f1 = 0; \ |
})) |
#define _FP_FRAC_ADDI_2(X,I) \ |
__FP_FRAC_ADDI_2(X##_f1, X##_f0, I) |
#define _FP_FRAC_ADD_2(R,X,Y) \ |
__FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) |
#define _FP_FRAC_SUB_2(R,X,Y) \ |
__FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) |
#define _FP_FRAC_DEC_2(X,Y) \ |
__FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0) |
#define _FP_FRAC_CLZ_2(R,X) \ |
do { \ |
if (X##_f1) \ |
__FP_CLZ(R,X##_f1); \ |
else \ |
{ \ |
__FP_CLZ(R,X##_f0); \ |
R += _FP_W_TYPE_SIZE; \ |
} \ |
} while(0) |
/* Predicates */ |
#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0) |
#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0) |
#define _FP_FRAC_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs) |
#define _FP_FRAC_CLEAR_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs) |
#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0) |
#define _FP_FRAC_GT_2(X, Y) \ |
(X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0)) |
#define _FP_FRAC_GE_2(X, Y) \ |
(X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0)) |
#define _FP_ZEROFRAC_2 0, 0 |
#define _FP_MINFRAC_2 0, 1 |
#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0) |
/* |
* Internals |
*/ |
#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1) |
#define __FP_CLZ_2(R, xh, xl) \ |
do { \ |
if (xh) \ |
__FP_CLZ(R,xh); \ |
else \ |
{ \ |
__FP_CLZ(R,xl); \ |
R += _FP_W_TYPE_SIZE; \ |
} \ |
} while(0) |
#if 0 |
#ifndef __FP_FRAC_ADDI_2 |
#define __FP_FRAC_ADDI_2(xh, xl, i) \ |
(xh += ((xl += i) < i)) |
#endif |
#ifndef __FP_FRAC_ADD_2 |
#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \ |
(rh = xh + yh + ((rl = xl + yl) < xl)) |
#endif |
#ifndef __FP_FRAC_SUB_2 |
#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \ |
(rh = xh - yh - ((rl = xl - yl) > xl)) |
#endif |
#ifndef __FP_FRAC_DEC_2 |
#define __FP_FRAC_DEC_2(xh, xl, yh, yl) \ |
do { \ |
UWtype _t = xl; \ |
xh -= yh + ((xl -= yl) > _t); \ |
} while (0) |
#endif |
#else |
#undef __FP_FRAC_ADDI_2 |
#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i) |
#undef __FP_FRAC_ADD_2 |
#define __FP_FRAC_ADD_2 add_ssaaaa |
#undef __FP_FRAC_SUB_2 |
#define __FP_FRAC_SUB_2 sub_ddmmss |
#undef __FP_FRAC_DEC_2 |
#define __FP_FRAC_DEC_2(xh, xl, yh, yl) sub_ddmmss(xh, xl, xh, xl, yh, yl) |
#endif |
/* |
* Unpack the raw bits of a native fp value. Do not classify or |
* normalize the data. |
*/ |
#define _FP_UNPACK_RAW_2(fs, X, val) \ |
do { \ |
union _FP_UNION_##fs _flo; _flo.flt = (val); \ |
\ |
X##_f0 = _flo.bits.frac0; \ |
X##_f1 = _flo.bits.frac1; \ |
X##_e = _flo.bits.exp; \ |
X##_s = _flo.bits.sign; \ |
} while (0) |
#define _FP_UNPACK_RAW_2_P(fs, X, val) \ |
do { \ |
union _FP_UNION_##fs *_flo = \ |
(union _FP_UNION_##fs *)(val); \ |
\ |
X##_f0 = _flo->bits.frac0; \ |
X##_f1 = _flo->bits.frac1; \ |
X##_e = _flo->bits.exp; \ |
X##_s = _flo->bits.sign; \ |
} while (0) |
/* |
* Repack the raw bits of a native fp value. |
*/ |
#define _FP_PACK_RAW_2(fs, val, X) \ |
do { \ |
union _FP_UNION_##fs _flo; \ |
\ |
_flo.bits.frac0 = X##_f0; \ |
_flo.bits.frac1 = X##_f1; \ |
_flo.bits.exp = X##_e; \ |
_flo.bits.sign = X##_s; \ |
\ |
(val) = _flo.flt; \ |
} while (0) |
#define _FP_PACK_RAW_2_P(fs, val, X) \ |
do { \ |
union _FP_UNION_##fs *_flo = \ |
(union _FP_UNION_##fs *)(val); \ |
\ |
_flo->bits.frac0 = X##_f0; \ |
_flo->bits.frac1 = X##_f1; \ |
_flo->bits.exp = X##_e; \ |
_flo->bits.sign = X##_s; \ |
} while (0) |
/* |
* Multiplication algorithms: |
*/ |
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ |
#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \ |
do { \ |
_FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ |
\ |
doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \ |
doit(_b_f1, _b_f0, X##_f0, Y##_f1); \ |
doit(_c_f1, _c_f0, X##_f1, Y##_f0); \ |
doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \ |
\ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0, \ |
_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_FP_FRAC_WORD_4(_z,1)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0, \ |
_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_FP_FRAC_WORD_4(_z,1)); \ |
\ |
/* Normalize since we know where the msb of the multiplicands \ |
were (bit B), we know that the msb of the of the product is \ |
at either 2B or 2B-1. */ \ |
_FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ |
R##_f0 = _FP_FRAC_WORD_4(_z,0); \ |
R##_f1 = _FP_FRAC_WORD_4(_z,1); \ |
} while (0) |
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. |
Do only 3 multiplications instead of four. This one is for machines |
where multiplication is much more expensive than subtraction. */ |
#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \ |
do { \ |
_FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ |
_FP_W_TYPE _d; \ |
int _c1, _c2; \ |
\ |
_b_f0 = X##_f0 + X##_f1; \ |
_c1 = _b_f0 < X##_f0; \ |
_b_f1 = Y##_f0 + Y##_f1; \ |
_c2 = _b_f1 < Y##_f0; \ |
doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \ |
doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1); \ |
doit(_c_f1, _c_f0, X##_f1, Y##_f1); \ |
\ |
_b_f0 &= -_c2; \ |
_b_f1 &= -_c1; \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d, \ |
0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1)); \ |
__FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_b_f0); \ |
__FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_b_f1); \ |
__FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_FP_FRAC_WORD_4(_z,1), \ |
0, _d, _FP_FRAC_WORD_4(_z,0)); \ |
__FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ |
_FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0); \ |
__FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), \ |
_c_f1, _c_f0, \ |
_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2)); \ |
\ |
/* Normalize since we know where the msb of the multiplicands \ |
were (bit B), we know that the msb of the of the product is \ |
at either 2B or 2B-1. */ \ |
_FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ |
R##_f0 = _FP_FRAC_WORD_4(_z,0); \ |
R##_f1 = _FP_FRAC_WORD_4(_z,1); \ |
} while (0) |
#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y) \ |
do { \ |
_FP_FRAC_DECL_4(_z); \ |
_FP_W_TYPE _x[2], _y[2]; \ |
_x[0] = X##_f0; _x[1] = X##_f1; \ |
_y[0] = Y##_f0; _y[1] = Y##_f1; \ |
\ |
mpn_mul_n(_z_f, _x, _y, 2); \ |
\ |
/* Normalize since we know where the msb of the multiplicands \ |
were (bit B), we know that the msb of the of the product is \ |
at either 2B or 2B-1. */ \ |
_FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ |
R##_f0 = _z_f[0]; \ |
R##_f1 = _z_f[1]; \ |
} while (0) |
/* Do at most 120x120=240 bits multiplication using double floating |
point multiplication. This is useful if floating point |
multiplication has much bigger throughput than integer multiply. |
It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits |
between 106 and 120 only. |
Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set. |
SETFETZ is a macro which will disable all FPU exceptions and set rounding |
towards zero, RESETFE should optionally reset it back. */ |
#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \ |
do { \ |
static const double _const[] = { \ |
/* 2^-24 */ 5.9604644775390625e-08, \ |
/* 2^-48 */ 3.5527136788005009e-15, \ |
/* 2^-72 */ 2.1175823681357508e-22, \ |
/* 2^-96 */ 1.2621774483536189e-29, \ |
/* 2^28 */ 2.68435456e+08, \ |
/* 2^4 */ 1.600000e+01, \ |
/* 2^-20 */ 9.5367431640625e-07, \ |
/* 2^-44 */ 5.6843418860808015e-14, \ |
/* 2^-68 */ 3.3881317890172014e-21, \ |
/* 2^-92 */ 2.0194839173657902e-28, \ |
/* 2^-116 */ 1.2037062152420224e-35}; \ |
double _a240, _b240, _c240, _d240, _e240, _f240, \ |
_g240, _h240, _i240, _j240, _k240; \ |
union { double d; UDItype i; } _l240, _m240, _n240, _o240, \ |
_p240, _q240, _r240, _s240; \ |
UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \ |
\ |
if (wfracbits < 106 || wfracbits > 120) \ |
abort(); \ |
\ |
setfetz; \ |
\ |
_e240 = (double)(long)(X##_f0 & 0xffffff); \ |
_j240 = (double)(long)(Y##_f0 & 0xffffff); \ |
_d240 = (double)(long)((X##_f0 >> 24) & 0xffffff); \ |
_i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff); \ |
_c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \ |
_h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \ |
_b240 = (double)(long)((X##_f1 >> 8) & 0xffffff); \ |
_g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff); \ |
_a240 = (double)(long)(X##_f1 >> 32); \ |
_f240 = (double)(long)(Y##_f1 >> 32); \ |
_e240 *= _const[3]; \ |
_j240 *= _const[3]; \ |
_d240 *= _const[2]; \ |
_i240 *= _const[2]; \ |
_c240 *= _const[1]; \ |
_h240 *= _const[1]; \ |
_b240 *= _const[0]; \ |
_g240 *= _const[0]; \ |
_s240.d = _e240*_j240;\ |
_r240.d = _d240*_j240 + _e240*_i240;\ |
_q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240;\ |
_p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\ |
_o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\ |
_n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \ |
_m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \ |
_l240.d = _a240*_g240 + _b240*_f240; \ |
_k240 = _a240*_f240; \ |
_r240.d += _s240.d; \ |
_q240.d += _r240.d; \ |
_p240.d += _q240.d; \ |
_o240.d += _p240.d; \ |
_n240.d += _o240.d; \ |
_m240.d += _n240.d; \ |
_l240.d += _m240.d; \ |
_k240 += _l240.d; \ |
_s240.d -= ((_const[10]+_s240.d)-_const[10]); \ |
_r240.d -= ((_const[9]+_r240.d)-_const[9]); \ |
_q240.d -= ((_const[8]+_q240.d)-_const[8]); \ |
_p240.d -= ((_const[7]+_p240.d)-_const[7]); \ |
_o240.d += _const[7]; \ |
_n240.d += _const[6]; \ |
_m240.d += _const[5]; \ |
_l240.d += _const[4]; \ |
if (_s240.d != 0.0) _y240 = 1; \ |
if (_r240.d != 0.0) _y240 = 1; \ |
if (_q240.d != 0.0) _y240 = 1; \ |
if (_p240.d != 0.0) _y240 = 1; \ |
_t240 = (DItype)_k240; \ |
_u240 = _l240.i; \ |
_v240 = _m240.i; \ |
_w240 = _n240.i; \ |
_x240 = _o240.i; \ |
R##_f1 = (_t240 << (128 - (wfracbits - 1))) \ |
| ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104)); \ |
R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \ |
| ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \ |
| ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \ |
| ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \ |
| _y240; \ |
resetfe; \ |
} while (0) |
/* |
* Division algorithms: |
*/ |
#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y) \ |
do { \ |
_FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0; \ |
if (_FP_FRAC_GT_2(X, Y)) \ |
{ \ |
_n_f2 = X##_f1 >> 1; \ |
_n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \ |
_n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \ |
} \ |
else \ |
{ \ |
R##_e--; \ |
_n_f2 = X##_f1; \ |
_n_f1 = X##_f0; \ |
_n_f0 = 0; \ |
} \ |
\ |
/* Normalize, i.e. make the most significant bit of the \ |
denominator set. */ \ |
_FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs); \ |
\ |
udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1); \ |
umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0); \ |
_r_f0 = _n_f0; \ |
if (_FP_FRAC_GT_2(_m, _r)) \ |
{ \ |
R##_f1--; \ |
_FP_FRAC_ADD_2(_r, Y, _r); \ |
if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \ |
{ \ |
R##_f1--; \ |
_FP_FRAC_ADD_2(_r, Y, _r); \ |
} \ |
} \ |
_FP_FRAC_DEC_2(_r, _m); \ |
\ |
if (_r_f1 == Y##_f1) \ |
{ \ |
/* This is a special case, not an optimization \ |
(_r/Y##_f1 would not fit into UWtype). \ |
As _r is guaranteed to be < Y, R##_f0 can be either \ |
(UWtype)-1 or (UWtype)-2. But as we know what kind \ |
of bits it is (sticky, guard, round), we don't care. \ |
We also don't care what the reminder is, because the \ |
guard bit will be set anyway. -jj */ \ |
R##_f0 = -1; \ |
} \ |
else \ |
{ \ |
udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1); \ |
umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0); \ |
_r_f0 = 0; \ |
if (_FP_FRAC_GT_2(_m, _r)) \ |
{ \ |
R##_f0--; \ |
_FP_FRAC_ADD_2(_r, Y, _r); \ |
if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \ |
{ \ |
R##_f0--; \ |
_FP_FRAC_ADD_2(_r, Y, _r); \ |
} \ |
} \ |
if (!_FP_FRAC_EQ_2(_r, _m)) \ |
R##_f0 |= _FP_WORK_STICKY; \ |
} \ |
} while (0) |
#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \ |
do { \ |
_FP_W_TYPE _x[4], _y[2], _z[4]; \ |
_y[0] = Y##_f0; _y[1] = Y##_f1; \ |
_x[0] = _x[3] = 0; \ |
if (_FP_FRAC_GT_2(X, Y)) \ |
{ \ |
R##_e++; \ |
_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) | \ |
X##_f1 >> (_FP_W_TYPE_SIZE - \ |
(_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE))); \ |
_x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE); \ |
} \ |
else \ |
{ \ |
_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) | \ |
X##_f1 >> (_FP_W_TYPE_SIZE - \ |
(_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE))); \ |
_x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE); \ |
} \ |
\ |
(void) mpn_divrem (_z, 0, _x, 4, _y, 2); \ |
R##_f1 = _z[1]; \ |
R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \ |
} while (0) |
/* |
* Square root algorithms: |
* We have just one right now, maybe Newton approximation |
* should be added for those machines where division is fast. |
*/ |
#define _FP_SQRT_MEAT_2(R, S, T, X, q) \ |
do { \ |
while (q) \ |
{ \ |
T##_f1 = S##_f1 + q; \ |
if (T##_f1 <= X##_f1) \ |
{ \ |
S##_f1 = T##_f1 + q; \ |
X##_f1 -= T##_f1; \ |
R##_f1 += q; \ |
} \ |
_FP_FRAC_SLL_2(X, 1); \ |
q >>= 1; \ |
} \ |
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ |
while (q != _FP_WORK_ROUND) \ |
{ \ |
T##_f0 = S##_f0 + q; \ |
T##_f1 = S##_f1; \ |
if (T##_f1 < X##_f1 || \ |
(T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \ |
{ \ |
S##_f0 = T##_f0 + q; \ |
S##_f1 += (T##_f0 > S##_f0); \ |
_FP_FRAC_DEC_2(X, T); \ |
R##_f0 += q; \ |
} \ |
_FP_FRAC_SLL_2(X, 1); \ |
q >>= 1; \ |
} \ |
if (X##_f0 | X##_f1) \ |
{ \ |
if (S##_f1 < X##_f1 || \ |
(S##_f1 == X##_f1 && S##_f0 < X##_f0)) \ |
R##_f0 |= _FP_WORK_ROUND; \ |
R##_f0 |= _FP_WORK_STICKY; \ |
} \ |
} while (0) |
/* |
* Assembly/disassembly for converting to/from integral types. |
* No shifting or overflow handled here. |
*/ |
#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \ |
(void)((rsize <= _FP_W_TYPE_SIZE) \ |
? ({ r = X##_f0; }) \ |
: ({ \ |
r = X##_f1; \ |
r <<= _FP_W_TYPE_SIZE; \ |
r += X##_f0; \ |
})) |
#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \ |
do { \ |
X##_f0 = r; \ |
X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ |
} while (0) |
/* |
* Convert FP values between word sizes |
*/ |
#define _FP_FRAC_COPY_1_2(D, S) (D##_f = S##_f0) |
#define _FP_FRAC_COPY_2_1(D, S) ((D##_f0 = S##_f), (D##_f1 = 0)) |
#define _FP_FRAC_COPY_2_2(D,S) _FP_FRAC_COPY_2(D,S) |
/programs/develop/libraries/newlib/math/op-4.h |
---|
0,0 → 1,688 |
/* Software floating-point emulation. |
Basic four-word fraction declaration and manipulation. |
Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz), |
David S. Miller (davem@redhat.com) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4] |
#define _FP_FRAC_COPY_4(D,S) \ |
(D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \ |
D##_f[2] = S##_f[2], D##_f[3] = S##_f[3]) |
#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I) |
#define _FP_FRAC_HIGH_4(X) (X##_f[3]) |
#define _FP_FRAC_LOW_4(X) (X##_f[0]) |
#define _FP_FRAC_WORD_4(X,w) (X##_f[w]) |
#define _FP_FRAC_SLL_4(X,N) \ |
do { \ |
_FP_I_TYPE _up, _down, _skip, _i; \ |
_skip = (N) / _FP_W_TYPE_SIZE; \ |
_up = (N) % _FP_W_TYPE_SIZE; \ |
_down = _FP_W_TYPE_SIZE - _up; \ |
if (!_up) \ |
for (_i = 3; _i >= _skip; --_i) \ |
X##_f[_i] = X##_f[_i-_skip]; \ |
else \ |
{ \ |
for (_i = 3; _i > _skip; --_i) \ |
X##_f[_i] = X##_f[_i-_skip] << _up \ |
| X##_f[_i-_skip-1] >> _down; \ |
X##_f[_i--] = X##_f[0] << _up; \ |
} \ |
for (; _i >= 0; --_i) \ |
X##_f[_i] = 0; \ |
} while (0) |
/* This one was broken too */ |
#define _FP_FRAC_SRL_4(X,N) \ |
do { \ |
_FP_I_TYPE _up, _down, _skip, _i; \ |
_skip = (N) / _FP_W_TYPE_SIZE; \ |
_down = (N) % _FP_W_TYPE_SIZE; \ |
_up = _FP_W_TYPE_SIZE - _down; \ |
if (!_down) \ |
for (_i = 0; _i <= 3-_skip; ++_i) \ |
X##_f[_i] = X##_f[_i+_skip]; \ |
else \ |
{ \ |
for (_i = 0; _i < 3-_skip; ++_i) \ |
X##_f[_i] = X##_f[_i+_skip] >> _down \ |
| X##_f[_i+_skip+1] << _up; \ |
X##_f[_i++] = X##_f[3] >> _down; \ |
} \ |
for (; _i < 4; ++_i) \ |
X##_f[_i] = 0; \ |
} while (0) |
/* Right shift with sticky-lsb. |
* What this actually means is that we do a standard right-shift, |
* but that if any of the bits that fall off the right hand side |
* were one then we always set the LSbit. |
*/ |
#define _FP_FRAC_SRST_4(X,S,N,size) \ |
do { \ |
_FP_I_TYPE _up, _down, _skip, _i; \ |
_FP_W_TYPE _s; \ |
_skip = (N) / _FP_W_TYPE_SIZE; \ |
_down = (N) % _FP_W_TYPE_SIZE; \ |
_up = _FP_W_TYPE_SIZE - _down; \ |
for (_s = _i = 0; _i < _skip; ++_i) \ |
_s |= X##_f[_i]; \ |
if (!_down) \ |
for (_i = 0; _i <= 3-_skip; ++_i) \ |
X##_f[_i] = X##_f[_i+_skip]; \ |
else \ |
{ \ |
_s |= X##_f[_i] << _up; \ |
for (_i = 0; _i < 3-_skip; ++_i) \ |
X##_f[_i] = X##_f[_i+_skip] >> _down \ |
| X##_f[_i+_skip+1] << _up; \ |
X##_f[_i++] = X##_f[3] >> _down; \ |
} \ |
for (; _i < 4; ++_i) \ |
X##_f[_i] = 0; \ |
S = (_s != 0); \ |
} while (0) |
#define _FP_FRAC_SRS_4(X,N,size) \ |
do { \ |
int _sticky; \ |
_FP_FRAC_SRST_4(X, _sticky, N, size); \ |
X##_f[0] |= _sticky; \ |
} while (0) |
#define _FP_FRAC_ADD_4(R,X,Y) \ |
__FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ |
X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ |
Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) |
#define _FP_FRAC_SUB_4(R,X,Y) \ |
__FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ |
X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ |
Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) |
#define _FP_FRAC_DEC_4(X,Y) \ |
__FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ |
Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) |
#define _FP_FRAC_ADDI_4(X,I) \ |
__FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I) |
#define _FP_ZEROFRAC_4 0,0,0,0 |
#define _FP_MINFRAC_4 0,0,0,1 |
#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0) |
#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0) |
#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0) |
#define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs) |
#define _FP_FRAC_CLEAR_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs) |
#define _FP_FRAC_EQ_4(X,Y) \ |
(X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \ |
&& X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3]) |
#define _FP_FRAC_GT_4(X,Y) \ |
(X##_f[3] > Y##_f[3] || \ |
(X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ |
(X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ |
(X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \ |
)) \ |
)) \ |
) |
#define _FP_FRAC_GE_4(X,Y) \ |
(X##_f[3] > Y##_f[3] || \ |
(X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ |
(X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ |
(X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \ |
)) \ |
)) \ |
) |
#define _FP_FRAC_CLZ_4(R,X) \ |
do { \ |
if (X##_f[3]) \ |
{ \ |
__FP_CLZ(R,X##_f[3]); \ |
} \ |
else if (X##_f[2]) \ |
{ \ |
__FP_CLZ(R,X##_f[2]); \ |
R += _FP_W_TYPE_SIZE; \ |
} \ |
else if (X##_f[1]) \ |
{ \ |
__FP_CLZ(R,X##_f[1]); \ |
R += _FP_W_TYPE_SIZE*2; \ |
} \ |
else \ |
{ \ |
__FP_CLZ(R,X##_f[0]); \ |
R += _FP_W_TYPE_SIZE*3; \ |
} \ |
} while(0) |
#define _FP_UNPACK_RAW_4(fs, X, val) \ |
do { \ |
union _FP_UNION_##fs _flo; _flo.flt = (val); \ |
X##_f[0] = _flo.bits.frac0; \ |
X##_f[1] = _flo.bits.frac1; \ |
X##_f[2] = _flo.bits.frac2; \ |
X##_f[3] = _flo.bits.frac3; \ |
X##_e = _flo.bits.exp; \ |
X##_s = _flo.bits.sign; \ |
} while (0) |
#define _FP_UNPACK_RAW_4_P(fs, X, val) \ |
do { \ |
union _FP_UNION_##fs *_flo = \ |
(union _FP_UNION_##fs *)(val); \ |
\ |
X##_f[0] = _flo->bits.frac0; \ |
X##_f[1] = _flo->bits.frac1; \ |
X##_f[2] = _flo->bits.frac2; \ |
X##_f[3] = _flo->bits.frac3; \ |
X##_e = _flo->bits.exp; \ |
X##_s = _flo->bits.sign; \ |
} while (0) |
#define _FP_PACK_RAW_4(fs, val, X) \ |
do { \ |
union _FP_UNION_##fs _flo; \ |
_flo.bits.frac0 = X##_f[0]; \ |
_flo.bits.frac1 = X##_f[1]; \ |
_flo.bits.frac2 = X##_f[2]; \ |
_flo.bits.frac3 = X##_f[3]; \ |
_flo.bits.exp = X##_e; \ |
_flo.bits.sign = X##_s; \ |
(val) = _flo.flt; \ |
} while (0) |
#define _FP_PACK_RAW_4_P(fs, val, X) \ |
do { \ |
union _FP_UNION_##fs *_flo = \ |
(union _FP_UNION_##fs *)(val); \ |
\ |
_flo->bits.frac0 = X##_f[0]; \ |
_flo->bits.frac1 = X##_f[1]; \ |
_flo->bits.frac2 = X##_f[2]; \ |
_flo->bits.frac3 = X##_f[3]; \ |
_flo->bits.exp = X##_e; \ |
_flo->bits.sign = X##_s; \ |
} while (0) |
/* |
* Multiplication algorithms: |
*/ |
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ |
#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \ |
do { \ |
_FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ |
_FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \ |
\ |
doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \ |
doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]); \ |
doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]); \ |
doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]); \ |
doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]); \ |
doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ |
_FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0, \ |
0,0,_FP_FRAC_WORD_8(_z,1)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ |
_FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0, \ |
_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ |
_FP_FRAC_WORD_8(_z,1)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ |
_FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0, \ |
0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ |
_FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0, \ |
_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ |
_FP_FRAC_WORD_8(_z,2)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ |
_FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0, \ |
_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ |
_FP_FRAC_WORD_8(_z,2)); \ |
doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]); \ |
doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]); \ |
doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]); \ |
doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ |
_FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0, \ |
0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ |
_FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0, \ |
_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ |
_FP_FRAC_WORD_8(_z,3)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ |
_FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0, \ |
_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ |
_FP_FRAC_WORD_8(_z,3)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ |
_FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0, \ |
_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ |
_FP_FRAC_WORD_8(_z,3)); \ |
doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]); \ |
doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]); \ |
doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]); \ |
doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]); \ |
doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ |
_FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0, \ |
0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ |
_FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0, \ |
_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ |
_FP_FRAC_WORD_8(_z,4)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ |
_FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0, \ |
_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ |
_FP_FRAC_WORD_8(_z,4)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ |
_FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0, \ |
0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5)); \ |
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ |
_FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0, \ |
_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ |
_FP_FRAC_WORD_8(_z,5)); \ |
doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]); \ |
__FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ |
_b_f1,_b_f0, \ |
_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6)); \ |
\ |
/* Normalize since we know where the msb of the multiplicands \ |
were (bit B), we know that the msb of the of the product is \ |
at either 2B or 2B-1. */ \ |
_FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \ |
__FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \ |
_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \ |
} while (0) |
#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \ |
do { \ |
_FP_FRAC_DECL_8(_z); \ |
\ |
mpn_mul_n(_z_f, _x_f, _y_f, 4); \ |
\ |
/* Normalize since we know where the msb of the multiplicands \ |
were (bit B), we know that the msb of the of the product is \ |
at either 2B or 2B-1. */ \ |
_FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \ |
__FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \ |
_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \ |
} while (0) |
/* |
* Helper utility for _FP_DIV_MEAT_4_udiv: |
* pppp = m * nnn |
*/ |
#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0) \ |
do { \ |
UWtype _t; \ |
umul_ppmm(p1,p0,m,n0); \ |
umul_ppmm(p2,_t,m,n1); \ |
__FP_FRAC_ADDI_2(p2,p1,_t); \ |
umul_ppmm(p3,_t,m,n2); \ |
__FP_FRAC_ADDI_2(p3,p2,_t); \ |
} while (0) |
/* |
* Division algorithms: |
*/ |
#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \ |
do { \ |
int _i; \ |
_FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m); \ |
_FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4); \ |
if (_FP_FRAC_GT_4(X, Y)) \ |
{ \ |
_n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \ |
_FP_FRAC_SRL_4(X, 1); \ |
} \ |
else \ |
R##_e--; \ |
\ |
/* Normalize, i.e. make the most significant bit of the \ |
denominator set. */ \ |
_FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs); \ |
\ |
for (_i = 3; ; _i--) \ |
{ \ |
if (X##_f[3] == Y##_f[3]) \ |
{ \ |
/* This is a special case, not an optimization \ |
(X##_f[3]/Y##_f[3] would not fit into UWtype). \ |
As X## is guaranteed to be < Y, R##_f[_i] can be either \ |
(UWtype)-1 or (UWtype)-2. */ \ |
R##_f[_i] = -1; \ |
if (!_i) \ |
break; \ |
__FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ |
Y##_f[2], Y##_f[1], Y##_f[0], 0, \ |
X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \ |
_FP_FRAC_SUB_4(X, Y, X); \ |
if (X##_f[3] > Y##_f[3]) \ |
{ \ |
R##_f[_i] = -2; \ |
_FP_FRAC_ADD_4(X, Y, X); \ |
} \ |
} \ |
else \ |
{ \ |
udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \ |
umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0], \ |
R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \ |
X##_f[2] = X##_f[1]; \ |
X##_f[1] = X##_f[0]; \ |
X##_f[0] = _n_f[_i]; \ |
if (_FP_FRAC_GT_4(_m, X)) \ |
{ \ |
R##_f[_i]--; \ |
_FP_FRAC_ADD_4(X, Y, X); \ |
if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X)) \ |
{ \ |
R##_f[_i]--; \ |
_FP_FRAC_ADD_4(X, Y, X); \ |
} \ |
} \ |
_FP_FRAC_DEC_4(X, _m); \ |
if (!_i) \ |
{ \ |
if (!_FP_FRAC_EQ_4(X, _m)) \ |
R##_f[0] |= _FP_WORK_STICKY; \ |
break; \ |
} \ |
} \ |
} \ |
} while (0) |
/* |
* Square root algorithms: |
* We have just one right now, maybe Newton approximation |
* should be added for those machines where division is fast. |
*/ |
#define _FP_SQRT_MEAT_4(R, S, T, X, q) \ |
do { \ |
while (q) \ |
{ \ |
T##_f[3] = S##_f[3] + q; \ |
if (T##_f[3] <= X##_f[3]) \ |
{ \ |
S##_f[3] = T##_f[3] + q; \ |
X##_f[3] -= T##_f[3]; \ |
R##_f[3] += q; \ |
} \ |
_FP_FRAC_SLL_4(X, 1); \ |
q >>= 1; \ |
} \ |
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ |
while (q) \ |
{ \ |
T##_f[2] = S##_f[2] + q; \ |
T##_f[3] = S##_f[3]; \ |
if (T##_f[3] < X##_f[3] || \ |
(T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \ |
{ \ |
S##_f[2] = T##_f[2] + q; \ |
S##_f[3] += (T##_f[2] > S##_f[2]); \ |
__FP_FRAC_DEC_2(X##_f[3], X##_f[2], \ |
T##_f[3], T##_f[2]); \ |
R##_f[2] += q; \ |
} \ |
_FP_FRAC_SLL_4(X, 1); \ |
q >>= 1; \ |
} \ |
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ |
while (q) \ |
{ \ |
T##_f[1] = S##_f[1] + q; \ |
T##_f[2] = S##_f[2]; \ |
T##_f[3] = S##_f[3]; \ |
if (T##_f[3] < X##_f[3] || \ |
(T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] || \ |
(T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1])))) \ |
{ \ |
S##_f[1] = T##_f[1] + q; \ |
S##_f[2] += (T##_f[1] > S##_f[1]); \ |
S##_f[3] += (T##_f[2] > S##_f[2]); \ |
__FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1], \ |
T##_f[3], T##_f[2], T##_f[1]); \ |
R##_f[1] += q; \ |
} \ |
_FP_FRAC_SLL_4(X, 1); \ |
q >>= 1; \ |
} \ |
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ |
while (q != _FP_WORK_ROUND) \ |
{ \ |
T##_f[0] = S##_f[0] + q; \ |
T##_f[1] = S##_f[1]; \ |
T##_f[2] = S##_f[2]; \ |
T##_f[3] = S##_f[3]; \ |
if (_FP_FRAC_GE_4(X,T)) \ |
{ \ |
S##_f[0] = T##_f[0] + q; \ |
S##_f[1] += (T##_f[0] > S##_f[0]); \ |
S##_f[2] += (T##_f[1] > S##_f[1]); \ |
S##_f[3] += (T##_f[2] > S##_f[2]); \ |
_FP_FRAC_DEC_4(X, T); \ |
R##_f[0] += q; \ |
} \ |
_FP_FRAC_SLL_4(X, 1); \ |
q >>= 1; \ |
} \ |
if (!_FP_FRAC_ZEROP_4(X)) \ |
{ \ |
if (_FP_FRAC_GT_4(X,S)) \ |
R##_f[0] |= _FP_WORK_ROUND; \ |
R##_f[0] |= _FP_WORK_STICKY; \ |
} \ |
} while (0) |
/* |
* Internals |
*/ |
#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \ |
(X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) |
#ifndef __FP_FRAC_ADD_3 |
#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ |
do { \ |
_FP_W_TYPE _c1, _c2; \ |
r0 = x0 + y0; \ |
_c1 = r0 < x0; \ |
r1 = x1 + y1; \ |
_c2 = r1 < x1; \ |
r1 += _c1; \ |
_c2 |= r1 < _c1; \ |
r2 = x2 + y2 + _c2; \ |
} while (0) |
#endif |
#ifndef __FP_FRAC_ADD_4 |
#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ |
do { \ |
_FP_W_TYPE _c1, _c2, _c3; \ |
r0 = x0 + y0; \ |
_c1 = r0 < x0; \ |
r1 = x1 + y1; \ |
_c2 = r1 < x1; \ |
r1 += _c1; \ |
_c2 |= r1 < _c1; \ |
r2 = x2 + y2; \ |
_c3 = r2 < x2; \ |
r2 += _c2; \ |
_c3 |= r2 < _c2; \ |
r3 = x3 + y3 + _c3; \ |
} while (0) |
#endif |
#ifndef __FP_FRAC_SUB_3 |
#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ |
do { \ |
_FP_W_TYPE _c1, _c2; \ |
r0 = x0 - y0; \ |
_c1 = r0 > x0; \ |
r1 = x1 - y1; \ |
_c2 = r1 > x1; \ |
r1 -= _c1; \ |
_c2 |= _c1 && (y1 == x1); \ |
r2 = x2 - y2 - _c2; \ |
} while (0) |
#endif |
#ifndef __FP_FRAC_SUB_4 |
#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ |
do { \ |
_FP_W_TYPE _c1, _c2, _c3; \ |
r0 = x0 - y0; \ |
_c1 = r0 > x0; \ |
r1 = x1 - y1; \ |
_c2 = r1 > x1; \ |
r1 -= _c1; \ |
_c2 |= _c1 && (y1 == x1); \ |
r2 = x2 - y2; \ |
_c3 = r2 > x2; \ |
r2 -= _c2; \ |
_c3 |= _c2 && (y2 == x2); \ |
r3 = x3 - y3 - _c3; \ |
} while (0) |
#endif |
#ifndef __FP_FRAC_DEC_3 |
#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \ |
do { \ |
UWtype _t0, _t1, _t2; \ |
_t0 = x0, _t1 = x1, _t2 = x2; \ |
__FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \ |
} while (0) |
#endif |
#ifndef __FP_FRAC_DEC_4 |
#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \ |
do { \ |
UWtype _t0, _t1, _t2, _t3; \ |
_t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \ |
__FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0); \ |
} while (0) |
#endif |
#ifndef __FP_FRAC_ADDI_4 |
#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \ |
do { \ |
UWtype _t; \ |
_t = ((x0 += i) < i); \ |
x1 += _t; _t = (x1 < _t); \ |
x2 += _t; _t = (x2 < _t); \ |
x3 += _t; \ |
} while (0) |
#endif |
/* Convert FP values between word sizes. This appears to be more |
* complicated than I'd have expected it to be, so these might be |
* wrong... These macros are in any case somewhat bogus because they |
* use information about what various FRAC_n variables look like |
* internally [eg, that 2 word vars are X_f0 and x_f1]. But so do |
* the ones in op-2.h and op-1.h. |
*/ |
#define _FP_FRAC_COPY_1_4(D, S) (D##_f = S##_f[0]) |
#define _FP_FRAC_COPY_2_4(D, S) \ |
do { \ |
D##_f0 = S##_f[0]; \ |
D##_f1 = S##_f[1]; \ |
} while (0) |
/* Assembly/disassembly for converting to/from integral types. |
* No shifting or overflow handled here. |
*/ |
/* Put the FP value X into r, which is an integer of size rsize. */ |
#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \ |
do { \ |
if (rsize <= _FP_W_TYPE_SIZE) \ |
r = X##_f[0]; \ |
else if (rsize <= 2*_FP_W_TYPE_SIZE) \ |
{ \ |
r = X##_f[1]; \ |
r <<= _FP_W_TYPE_SIZE; \ |
r += X##_f[0]; \ |
} \ |
else \ |
{ \ |
/* I'm feeling lazy so we deal with int == 3words (implausible)*/ \ |
/* and int == 4words as a single case. */ \ |
r = X##_f[3]; \ |
r <<= _FP_W_TYPE_SIZE; \ |
r += X##_f[2]; \ |
r <<= _FP_W_TYPE_SIZE; \ |
r += X##_f[1]; \ |
r <<= _FP_W_TYPE_SIZE; \ |
r += X##_f[0]; \ |
} \ |
} while (0) |
/* "No disassemble Number Five!" */ |
/* move an integer of size rsize into X's fractional part. We rely on |
* the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid |
* having to mask the values we store into it. |
*/ |
#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \ |
do { \ |
X##_f[0] = r; \ |
X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ |
X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \ |
X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \ |
} while (0); |
#define _FP_FRAC_COPY_4_1(D, S) \ |
do { \ |
D##_f[0] = S##_f; \ |
D##_f[1] = D##_f[2] = D##_f[3] = 0; \ |
} while (0) |
#define _FP_FRAC_COPY_4_2(D, S) \ |
do { \ |
D##_f[0] = S##_f0; \ |
D##_f[1] = S##_f1; \ |
D##_f[2] = D##_f[3] = 0; \ |
} while (0) |
#define _FP_FRAC_COPY_4_4(D,S) _FP_FRAC_COPY_4(D,S) |
/programs/develop/libraries/newlib/math/op-8.h |
---|
0,0 → 1,111 |
/* Software floating-point emulation. |
Basic eight-word fraction declaration and manipulation. |
Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
/* We need just a few things from here for op-4, if we ever need some |
other macros, they can be added. */ |
#define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8] |
#define _FP_FRAC_HIGH_8(X) (X##_f[7]) |
#define _FP_FRAC_LOW_8(X) (X##_f[0]) |
#define _FP_FRAC_WORD_8(X,w) (X##_f[w]) |
#define _FP_FRAC_SLL_8(X,N) \ |
do { \ |
_FP_I_TYPE _up, _down, _skip, _i; \ |
_skip = (N) / _FP_W_TYPE_SIZE; \ |
_up = (N) % _FP_W_TYPE_SIZE; \ |
_down = _FP_W_TYPE_SIZE - _up; \ |
if (!_up) \ |
for (_i = 7; _i >= _skip; --_i) \ |
X##_f[_i] = X##_f[_i-_skip]; \ |
else \ |
{ \ |
for (_i = 7; _i > _skip; --_i) \ |
X##_f[_i] = X##_f[_i-_skip] << _up \ |
| X##_f[_i-_skip-1] >> _down; \ |
X##_f[_i--] = X##_f[0] << _up; \ |
} \ |
for (; _i >= 0; --_i) \ |
X##_f[_i] = 0; \ |
} while (0) |
#define _FP_FRAC_SRL_8(X,N) \ |
do { \ |
_FP_I_TYPE _up, _down, _skip, _i; \ |
_skip = (N) / _FP_W_TYPE_SIZE; \ |
_down = (N) % _FP_W_TYPE_SIZE; \ |
_up = _FP_W_TYPE_SIZE - _down; \ |
if (!_down) \ |
for (_i = 0; _i <= 7-_skip; ++_i) \ |
X##_f[_i] = X##_f[_i+_skip]; \ |
else \ |
{ \ |
for (_i = 0; _i < 7-_skip; ++_i) \ |
X##_f[_i] = X##_f[_i+_skip] >> _down \ |
| X##_f[_i+_skip+1] << _up; \ |
X##_f[_i++] = X##_f[7] >> _down; \ |
} \ |
for (; _i < 8; ++_i) \ |
X##_f[_i] = 0; \ |
} while (0) |
/* Right shift with sticky-lsb. |
* What this actually means is that we do a standard right-shift, |
* but that if any of the bits that fall off the right hand side |
* were one then we always set the LSbit. |
*/ |
#define _FP_FRAC_SRS_8(X,N,size) \ |
do { \ |
_FP_I_TYPE _up, _down, _skip, _i; \ |
_FP_W_TYPE _s; \ |
_skip = (N) / _FP_W_TYPE_SIZE; \ |
_down = (N) % _FP_W_TYPE_SIZE; \ |
_up = _FP_W_TYPE_SIZE - _down; \ |
for (_s = _i = 0; _i < _skip; ++_i) \ |
_s |= X##_f[_i]; \ |
if (!_down) \ |
for (_i = 0; _i <= 7-_skip; ++_i) \ |
X##_f[_i] = X##_f[_i+_skip]; \ |
else \ |
{ \ |
_s |= X##_f[_i] << _up; \ |
for (_i = 0; _i < 7-_skip; ++_i) \ |
X##_f[_i] = X##_f[_i+_skip] >> _down \ |
| X##_f[_i+_skip+1] << _up; \ |
X##_f[_i++] = X##_f[7] >> _down; \ |
} \ |
for (; _i < 8; ++_i) \ |
X##_f[_i] = 0; \ |
/* don't fix the LSB until the very end when we're sure f[0] is stable */ \ |
X##_f[0] |= (_s != 0); \ |
} while (0) |
/programs/develop/libraries/newlib/math/op-common.h |
---|
0,0 → 1,1359 |
/* Software floating-point emulation. Common operations. |
Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz), |
David S. Miller (davem@redhat.com) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
#define _FP_DECL(wc, X) \ |
_FP_I_TYPE X##_c __attribute__((unused)), X##_s, X##_e; \ |
_FP_FRAC_DECL_##wc(X) |
/* |
* Finish truely unpacking a native fp value by classifying the kind |
* of fp value and normalizing both the exponent and the fraction. |
*/ |
#define _FP_UNPACK_CANONICAL(fs, wc, X) \ |
do { \ |
switch (X##_e) \ |
{ \ |
default: \ |
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \ |
_FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \ |
X##_e -= _FP_EXPBIAS_##fs; \ |
X##_c = FP_CLS_NORMAL; \ |
break; \ |
\ |
case 0: \ |
if (_FP_FRAC_ZEROP_##wc(X)) \ |
X##_c = FP_CLS_ZERO; \ |
else \ |
{ \ |
/* a denormalized number */ \ |
_FP_I_TYPE _shift; \ |
_FP_FRAC_CLZ_##wc(_shift, X); \ |
_shift -= _FP_FRACXBITS_##fs; \ |
_FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \ |
X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \ |
X##_c = FP_CLS_NORMAL; \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
} \ |
break; \ |
\ |
case _FP_EXPMAX_##fs: \ |
if (_FP_FRAC_ZEROP_##wc(X)) \ |
X##_c = FP_CLS_INF; \ |
else \ |
{ \ |
X##_c = FP_CLS_NAN; \ |
/* Check for signaling NaN */ \ |
if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
} \ |
break; \ |
} \ |
} while (0) |
/* Finish unpacking an fp value in semi-raw mode: the mantissa is |
shifted by _FP_WORKBITS but the implicit MSB is not inserted and |
other classification is not done. */ |
#define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc(X, _FP_WORKBITS) |
/* A semi-raw value has overflowed to infinity. Adjust the mantissa |
and exponent appropriately. */ |
#define _FP_OVERFLOW_SEMIRAW(fs, wc, X) \ |
do { \ |
if (FP_ROUNDMODE == FP_RND_NEAREST \ |
|| (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \ |
|| (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \ |
{ \ |
X##_e = _FP_EXPMAX_##fs; \ |
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ |
} \ |
else \ |
{ \ |
X##_e = _FP_EXPMAX_##fs - 1; \ |
_FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \ |
} \ |
FP_SET_EXCEPTION(FP_EX_INEXACT); \ |
FP_SET_EXCEPTION(FP_EX_OVERFLOW); \ |
} while (0) |
/* Check for a semi-raw value being a signaling NaN and raise the |
invalid exception if so. */ |
#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \ |
do { \ |
if (X##_e == _FP_EXPMAX_##fs \ |
&& !_FP_FRAC_ZEROP_##wc(X) \ |
&& !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs)) \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
} while (0) |
/* Choose a NaN result from an operation on two semi-raw NaN |
values. */ |
#define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP) \ |
do { \ |
/* _FP_CHOOSENAN expects raw values, so shift as required. */ \ |
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ |
_FP_FRAC_SRL_##wc(Y, _FP_WORKBITS); \ |
_FP_CHOOSENAN(fs, wc, R, X, Y, OP); \ |
_FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \ |
} while (0) |
/* Test whether a biased exponent is normal (not zero or maximum). */ |
#define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1) |
/* Prepare to pack an fp value in semi-raw mode: the mantissa is |
rounded and shifted right, with the rounding possibly increasing |
the exponent (including changing a finite value to infinity). */ |
#define _FP_PACK_SEMIRAW(fs, wc, X) \ |
do { \ |
_FP_ROUND(wc, X); \ |
if (_FP_FRAC_HIGH_##fs(X) \ |
& (_FP_OVERFLOW_##fs >> 1)) \ |
{ \ |
_FP_FRAC_HIGH_##fs(X) &= ~(_FP_OVERFLOW_##fs >> 1); \ |
X##_e++; \ |
if (X##_e == _FP_EXPMAX_##fs) \ |
_FP_OVERFLOW_SEMIRAW(fs, wc, X); \ |
} \ |
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ |
if (!_FP_EXP_NORMAL(fs, wc, X) && !_FP_FRAC_ZEROP_##wc(X)) \ |
{ \ |
if (X##_e == 0) \ |
FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ |
else \ |
{ \ |
if (!_FP_KEEPNANFRACP) \ |
{ \ |
_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \ |
X##_s = _FP_NANSIGN_##fs; \ |
} \ |
else \ |
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ |
} \ |
} \ |
} while (0) |
/* |
* Before packing the bits back into the native fp result, take care |
* of such mundane things as rounding and overflow. Also, for some |
* kinds of fp values, the original parts may not have been fully |
* extracted -- but that is ok, we can regenerate them now. |
*/ |
#define _FP_PACK_CANONICAL(fs, wc, X) \ |
do { \ |
switch (X##_c) \ |
{ \ |
case FP_CLS_NORMAL: \ |
X##_e += _FP_EXPBIAS_##fs; \ |
if (X##_e > 0) \ |
{ \ |
_FP_ROUND(wc, X); \ |
if (_FP_FRAC_OVERP_##wc(fs, X)) \ |
{ \ |
_FP_FRAC_CLEAR_OVERP_##wc(fs, X); \ |
X##_e++; \ |
} \ |
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ |
if (X##_e >= _FP_EXPMAX_##fs) \ |
{ \ |
/* overflow */ \ |
switch (FP_ROUNDMODE) \ |
{ \ |
case FP_RND_NEAREST: \ |
X##_c = FP_CLS_INF; \ |
break; \ |
case FP_RND_PINF: \ |
if (!X##_s) X##_c = FP_CLS_INF; \ |
break; \ |
case FP_RND_MINF: \ |
if (X##_s) X##_c = FP_CLS_INF; \ |
break; \ |
} \ |
if (X##_c == FP_CLS_INF) \ |
{ \ |
/* Overflow to infinity */ \ |
X##_e = _FP_EXPMAX_##fs; \ |
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ |
} \ |
else \ |
{ \ |
/* Overflow to maximum normal */ \ |
X##_e = _FP_EXPMAX_##fs - 1; \ |
_FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \ |
} \ |
FP_SET_EXCEPTION(FP_EX_OVERFLOW); \ |
FP_SET_EXCEPTION(FP_EX_INEXACT); \ |
} \ |
} \ |
else \ |
{ \ |
/* we've got a denormalized number */ \ |
X##_e = -X##_e + 1; \ |
if (X##_e <= _FP_WFRACBITS_##fs) \ |
{ \ |
_FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ |
_FP_ROUND(wc, X); \ |
if (_FP_FRAC_HIGH_##fs(X) \ |
& (_FP_OVERFLOW_##fs >> 1)) \ |
{ \ |
X##_e = 1; \ |
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ |
} \ |
else \ |
{ \ |
X##_e = 0; \ |
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ |
FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ |
} \ |
} \ |
else \ |
{ \ |
/* underflow to zero */ \ |
X##_e = 0; \ |
if (!_FP_FRAC_ZEROP_##wc(X)) \ |
{ \ |
_FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ |
_FP_ROUND(wc, X); \ |
_FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \ |
} \ |
FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ |
} \ |
} \ |
break; \ |
\ |
case FP_CLS_ZERO: \ |
X##_e = 0; \ |
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ |
break; \ |
\ |
case FP_CLS_INF: \ |
X##_e = _FP_EXPMAX_##fs; \ |
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ |
break; \ |
\ |
case FP_CLS_NAN: \ |
X##_e = _FP_EXPMAX_##fs; \ |
if (!_FP_KEEPNANFRACP) \ |
{ \ |
_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \ |
X##_s = _FP_NANSIGN_##fs; \ |
} \ |
else \ |
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ |
break; \ |
} \ |
} while (0) |
/* This one accepts raw argument and not cooked, returns |
* 1 if X is a signaling NaN. |
*/ |
#define _FP_ISSIGNAN(fs, wc, X) \ |
({ \ |
int __ret = 0; \ |
if (X##_e == _FP_EXPMAX_##fs) \ |
{ \ |
if (!_FP_FRAC_ZEROP_##wc(X) \ |
&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ |
__ret = 1; \ |
} \ |
__ret; \ |
}) |
/* Addition on semi-raw values. */ |
#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \ |
do { \ |
if (X##_s == Y##_s) \ |
{ \ |
/* Addition. */ \ |
R##_s = X##_s; \ |
int ediff = X##_e - Y##_e; \ |
if (ediff > 0) \ |
{ \ |
R##_e = X##_e; \ |
if (Y##_e == 0) \ |
{ \ |
/* Y is zero or denormalized. */ \ |
if (_FP_FRAC_ZEROP_##wc(Y)) \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ |
_FP_FRAC_COPY_##wc(R, X); \ |
goto add_done; \ |
} \ |
else \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
ediff--; \ |
if (ediff == 0) \ |
{ \ |
_FP_FRAC_ADD_##wc(R, X, Y); \ |
goto add3; \ |
} \ |
if (X##_e == _FP_EXPMAX_##fs) \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ |
_FP_FRAC_COPY_##wc(R, X); \ |
goto add_done; \ |
} \ |
goto add1; \ |
} \ |
} \ |
else if (X##_e == _FP_EXPMAX_##fs) \ |
{ \ |
/* X is NaN or Inf, Y is normal. */ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ |
_FP_FRAC_COPY_##wc(R, X); \ |
goto add_done; \ |
} \ |
\ |
/* Insert implicit MSB of Y. */ \ |
_FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs; \ |
\ |
add1: \ |
/* Shift the mantissa of Y to the right EDIFF steps; \ |
remember to account later for the implicit MSB of X. */ \ |
if (ediff <= _FP_WFRACBITS_##fs) \ |
_FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs); \ |
else if (!_FP_FRAC_ZEROP_##wc(Y)) \ |
_FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \ |
_FP_FRAC_ADD_##wc(R, X, Y); \ |
} \ |
else if (ediff < 0) \ |
{ \ |
ediff = -ediff; \ |
R##_e = Y##_e; \ |
if (X##_e == 0) \ |
{ \ |
/* X is zero or denormalized. */ \ |
if (_FP_FRAC_ZEROP_##wc(X)) \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
goto add_done; \ |
} \ |
else \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
ediff--; \ |
if (ediff == 0) \ |
{ \ |
_FP_FRAC_ADD_##wc(R, Y, X); \ |
goto add3; \ |
} \ |
if (Y##_e == _FP_EXPMAX_##fs) \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
goto add_done; \ |
} \ |
goto add2; \ |
} \ |
} \ |
else if (Y##_e == _FP_EXPMAX_##fs) \ |
{ \ |
/* Y is NaN or Inf, X is normal. */ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
goto add_done; \ |
} \ |
\ |
/* Insert implicit MSB of X. */ \ |
_FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs; \ |
\ |
add2: \ |
/* Shift the mantissa of X to the right EDIFF steps; \ |
remember to account later for the implicit MSB of Y. */ \ |
if (ediff <= _FP_WFRACBITS_##fs) \ |
_FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs); \ |
else if (!_FP_FRAC_ZEROP_##wc(X)) \ |
_FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ |
_FP_FRAC_ADD_##wc(R, Y, X); \ |
} \ |
else \ |
{ \ |
/* ediff == 0. */ \ |
if (!_FP_EXP_NORMAL(fs, wc, X)) \ |
{ \ |
if (X##_e == 0) \ |
{ \ |
/* X and Y are zero or denormalized. */ \ |
R##_e = 0; \ |
if (_FP_FRAC_ZEROP_##wc(X)) \ |
{ \ |
if (!_FP_FRAC_ZEROP_##wc(Y)) \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
goto add_done; \ |
} \ |
else if (_FP_FRAC_ZEROP_##wc(Y)) \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
_FP_FRAC_COPY_##wc(R, X); \ |
goto add_done; \ |
} \ |
else \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
_FP_FRAC_ADD_##wc(R, X, Y); \ |
if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ |
{ \ |
/* Normalized result. */ \ |
_FP_FRAC_HIGH_##fs(R) \ |
&= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \ |
R##_e = 1; \ |
} \ |
goto add_done; \ |
} \ |
} \ |
else \ |
{ \ |
/* X and Y are NaN or Inf. */ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ |
R##_e = _FP_EXPMAX_##fs; \ |
if (_FP_FRAC_ZEROP_##wc(X)) \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
else if (_FP_FRAC_ZEROP_##wc(Y)) \ |
_FP_FRAC_COPY_##wc(R, X); \ |
else \ |
_FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP); \ |
goto add_done; \ |
} \ |
} \ |
/* The exponents of X and Y, both normal, are equal. The \ |
implicit MSBs will always add to increase the \ |
exponent. */ \ |
_FP_FRAC_ADD_##wc(R, X, Y); \ |
R##_e = X##_e + 1; \ |
_FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ |
if (R##_e == _FP_EXPMAX_##fs) \ |
/* Overflow to infinity (depending on rounding mode). */ \ |
_FP_OVERFLOW_SEMIRAW(fs, wc, R); \ |
goto add_done; \ |
} \ |
add3: \ |
if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ |
{ \ |
/* Overflow. */ \ |
_FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \ |
R##_e++; \ |
_FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ |
if (R##_e == _FP_EXPMAX_##fs) \ |
/* Overflow to infinity (depending on rounding mode). */ \ |
_FP_OVERFLOW_SEMIRAW(fs, wc, R); \ |
} \ |
add_done: ; \ |
} \ |
else \ |
{ \ |
/* Subtraction. */ \ |
int ediff = X##_e - Y##_e; \ |
if (ediff > 0) \ |
{ \ |
R##_e = X##_e; \ |
R##_s = X##_s; \ |
if (Y##_e == 0) \ |
{ \ |
/* Y is zero or denormalized. */ \ |
if (_FP_FRAC_ZEROP_##wc(Y)) \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ |
_FP_FRAC_COPY_##wc(R, X); \ |
goto sub_done; \ |
} \ |
else \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
ediff--; \ |
if (ediff == 0) \ |
{ \ |
_FP_FRAC_SUB_##wc(R, X, Y); \ |
goto sub3; \ |
} \ |
if (X##_e == _FP_EXPMAX_##fs) \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ |
_FP_FRAC_COPY_##wc(R, X); \ |
goto sub_done; \ |
} \ |
goto sub1; \ |
} \ |
} \ |
else if (X##_e == _FP_EXPMAX_##fs) \ |
{ \ |
/* X is NaN or Inf, Y is normal. */ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ |
_FP_FRAC_COPY_##wc(R, X); \ |
goto sub_done; \ |
} \ |
\ |
/* Insert implicit MSB of Y. */ \ |
_FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs; \ |
\ |
sub1: \ |
/* Shift the mantissa of Y to the right EDIFF steps; \ |
remember to account later for the implicit MSB of X. */ \ |
if (ediff <= _FP_WFRACBITS_##fs) \ |
_FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs); \ |
else if (!_FP_FRAC_ZEROP_##wc(Y)) \ |
_FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \ |
_FP_FRAC_SUB_##wc(R, X, Y); \ |
} \ |
else if (ediff < 0) \ |
{ \ |
ediff = -ediff; \ |
R##_e = Y##_e; \ |
R##_s = Y##_s; \ |
if (X##_e == 0) \ |
{ \ |
/* X is zero or denormalized. */ \ |
if (_FP_FRAC_ZEROP_##wc(X)) \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
goto sub_done; \ |
} \ |
else \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
ediff--; \ |
if (ediff == 0) \ |
{ \ |
_FP_FRAC_SUB_##wc(R, Y, X); \ |
goto sub3; \ |
} \ |
if (Y##_e == _FP_EXPMAX_##fs) \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
goto sub_done; \ |
} \ |
goto sub2; \ |
} \ |
} \ |
else if (Y##_e == _FP_EXPMAX_##fs) \ |
{ \ |
/* Y is NaN or Inf, X is normal. */ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
goto sub_done; \ |
} \ |
\ |
/* Insert implicit MSB of X. */ \ |
_FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs; \ |
\ |
sub2: \ |
/* Shift the mantissa of X to the right EDIFF steps; \ |
remember to account later for the implicit MSB of Y. */ \ |
if (ediff <= _FP_WFRACBITS_##fs) \ |
_FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs); \ |
else if (!_FP_FRAC_ZEROP_##wc(X)) \ |
_FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ |
_FP_FRAC_SUB_##wc(R, Y, X); \ |
} \ |
else \ |
{ \ |
/* ediff == 0. */ \ |
if (!_FP_EXP_NORMAL(fs, wc, X)) \ |
{ \ |
if (X##_e == 0) \ |
{ \ |
/* X and Y are zero or denormalized. */ \ |
R##_e = 0; \ |
if (_FP_FRAC_ZEROP_##wc(X)) \ |
{ \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
if (_FP_FRAC_ZEROP_##wc(Y)) \ |
R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ |
else \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
R##_s = Y##_s; \ |
} \ |
goto sub_done; \ |
} \ |
else if (_FP_FRAC_ZEROP_##wc(Y)) \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
_FP_FRAC_COPY_##wc(R, X); \ |
R##_s = X##_s; \ |
goto sub_done; \ |
} \ |
else \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
_FP_FRAC_SUB_##wc(R, X, Y); \ |
R##_s = X##_s; \ |
if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ |
{ \ |
/* |X| < |Y|, negate result. */ \ |
_FP_FRAC_SUB_##wc(R, Y, X); \ |
R##_s = Y##_s; \ |
} \ |
else if (_FP_FRAC_ZEROP_##wc(R)) \ |
R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ |
goto sub_done; \ |
} \ |
} \ |
else \ |
{ \ |
/* X and Y are NaN or Inf, of opposite signs. */ \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ |
_FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ |
R##_e = _FP_EXPMAX_##fs; \ |
if (_FP_FRAC_ZEROP_##wc(X)) \ |
{ \ |
if (_FP_FRAC_ZEROP_##wc(Y)) \ |
{ \ |
/* Inf - Inf. */ \ |
R##_s = _FP_NANSIGN_##fs; \ |
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ |
_FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
} \ |
else \ |
{ \ |
/* Inf - NaN. */ \ |
R##_s = Y##_s; \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
} \ |
} \ |
else \ |
{ \ |
if (_FP_FRAC_ZEROP_##wc(Y)) \ |
{ \ |
/* NaN - Inf. */ \ |
R##_s = X##_s; \ |
_FP_FRAC_COPY_##wc(R, X); \ |
} \ |
else \ |
{ \ |
/* NaN - NaN. */ \ |
_FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP); \ |
} \ |
} \ |
goto sub_done; \ |
} \ |
} \ |
/* The exponents of X and Y, both normal, are equal. The \ |
implicit MSBs cancel. */ \ |
R##_e = X##_e; \ |
_FP_FRAC_SUB_##wc(R, X, Y); \ |
R##_s = X##_s; \ |
if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ |
{ \ |
/* |X| < |Y|, negate result. */ \ |
_FP_FRAC_SUB_##wc(R, Y, X); \ |
R##_s = Y##_s; \ |
} \ |
else if (_FP_FRAC_ZEROP_##wc(R)) \ |
{ \ |
R##_e = 0; \ |
R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ |
goto sub_done; \ |
} \ |
goto norm; \ |
} \ |
sub3: \ |
if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ |
{ \ |
int diff; \ |
/* Carry into most significant bit of larger one of X and Y, \ |
canceling it; renormalize. */ \ |
_FP_FRAC_HIGH_##fs(R) &= _FP_IMPLBIT_SH_##fs - 1; \ |
norm: \ |
_FP_FRAC_CLZ_##wc(diff, R); \ |
diff -= _FP_WFRACXBITS_##fs; \ |
_FP_FRAC_SLL_##wc(R, diff); \ |
if (R##_e <= diff) \ |
{ \ |
/* R is denormalized. */ \ |
diff = diff - R##_e + 1; \ |
_FP_FRAC_SRS_##wc(R, diff, _FP_WFRACBITS_##fs); \ |
R##_e = 0; \ |
} \ |
else \ |
{ \ |
R##_e -= diff; \ |
_FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \ |
} \ |
} \ |
sub_done: ; \ |
} \ |
} while (0) |
#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+') |
#define _FP_SUB(fs, wc, R, X, Y) \ |
do { \ |
if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) Y##_s ^= 1; \ |
_FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \ |
} while (0) |
/* |
* Main negation routine. FIXME -- when we care about setting exception |
* bits reliably, this will not do. We should examine all of the fp classes. |
*/ |
#define _FP_NEG(fs, wc, R, X) \ |
do { \ |
_FP_FRAC_COPY_##wc(R, X); \ |
R##_c = X##_c; \ |
R##_e = X##_e; \ |
R##_s = 1 ^ X##_s; \ |
} while (0) |
/* |
* Main multiplication routine. The input values should be cooked. |
*/ |
#define _FP_MUL(fs, wc, R, X, Y) \ |
do { \ |
R##_s = X##_s ^ Y##_s; \ |
switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ |
{ \ |
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ |
R##_c = FP_CLS_NORMAL; \ |
R##_e = X##_e + Y##_e + 1; \ |
\ |
_FP_MUL_MEAT_##fs(R,X,Y); \ |
\ |
if (_FP_FRAC_OVERP_##wc(fs, R)) \ |
_FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ |
else \ |
R##_e--; \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ |
_FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ |
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ |
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ |
R##_s = X##_s; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ |
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ |
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ |
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ |
_FP_FRAC_COPY_##wc(R, X); \ |
R##_c = X##_c; \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ |
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ |
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ |
R##_s = Y##_s; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ |
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
R##_c = Y##_c; \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ |
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ |
R##_s = _FP_NANSIGN_##fs; \ |
R##_c = FP_CLS_NAN; \ |
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
break; \ |
\ |
default: \ |
abort(); \ |
} \ |
} while (0) |
/* |
* Main division routine. The input values should be cooked. |
*/ |
#define _FP_DIV(fs, wc, R, X, Y) \ |
do { \ |
R##_s = X##_s ^ Y##_s; \ |
switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ |
{ \ |
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ |
R##_c = FP_CLS_NORMAL; \ |
R##_e = X##_e - Y##_e; \ |
\ |
_FP_DIV_MEAT_##fs(R,X,Y); \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ |
_FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ |
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ |
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ |
R##_s = X##_s; \ |
_FP_FRAC_COPY_##wc(R, X); \ |
R##_c = X##_c; \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ |
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ |
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ |
R##_s = Y##_s; \ |
_FP_FRAC_COPY_##wc(R, Y); \ |
R##_c = Y##_c; \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ |
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ |
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ |
R##_c = FP_CLS_ZERO; \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ |
FP_SET_EXCEPTION(FP_EX_DIVZERO); \ |
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ |
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ |
R##_c = FP_CLS_INF; \ |
break; \ |
\ |
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ |
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ |
R##_s = _FP_NANSIGN_##fs; \ |
R##_c = FP_CLS_NAN; \ |
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
break; \ |
\ |
default: \ |
abort(); \ |
} \ |
} while (0) |
/* |
* Main differential comparison routine. The inputs should be raw not |
* cooked. The return is -1,0,1 for normal values, 2 otherwise. |
*/ |
#define _FP_CMP(fs, wc, ret, X, Y, un) \ |
do { \ |
/* NANs are unordered */ \ |
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ |
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ |
{ \ |
ret = un; \ |
} \ |
else \ |
{ \ |
int __is_zero_x; \ |
int __is_zero_y; \ |
\ |
__is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \ |
__is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \ |
\ |
if (__is_zero_x && __is_zero_y) \ |
ret = 0; \ |
else if (__is_zero_x) \ |
ret = Y##_s ? 1 : -1; \ |
else if (__is_zero_y) \ |
ret = X##_s ? -1 : 1; \ |
else if (X##_s != Y##_s) \ |
ret = X##_s ? -1 : 1; \ |
else if (X##_e > Y##_e) \ |
ret = X##_s ? -1 : 1; \ |
else if (X##_e < Y##_e) \ |
ret = X##_s ? 1 : -1; \ |
else if (_FP_FRAC_GT_##wc(X, Y)) \ |
ret = X##_s ? -1 : 1; \ |
else if (_FP_FRAC_GT_##wc(Y, X)) \ |
ret = X##_s ? 1 : -1; \ |
else \ |
ret = 0; \ |
} \ |
} while (0) |
/* Simplification for strict equality. */ |
#define _FP_CMP_EQ(fs, wc, ret, X, Y) \ |
do { \ |
/* NANs are unordered */ \ |
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ |
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ |
{ \ |
ret = 1; \ |
} \ |
else \ |
{ \ |
ret = !(X##_e == Y##_e \ |
&& _FP_FRAC_EQ_##wc(X, Y) \ |
&& (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc(X)))); \ |
} \ |
} while (0) |
/* Version to test unordered. */ |
#define _FP_CMP_UNORD(fs, wc, ret, X, Y) \ |
do { \ |
ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ |
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))); \ |
} while (0) |
/* |
* Main square root routine. The input value should be cooked. |
*/ |
#define _FP_SQRT(fs, wc, R, X) \ |
do { \ |
_FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \ |
_FP_W_TYPE q; \ |
switch (X##_c) \ |
{ \ |
case FP_CLS_NAN: \ |
_FP_FRAC_COPY_##wc(R, X); \ |
R##_s = X##_s; \ |
R##_c = FP_CLS_NAN; \ |
break; \ |
case FP_CLS_INF: \ |
if (X##_s) \ |
{ \ |
R##_s = _FP_NANSIGN_##fs; \ |
R##_c = FP_CLS_NAN; /* NAN */ \ |
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
} \ |
else \ |
{ \ |
R##_s = 0; \ |
R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ |
} \ |
break; \ |
case FP_CLS_ZERO: \ |
R##_s = X##_s; \ |
R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ |
break; \ |
case FP_CLS_NORMAL: \ |
R##_s = 0; \ |
if (X##_s) \ |
{ \ |
R##_c = FP_CLS_NAN; /* sNAN */ \ |
R##_s = _FP_NANSIGN_##fs; \ |
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
break; \ |
} \ |
R##_c = FP_CLS_NORMAL; \ |
if (X##_e & 1) \ |
_FP_FRAC_SLL_##wc(X, 1); \ |
R##_e = X##_e >> 1; \ |
_FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \ |
_FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \ |
q = _FP_OVERFLOW_##fs >> 1; \ |
_FP_SQRT_MEAT_##wc(R, S, T, X, q); \ |
} \ |
} while (0) |
/* |
* Convert from FP to integer. Input is raw. |
*/ |
/* RSIGNED can have following values: |
* 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus |
* the result is either 0 or (2^rsize)-1 depending on the sign in such |
* case. |
* 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, |
* NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 |
* depending on the sign in such case. |
* -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is |
* set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 |
* depending on the sign in such case. |
*/ |
#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \ |
do { \ |
if (X##_e < _FP_EXPBIAS_##fs) \ |
{ \ |
r = 0; \ |
if (X##_e == 0) \ |
{ \ |
if (!_FP_FRAC_ZEROP_##wc(X)) \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_INEXACT); \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
} \ |
} \ |
else \ |
FP_SET_EXCEPTION(FP_EX_INEXACT); \ |
} \ |
else if (X##_e >= _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s) \ |
|| (!rsigned && X##_s)) \ |
{ \ |
/* Overflow or converting to the most negative integer. */ \ |
if (rsigned) \ |
{ \ |
r = 1; \ |
r <<= rsize - 1; \ |
r -= 1 - X##_s; \ |
} else { \ |
r = 0; \ |
if (X##_s) \ |
r = ~r; \ |
} \ |
\ |
if (rsigned && X##_s && X##_e == _FP_EXPBIAS_##fs + rsize - 1) \ |
{ \ |
/* Possibly converting to most negative integer; check the \ |
mantissa. */ \ |
int inexact = 0; \ |
(void)((_FP_FRACBITS_##fs > rsize) \ |
? ({ _FP_FRAC_SRST_##wc(X, inexact, \ |
_FP_FRACBITS_##fs - rsize, \ |
_FP_FRACBITS_##fs); 0; }) \ |
: 0); \ |
if (!_FP_FRAC_ZEROP_##wc(X)) \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
else if (inexact) \ |
FP_SET_EXCEPTION(FP_EX_INEXACT); \ |
} \ |
else \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
} \ |
else \ |
{ \ |
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \ |
if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \ |
{ \ |
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ |
r <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \ |
} \ |
else \ |
{ \ |
int inexact; \ |
_FP_FRAC_SRST_##wc(X, inexact, \ |
(_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \ |
- X##_e), \ |
_FP_FRACBITS_##fs); \ |
if (inexact) \ |
FP_SET_EXCEPTION(FP_EX_INEXACT); \ |
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ |
} \ |
if (rsigned && X##_s) \ |
r = -r; \ |
} \ |
} while (0) |
/* Convert integer to fp. Output is raw. RTYPE is unsigned even if |
input is signed. */ |
#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \ |
do { \ |
if (r) \ |
{ \ |
rtype ur_; \ |
\ |
if ((X##_s = (r < 0))) \ |
r = -(rtype)r; \ |
\ |
ur_ = (rtype) r; \ |
(void)((rsize <= _FP_W_TYPE_SIZE) \ |
? ({ \ |
int lz_; \ |
__FP_CLZ(lz_, (_FP_W_TYPE)ur_); \ |
X##_e = _FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 - lz_; \ |
}) \ |
: ((rsize <= 2 * _FP_W_TYPE_SIZE) \ |
? ({ \ |
int lz_; \ |
__FP_CLZ_2(lz_, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \ |
(_FP_W_TYPE)ur_); \ |
X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \ |
- lz_); \ |
}) \ |
: (abort(), 0))); \ |
\ |
if (rsize - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \ |
&& X##_e >= _FP_EXPMAX_##fs) \ |
{ \ |
/* Exponent too big; overflow to infinity. (May also \ |
happen after rounding below.) */ \ |
_FP_OVERFLOW_SEMIRAW(fs, wc, X); \ |
goto pack_semiraw; \ |
} \ |
\ |
if (rsize <= _FP_FRACBITS_##fs \ |
|| X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs) \ |
{ \ |
/* Exactly representable; shift left. */ \ |
_FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \ |
_FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs \ |
+ _FP_FRACBITS_##fs - 1 - X##_e)); \ |
} \ |
else \ |
{ \ |
/* More bits in integer than in floating type; need to \ |
round. */ \ |
if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e) \ |
ur_ = ((ur_ >> (X##_e - _FP_EXPBIAS_##fs \ |
- _FP_WFRACBITS_##fs + 1)) \ |
| ((ur_ << (rsize - (X##_e - _FP_EXPBIAS_##fs \ |
- _FP_WFRACBITS_##fs + 1))) \ |
!= 0)); \ |
_FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \ |
if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0) \ |
_FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs \ |
+ _FP_WFRACBITS_##fs - 1 - X##_e)); \ |
_FP_FRAC_HIGH_##fs(X) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \ |
pack_semiraw: \ |
_FP_PACK_SEMIRAW(fs, wc, X); \ |
} \ |
} \ |
else \ |
{ \ |
X##_s = 0; \ |
X##_e = 0; \ |
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ |
} \ |
} while (0) |
/* Extend from a narrower floating-point format to a wider one. Input |
and output are raw. */ |
#define FP_EXTEND(dfs,sfs,dwc,swc,D,S) \ |
do { \ |
if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \ |
|| (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \ |
< _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \ |
|| (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \ |
&& _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \ |
abort(); \ |
D##_s = S##_s; \ |
_FP_FRAC_COPY_##dwc##_##swc(D, S); \ |
if (_FP_EXP_NORMAL(sfs, swc, S)) \ |
{ \ |
D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \ |
_FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs)); \ |
} \ |
else \ |
{ \ |
if (S##_e == 0) \ |
{ \ |
if (_FP_FRAC_ZEROP_##swc(S)) \ |
D##_e = 0; \ |
else if (_FP_EXPBIAS_##dfs \ |
< _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
_FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \ |
- _FP_FRACBITS_##sfs)); \ |
D##_e = 0; \ |
} \ |
else \ |
{ \ |
int _lz; \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
_FP_FRAC_CLZ_##swc(_lz, S); \ |
_FP_FRAC_SLL_##dwc(D, \ |
_lz + _FP_FRACBITS_##dfs \ |
- _FP_FRACTBITS_##sfs); \ |
D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1 \ |
+ _FP_FRACXBITS_##sfs - _lz); \ |
} \ |
} \ |
else \ |
{ \ |
D##_e = _FP_EXPMAX_##dfs; \ |
if (!_FP_FRAC_ZEROP_##swc(S)) \ |
{ \ |
if (!(_FP_FRAC_HIGH_RAW_##sfs(S) & _FP_QNANBIT_##sfs)) \ |
FP_SET_EXCEPTION(FP_EX_INVALID); \ |
_FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \ |
- _FP_FRACBITS_##sfs)); \ |
} \ |
} \ |
} \ |
} while (0) |
/* Truncate from a wider floating-point format to a narrower one. |
Input and output are semi-raw. */ |
#define FP_TRUNC(dfs,sfs,dwc,swc,D,S) \ |
do { \ |
if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \ |
|| (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \ |
&& _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \ |
abort(); \ |
D##_s = S##_s; \ |
if (_FP_EXP_NORMAL(sfs, swc, S)) \ |
{ \ |
D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \ |
if (D##_e >= _FP_EXPMAX_##dfs) \ |
_FP_OVERFLOW_SEMIRAW(dfs, dwc, D); \ |
else \ |
{ \ |
if (D##_e <= 0) \ |
{ \ |
if (D##_e < 1 - _FP_FRACBITS_##dfs) \ |
{ \ |
_FP_FRAC_SET_##swc(S, _FP_ZEROFRAC_##swc); \ |
_FP_FRAC_LOW_##swc(S) |= 1; \ |
} \ |
else \ |
{ \ |
_FP_FRAC_HIGH_##sfs(S) |= _FP_IMPLBIT_SH_##sfs; \ |
_FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \ |
- _FP_WFRACBITS_##dfs + 1 - D##_e), \ |
_FP_WFRACBITS_##sfs); \ |
} \ |
D##_e = 0; \ |
} \ |
else \ |
_FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \ |
- _FP_WFRACBITS_##dfs), \ |
_FP_WFRACBITS_##sfs); \ |
_FP_FRAC_COPY_##dwc##_##swc(D, S); \ |
} \ |
} \ |
else \ |
{ \ |
if (S##_e == 0) \ |
{ \ |
D##_e = 0; \ |
if (_FP_FRAC_ZEROP_##swc(S)) \ |
_FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ |
else \ |
{ \ |
FP_SET_EXCEPTION(FP_EX_DENORM); \ |
if (_FP_EXPBIAS_##sfs \ |
< _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \ |
{ \ |
_FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \ |
- _FP_WFRACBITS_##dfs), \ |
_FP_WFRACBITS_##sfs); \ |
_FP_FRAC_COPY_##dwc##_##swc(D, S); \ |
} \ |
else \ |
{ \ |
_FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ |
_FP_FRAC_LOW_##dwc(D) |= 1; \ |
} \ |
} \ |
} \ |
else \ |
{ \ |
D##_e = _FP_EXPMAX_##dfs; \ |
if (_FP_FRAC_ZEROP_##swc(S)) \ |
_FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ |
else \ |
{ \ |
_FP_CHECK_SIGNAN_SEMIRAW(sfs, swc, S); \ |
_FP_FRAC_SRL_##swc(S, (_FP_WFRACBITS_##sfs \ |
- _FP_WFRACBITS_##dfs)); \ |
_FP_FRAC_COPY_##dwc##_##swc(D, S); \ |
/* Semi-raw NaN must have all workbits cleared. */ \ |
_FP_FRAC_LOW_##dwc(D) \ |
&= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \ |
_FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs; \ |
} \ |
} \ |
} \ |
} while (0) |
/* |
* Helper primitives. |
*/ |
/* Count leading zeros in a word. */ |
#ifndef __FP_CLZ |
/* GCC 3.4 and later provide the builtins for us. */ |
#define __FP_CLZ(r, x) \ |
do { \ |
if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \ |
r = __builtin_clz (x); \ |
else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \ |
r = __builtin_clzl (x); \ |
else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long)) \ |
r = __builtin_clzll (x); \ |
else \ |
abort (); \ |
} while (0) |
#endif /* ndef __FP_CLZ */ |
#define _FP_DIV_HELP_imm(q, r, n, d) \ |
do { \ |
q = n / d, r = n % d; \ |
} while (0) |
/* A restoring bit-by-bit division primitive. */ |
#define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y) \ |
do { \ |
int count = _FP_WFRACBITS_##fs; \ |
_FP_FRAC_DECL_##wc (u); \ |
_FP_FRAC_DECL_##wc (v); \ |
_FP_FRAC_COPY_##wc (u, X); \ |
_FP_FRAC_COPY_##wc (v, Y); \ |
_FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ |
/* Normalize U and V. */ \ |
_FP_FRAC_SLL_##wc (u, _FP_WFRACXBITS_##fs); \ |
_FP_FRAC_SLL_##wc (v, _FP_WFRACXBITS_##fs); \ |
/* First round. Since the operands are normalized, either the \ |
first or second bit will be set in the fraction. Produce a \ |
normalized result by checking which and adjusting the loop \ |
count and exponent accordingly. */ \ |
if (_FP_FRAC_GE_1 (u, v)) \ |
{ \ |
_FP_FRAC_SUB_##wc (u, u, v); \ |
_FP_FRAC_LOW_##wc (R) |= 1; \ |
count--; \ |
} \ |
else \ |
R##_e--; \ |
/* Subsequent rounds. */ \ |
do { \ |
int msb = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (u) < 0; \ |
_FP_FRAC_SLL_##wc (u, 1); \ |
_FP_FRAC_SLL_##wc (R, 1); \ |
if (msb || _FP_FRAC_GE_1 (u, v)) \ |
{ \ |
_FP_FRAC_SUB_##wc (u, u, v); \ |
_FP_FRAC_LOW_##wc (R) |= 1; \ |
} \ |
} while (--count > 0); \ |
/* If there's anything left in U, the result is inexact. */ \ |
_FP_FRAC_LOW_##wc (R) |= !_FP_FRAC_ZEROP_##wc (u); \ |
} while (0) |
#define _FP_DIV_MEAT_1_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y) |
#define _FP_DIV_MEAT_2_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y) |
#define _FP_DIV_MEAT_4_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y) |
/programs/develop/libraries/newlib/math/pow.c |
---|
0,0 → 1,781 |
/* pow.c |
* |
* Power function |
* |
* |
* |
* SYNOPSIS: |
* |
* double x, y, z, pow(); |
* |
* z = pow( x, y ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Computes x raised to the yth power. Analytically, |
* |
* x**y = exp( y log(x) ). |
* |
* Following Cody and Waite, this program uses a lookup table |
* of 2**-i/16 and pseudo extended precision arithmetic to |
* obtain an extra three bits of accuracy in both the logarithm |
* and the exponential. |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE -26,26 30000 4.2e-16 7.7e-17 |
* DEC -26,26 60000 4.8e-17 9.1e-18 |
* 1/26 < x < 26, with log(x) uniformly distributed. |
* -26 < y < 26, y uniformly distributed. |
* IEEE 0,8700 30000 1.5e-14 2.1e-15 |
* 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed. |
* |
* |
* ERROR MESSAGES: |
* |
* message condition value returned |
* pow overflow x**y > MAXNUM INFINITY |
* pow underflow x**y < 1/MAXNUM 0.0 |
* pow domain x<0 and y noninteger 0.0 |
* |
*/ |
/* |
Cephes Math Library Release 2.8: June, 2000 |
Copyright 1984, 1995, 2000 by Stephen L. Moshier |
*/ |
/* |
Modified for mingw |
2002-09-27 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
static char fname[] = {"pow"}; |
#endif |
#ifndef _SET_ERRNO |
#define _SET_ERRNO(x) |
#endif |
#define SQRTH 0.70710678118654752440 |
#ifdef UNK |
static double P[] = { |
4.97778295871696322025E-1, |
3.73336776063286838734E0, |
7.69994162726912503298E0, |
4.66651806774358464979E0 |
}; |
static double Q[] = { |
/* 1.00000000000000000000E0, */ |
9.33340916416696166113E0, |
2.79999886606328401649E1, |
3.35994905342304405431E1, |
1.39995542032307539578E1 |
}; |
/* 2^(-i/16), IEEE precision */ |
static double A[] = { |
1.00000000000000000000E0, |
9.57603280698573700036E-1, |
9.17004043204671215328E-1, |
8.78126080186649726755E-1, |
8.40896415253714502036E-1, |
8.05245165974627141736E-1, |
7.71105412703970372057E-1, |
7.38413072969749673113E-1, |
7.07106781186547572737E-1, |
6.77127773468446325644E-1, |
6.48419777325504820276E-1, |
6.20928906036742001007E-1, |
5.94603557501360513449E-1, |
5.69394317378345782288E-1, |
5.45253866332628844837E-1, |
5.22136891213706877402E-1, |
5.00000000000000000000E-1 |
}; |
static double B[] = { |
0.00000000000000000000E0, |
1.64155361212281360176E-17, |
4.09950501029074826006E-17, |
3.97491740484881042808E-17, |
-4.83364665672645672553E-17, |
1.26912513974441574796E-17, |
1.99100761573282305549E-17, |
-1.52339103990623557348E-17, |
0.00000000000000000000E0 |
}; |
static double R[] = { |
1.49664108433729301083E-5, |
1.54010762792771901396E-4, |
1.33335476964097721140E-3, |
9.61812908476554225149E-3, |
5.55041086645832347466E-2, |
2.40226506959099779976E-1, |
6.93147180559945308821E-1 |
}; |
#define douba(k) A[k] |
#define doubb(k) B[k] |
#define MEXP 16383.0 |
#ifdef DENORMAL |
#define MNEXP -17183.0 |
#else |
#define MNEXP -16383.0 |
#endif |
#endif |
#ifdef DEC |
static unsigned short P[] = { |
0037776,0156313,0175332,0163602, |
0040556,0167577,0052366,0174245, |
0040766,0062753,0175707,0055564, |
0040625,0052035,0131344,0155636, |
}; |
static unsigned short Q[] = { |
/*0040200,0000000,0000000,0000000,*/ |
0041025,0052644,0154404,0105155, |
0041337,0177772,0007016,0047646, |
0041406,0062740,0154273,0020020, |
0041137,0177054,0106127,0044555, |
}; |
static unsigned short A[] = { |
0040200,0000000,0000000,0000000, |
0040165,0022575,0012444,0103314, |
0040152,0140306,0163735,0022071, |
0040140,0146336,0166052,0112341, |
0040127,0042374,0145326,0116553, |
0040116,0022214,0012437,0102201, |
0040105,0063452,0010525,0003333, |
0040075,0004243,0117530,0006067, |
0040065,0002363,0031771,0157145, |
0040055,0054076,0165102,0120513, |
0040045,0177326,0124661,0050471, |
0040036,0172462,0060221,0120422, |
0040030,0033760,0050615,0134251, |
0040021,0141723,0071653,0010703, |
0040013,0112701,0161752,0105727, |
0040005,0125303,0063714,0044173, |
0040000,0000000,0000000,0000000 |
}; |
static unsigned short B[] = { |
0000000,0000000,0000000,0000000, |
0021473,0040265,0153315,0140671, |
0121074,0062627,0042146,0176454, |
0121413,0003524,0136332,0066212, |
0121767,0046404,0166231,0012553, |
0121257,0015024,0002357,0043574, |
0021736,0106532,0043060,0056206, |
0121310,0020334,0165705,0035326, |
0000000,0000000,0000000,0000000 |
}; |
static unsigned short R[] = { |
0034173,0014076,0137624,0115771, |
0035041,0076763,0003744,0111311, |
0035656,0141766,0041127,0074351, |
0036435,0112533,0073611,0116664, |
0037143,0054106,0134040,0152223, |
0037565,0176757,0176026,0025551, |
0040061,0071027,0173721,0147572 |
}; |
/* |
static double R[] = { |
0.14928852680595608186e-4, |
0.15400290440989764601e-3, |
0.13333541313585784703e-2, |
0.96181290595172416964e-2, |
0.55504108664085595326e-1, |
0.24022650695909537056e0, |
0.69314718055994529629e0 |
}; |
*/ |
#define douba(k) (*(double *)&A[(k)<<2]) |
#define doubb(k) (*(double *)&B[(k)<<2]) |
#define MEXP 2031.0 |
#define MNEXP -2031.0 |
#endif |
#ifdef IBMPC |
static const unsigned short P[] = { |
0x5cf0,0x7f5b,0xdb99,0x3fdf, |
0xdf15,0xea9e,0xddef,0x400d, |
0xeb6f,0x7f78,0xccbd,0x401e, |
0x9b74,0xb65c,0xaa83,0x4012, |
}; |
static const unsigned short Q[] = { |
/*0x0000,0x0000,0x0000,0x3ff0,*/ |
0x914e,0x9b20,0xaab4,0x4022, |
0xc9f5,0x41c1,0xffff,0x403b, |
0x6402,0x1b17,0xccbc,0x4040, |
0xe92e,0x918a,0xffc5,0x402b, |
}; |
static const unsigned short A[] = { |
0x0000,0x0000,0x0000,0x3ff0, |
0x90da,0xa2a4,0xa4af,0x3fee, |
0xa487,0xdcfb,0x5818,0x3fed, |
0x529c,0xdd85,0x199b,0x3fec, |
0xd3ad,0x995a,0xe89f,0x3fea, |
0xf090,0x82a3,0xc491,0x3fe9, |
0xa0db,0x422a,0xace5,0x3fe8, |
0x0187,0x73eb,0xa114,0x3fe7, |
0x3bcd,0x667f,0xa09e,0x3fe6, |
0x5429,0xdd48,0xab07,0x3fe5, |
0x2a27,0xd536,0xbfda,0x3fe4, |
0x3422,0x4c12,0xdea6,0x3fe3, |
0xb715,0x0a31,0x06fe,0x3fe3, |
0x6238,0x6e75,0x387a,0x3fe2, |
0x517b,0x3c7d,0x72b8,0x3fe1, |
0x890f,0x6cf9,0xb558,0x3fe0, |
0x0000,0x0000,0x0000,0x3fe0 |
}; |
static const unsigned short B[] = { |
0x0000,0x0000,0x0000,0x0000, |
0x3707,0xd75b,0xed02,0x3c72, |
0xcc81,0x345d,0xa1cd,0x3c87, |
0x4b27,0x5686,0xe9f1,0x3c86, |
0x6456,0x13b2,0xdd34,0xbc8b, |
0x42e2,0xafec,0x4397,0x3c6d, |
0x82e4,0xd231,0xf46a,0x3c76, |
0x8a76,0xb9d7,0x9041,0xbc71, |
0x0000,0x0000,0x0000,0x0000 |
}; |
static const unsigned short R[] = { |
0x937f,0xd7f2,0x6307,0x3eef, |
0x9259,0x60fc,0x2fbe,0x3f24, |
0xef1d,0xc84a,0xd87e,0x3f55, |
0x33b7,0x6ef1,0xb2ab,0x3f83, |
0x1a92,0xd704,0x6b08,0x3fac, |
0xc56d,0xff82,0xbfbd,0x3fce, |
0x39ef,0xfefa,0x2e42,0x3fe6 |
}; |
#define douba(k) (*(double *)&A[(k)<<2]) |
#define doubb(k) (*(double *)&B[(k)<<2]) |
#define MEXP 16383.0 |
#ifdef DENORMAL |
#define MNEXP -17183.0 |
#else |
#define MNEXP -16383.0 |
#endif |
#endif |
#ifdef MIEEE |
static unsigned short P[] = { |
0x3fdf,0xdb99,0x7f5b,0x5cf0, |
0x400d,0xddef,0xea9e,0xdf15, |
0x401e,0xccbd,0x7f78,0xeb6f, |
0x4012,0xaa83,0xb65c,0x9b74 |
}; |
static unsigned short Q[] = { |
0x4022,0xaab4,0x9b20,0x914e, |
0x403b,0xffff,0x41c1,0xc9f5, |
0x4040,0xccbc,0x1b17,0x6402, |
0x402b,0xffc5,0x918a,0xe92e |
}; |
static unsigned short A[] = { |
0x3ff0,0x0000,0x0000,0x0000, |
0x3fee,0xa4af,0xa2a4,0x90da, |
0x3fed,0x5818,0xdcfb,0xa487, |
0x3fec,0x199b,0xdd85,0x529c, |
0x3fea,0xe89f,0x995a,0xd3ad, |
0x3fe9,0xc491,0x82a3,0xf090, |
0x3fe8,0xace5,0x422a,0xa0db, |
0x3fe7,0xa114,0x73eb,0x0187, |
0x3fe6,0xa09e,0x667f,0x3bcd, |
0x3fe5,0xab07,0xdd48,0x5429, |
0x3fe4,0xbfda,0xd536,0x2a27, |
0x3fe3,0xdea6,0x4c12,0x3422, |
0x3fe3,0x06fe,0x0a31,0xb715, |
0x3fe2,0x387a,0x6e75,0x6238, |
0x3fe1,0x72b8,0x3c7d,0x517b, |
0x3fe0,0xb558,0x6cf9,0x890f, |
0x3fe0,0x0000,0x0000,0x0000 |
}; |
static unsigned short B[] = { |
0x0000,0x0000,0x0000,0x0000, |
0x3c72,0xed02,0xd75b,0x3707, |
0x3c87,0xa1cd,0x345d,0xcc81, |
0x3c86,0xe9f1,0x5686,0x4b27, |
0xbc8b,0xdd34,0x13b2,0x6456, |
0x3c6d,0x4397,0xafec,0x42e2, |
0x3c76,0xf46a,0xd231,0x82e4, |
0xbc71,0x9041,0xb9d7,0x8a76, |
0x0000,0x0000,0x0000,0x0000 |
}; |
static unsigned short R[] = { |
0x3eef,0x6307,0xd7f2,0x937f, |
0x3f24,0x2fbe,0x60fc,0x9259, |
0x3f55,0xd87e,0xc84a,0xef1d, |
0x3f83,0xb2ab,0x6ef1,0x33b7, |
0x3fac,0x6b08,0xd704,0x1a92, |
0x3fce,0xbfbd,0xff82,0xc56d, |
0x3fe6,0x2e42,0xfefa,0x39ef |
}; |
#define douba(k) (*(double *)&A[(k)<<2]) |
#define doubb(k) (*(double *)&B[(k)<<2]) |
#define MEXP 16383.0 |
#ifdef DENORMAL |
#define MNEXP -17183.0 |
#else |
#define MNEXP -16383.0 |
#endif |
#endif |
/* log2(e) - 1 */ |
#define LOG2EA 0.44269504088896340736 |
#define F W |
#define Fa Wa |
#define Fb Wb |
#define G W |
#define Ga Wa |
#define Gb u |
#define H W |
#define Ha Wb |
#define Hb Wb |
#ifdef __MINGW32__ |
static __inline__ double reduc( double ); |
extern double __powi ( double, int ); |
extern double pow ( double x, double y); |
#else /* __MINGW32__ */ |
#ifdef ANSIPROT |
extern double floor ( double ); |
extern double fabs ( double ); |
extern double frexp ( double, int * ); |
extern double ldexp ( double, int ); |
extern double polevl ( double, void *, int ); |
extern double p1evl ( double, void *, int ); |
extern double __powi ( double, int ); |
extern int signbit ( double ); |
extern int isnan ( double ); |
extern int isfinite ( double ); |
static double reduc ( double ); |
#else |
double floor(), fabs(), frexp(), ldexp(); |
double polevl(), p1evl(), __powi(); |
int signbit(), isnan(), isfinite(); |
static double reduc(); |
#endif |
extern double MAXNUM; |
#ifdef INFINITIES |
extern double INFINITY; |
#endif |
#ifdef NANS |
extern double NAN; |
#endif |
#ifdef MINUSZERO |
extern double NEGZERO; |
#endif |
#endif /* __MINGW32__ */ |
double pow( x, y ) |
double x, y; |
{ |
double w, z, W, Wa, Wb, ya, yb, u; |
/* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */ |
double aw, ay, wy; |
int e, i, nflg, iyflg, yoddint; |
if( y == 0.0 ) |
return( 1.0 ); |
#ifdef NANS |
if( isnan(x) || isnan(y) ) |
{ |
_SET_ERRNO (EDOM); |
return( x + y ); |
} |
#endif |
if( y == 1.0 ) |
return( x ); |
#ifdef INFINITIES |
if( !isfinite(y) && (x == 1.0 || x == -1.0) ) |
{ |
mtherr( "pow", DOMAIN ); |
#ifdef NANS |
return( NAN ); |
#else |
return( INFINITY ); |
#endif |
} |
#endif |
if( x == 1.0 ) |
return( 1.0 ); |
if( y >= MAXNUM ) |
{ |
_SET_ERRNO (ERANGE); |
#ifdef INFINITIES |
if( x > 1.0 ) |
return( INFINITY ); |
#else |
if( x > 1.0 ) |
return( MAXNUM ); |
#endif |
if( x > 0.0 && x < 1.0 ) |
return( 0.0); |
if( x < -1.0 ) |
{ |
#ifdef INFINITIES |
return( INFINITY ); |
#else |
return( MAXNUM ); |
#endif |
} |
if( x > -1.0 && x < 0.0 ) |
return( 0.0 ); |
} |
if( y <= -MAXNUM ) |
{ |
_SET_ERRNO (ERANGE); |
if( x > 1.0 ) |
return( 0.0 ); |
#ifdef INFINITIES |
if( x > 0.0 && x < 1.0 ) |
return( INFINITY ); |
#else |
if( x > 0.0 && x < 1.0 ) |
return( MAXNUM ); |
#endif |
if( x < -1.0 ) |
return( 0.0 ); |
#ifdef INFINITIES |
if( x > -1.0 && x < 0.0 ) |
return( INFINITY ); |
#else |
if( x > -1.0 && x < 0.0 ) |
return( MAXNUM ); |
#endif |
} |
if( x >= MAXNUM ) |
{ |
#if INFINITIES |
if( y > 0.0 ) |
return( INFINITY ); |
#else |
if( y > 0.0 ) |
return( MAXNUM ); |
#endif |
return(0.0); |
} |
/* Set iyflg to 1 if y is an integer. */ |
iyflg = 0; |
w = floor(y); |
if( w == y ) |
iyflg = 1; |
/* Test for odd integer y. */ |
yoddint = 0; |
if( iyflg ) |
{ |
ya = fabs(y); |
ya = floor(0.5 * ya); |
yb = 0.5 * fabs(w); |
if( ya != yb ) |
yoddint = 1; |
} |
if( x <= -MAXNUM ) |
{ |
if( y > 0.0 ) |
{ |
#ifdef INFINITIES |
if( yoddint ) |
return( -INFINITY ); |
return( INFINITY ); |
#else |
if( yoddint ) |
return( -MAXNUM ); |
return( MAXNUM ); |
#endif |
} |
if( y < 0.0 ) |
{ |
#ifdef MINUSZERO |
if( yoddint ) |
return( NEGZERO ); |
#endif |
return( 0.0 ); |
} |
} |
nflg = 0; /* flag = 1 if x<0 raised to integer power */ |
if( x <= 0.0 ) |
{ |
if( x == 0.0 ) |
{ |
if( y < 0.0 ) |
{ |
#ifdef MINUSZERO |
if( signbit(x) && yoddint ) |
return( -INFINITY ); |
#endif |
#ifdef INFINITIES |
return( INFINITY ); |
#else |
return( MAXNUM ); |
#endif |
} |
if( y > 0.0 ) |
{ |
#ifdef MINUSZERO |
if( signbit(x) && yoddint ) |
return( NEGZERO ); |
#endif |
return( 0.0 ); |
} |
return( 1.0 ); |
} |
else |
{ |
if( iyflg == 0 ) |
{ /* noninteger power of negative number */ |
mtherr( fname, DOMAIN ); |
_SET_ERRNO (EDOM); |
#ifdef NANS |
return(NAN); |
#else |
return(0.0L); |
#endif |
} |
nflg = 1; |
} |
} |
/* Integer power of an integer. */ |
if( iyflg ) |
{ |
i = w; |
w = floor(x); |
if( (w == x) && (fabs(y) < 32768.0) ) |
{ |
w = __powi( x, (int) y ); |
return( w ); |
} |
} |
if( nflg ) |
x = fabs(x); |
/* For results close to 1, use a series expansion. */ |
w = x - 1.0; |
aw = fabs(w); |
ay = fabs(y); |
wy = w * y; |
ya = fabs(wy); |
if((aw <= 1.0e-3 && ay <= 1.0) |
|| (ya <= 1.0e-3 && ay >= 1.0)) |
{ |
z = (((((w*(y-5.)/720. + 1./120.)*w*(y-4.) + 1./24.)*w*(y-3.) |
+ 1./6.)*w*(y-2.) + 0.5)*w*(y-1.) )*wy + wy + 1.; |
goto done; |
} |
/* These are probably too much trouble. */ |
#if 0 |
w = y * log(x); |
if (aw > 1.0e-3 && fabs(w) < 1.0e-3) |
{ |
z = (((((( |
w/7. + 1.)*w/6. + 1.)*w/5. + 1.)*w/4. + 1.)*w/3. + 1.)*w/2. + 1.)*w + 1.; |
goto done; |
} |
if(ya <= 1.0e-3 && aw <= 1.0e-4) |
{ |
z = ((((( |
wy*1./720. |
+ (-w*1./48. + 1./120.) )*wy |
+ ((w*17./144. - 1./12.)*w + 1./24.) )*wy |
+ (((-w*5./16. + 7./24.)*w - 1./4.)*w + 1./6.) )*wy |
+ ((((w*137./360. - 5./12.)*w + 11./24.)*w - 1./2.)*w + 1./2.) )*wy |
+ (((((-w*1./6. + 1./5.)*w - 1./4)*w + 1./3.)*w -1./2.)*w ) )*wy |
+ wy + 1.0; |
goto done; |
} |
#endif |
/* separate significand from exponent */ |
x = frexp( x, &e ); |
#if 0 |
/* For debugging, check for gross overflow. */ |
if( (e * y) > (MEXP + 1024) ) |
goto overflow; |
#endif |
/* Find significand of x in antilog table A[]. */ |
i = 1; |
if( x <= douba(9) ) |
i = 9; |
if( x <= douba(i+4) ) |
i += 4; |
if( x <= douba(i+2) ) |
i += 2; |
if( x >= douba(1) ) |
i = -1; |
i += 1; |
/* Find (x - A[i])/A[i] |
* in order to compute log(x/A[i]): |
* |
* log(x) = log( a x/a ) = log(a) + log(x/a) |
* |
* log(x/a) = log(1+v), v = x/a - 1 = (x-a)/a |
*/ |
x -= douba(i); |
x -= doubb(i/2); |
x /= douba(i); |
/* rational approximation for log(1+v): |
* |
* log(1+v) = v - v**2/2 + v**3 P(v) / Q(v) |
*/ |
z = x*x; |
w = x * ( z * polevl( x, P, 3 ) / p1evl( x, Q, 4 ) ); |
w = w - ldexp( z, -1 ); /* w - 0.5 * z */ |
/* Convert to base 2 logarithm: |
* multiply by log2(e) |
*/ |
w = w + LOG2EA * w; |
/* Note x was not yet added in |
* to above rational approximation, |
* so do it now, while multiplying |
* by log2(e). |
*/ |
z = w + LOG2EA * x; |
z = z + x; |
/* Compute exponent term of the base 2 logarithm. */ |
w = -i; |
w = ldexp( w, -4 ); /* divide by 16 */ |
w += e; |
/* Now base 2 log of x is w + z. */ |
/* Multiply base 2 log by y, in extended precision. */ |
/* separate y into large part ya |
* and small part yb less than 1/16 |
*/ |
ya = reduc(y); |
yb = y - ya; |
F = z * y + w * yb; |
Fa = reduc(F); |
Fb = F - Fa; |
G = Fa + w * ya; |
Ga = reduc(G); |
Gb = G - Ga; |
H = Fb + Gb; |
Ha = reduc(H); |
w = ldexp( Ga+Ha, 4 ); |
/* Test the power of 2 for overflow */ |
if( w > MEXP ) |
{ |
#ifndef INFINITIES |
mtherr( fname, OVERFLOW ); |
#endif |
#ifdef INFINITIES |
if( nflg && yoddint ) |
return( -INFINITY ); |
return( INFINITY ); |
#else |
if( nflg && yoddint ) |
return( -MAXNUM ); |
return( MAXNUM ); |
#endif |
} |
if( w < (MNEXP - 1) ) |
{ |
#ifndef DENORMAL |
mtherr( fname, UNDERFLOW ); |
#endif |
#ifdef MINUSZERO |
if( nflg && yoddint ) |
return( NEGZERO ); |
#endif |
return( 0.0 ); |
} |
e = w; |
Hb = H - Ha; |
if( Hb > 0.0 ) |
{ |
e += 1; |
Hb -= 0.0625; |
} |
/* Now the product y * log2(x) = Hb + e/16.0. |
* |
* Compute base 2 exponential of Hb, |
* where -0.0625 <= Hb <= 0. |
*/ |
z = Hb * polevl( Hb, R, 6 ); /* z = 2**Hb - 1 */ |
/* Express e/16 as an integer plus a negative number of 16ths. |
* Find lookup table entry for the fractional power of 2. |
*/ |
if( e < 0 ) |
i = 0; |
else |
i = 1; |
i = e/16 + i; |
e = 16*i - e; |
w = douba( e ); |
z = w + w * z; /* 2**-e * ( 1 + (2**Hb-1) ) */ |
z = ldexp( z, i ); /* multiply by integer power of 2 */ |
done: |
/* Negate if odd integer power of negative number */ |
if( nflg && yoddint ) |
{ |
#ifdef MINUSZERO |
if( z == 0.0 ) |
z = NEGZERO; |
else |
#endif |
z = -z; |
} |
return( z ); |
} |
/* Find a multiple of 1/16 that is within 1/16 of x. */ |
static __inline__ double reduc(x) |
double x; |
{ |
double t; |
t = ldexp( x, 4 ); |
t = floor( t ); |
t = ldexp( t, -4 ); |
return(t); |
} |
/programs/develop/libraries/newlib/math/powf.c |
---|
0,0 → 1,3 |
#include <math.h> |
float powf (float x, float y) |
{return (float) pow (x, y);} |
/programs/develop/libraries/newlib/math/powi.c |
---|
0,0 → 1,200 |
/* powi.c |
* |
* Real raised to integer power |
* |
* |
* |
* SYNOPSIS: |
* |
* double x, y, __powi(); |
* int n; |
* |
* y = __powi( x, n ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns argument x raised to the nth power. |
* The routine efficiently decomposes n as a sum of powers of |
* two. The desired power is a product of two-to-the-kth |
* powers of x. Thus to compute the 32767 power of x requires |
* 28 multiplications instead of 32767 multiplications. |
* |
* |
* |
* ACCURACY: |
* |
* |
* Relative error: |
* arithmetic x domain n domain # trials peak rms |
* DEC .04,26 -26,26 100000 2.7e-16 4.3e-17 |
* IEEE .04,26 -26,26 50000 2.0e-15 3.8e-16 |
* IEEE 1,2 -1022,1023 50000 8.6e-14 1.6e-14 |
* |
* Returns MAXNUM on overflow, zero on underflow. |
* |
*/ |
/* powi.c */ |
/* |
Cephes Math Library Release 2.8: June, 2000 |
Copyright 1984, 1995, 2000 by Stephen L. Moshier |
*/ |
/* |
Modified for mingw |
2002-07-22 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
#ifdef ANSIPROT |
extern double log ( double ); |
extern double frexp ( double, int * ); |
extern int signbit ( double ); |
#else |
double log(), frexp(); |
int signbit(); |
#endif |
extern double NEGZERO, INFINITY, MAXNUM, MAXLOG, MINLOG, LOGE2; |
#endif /* __MINGW32__ */ |
#ifndef _SET_ERRNO |
#define _SET_ERRNO(x) |
#endif |
double __powi( x, nn ) |
double x; |
int nn; |
{ |
int n, e, sign, asign, lx; |
double w, y, s; |
/* See pow.c for these tests. */ |
if( x == 0.0 ) |
{ |
if( nn == 0 ) |
return( 1.0 ); |
else if( nn < 0 ) |
return( INFINITY ); |
else |
{ |
if( nn & 1 ) |
return( x ); |
else |
return( 0.0 ); |
} |
} |
if( nn == 0 ) |
return( 1.0 ); |
if( nn == -1 ) |
return( 1.0/x ); |
if( x < 0.0 ) |
{ |
asign = -1; |
x = -x; |
} |
else |
asign = 0; |
if( nn < 0 ) |
{ |
sign = -1; |
n = -nn; |
} |
else |
{ |
sign = 1; |
n = nn; |
} |
/* Even power will be positive. */ |
if( (n & 1) == 0 ) |
asign = 0; |
/* Overflow detection */ |
/* Calculate approximate logarithm of answer */ |
s = frexp( x, &lx ); |
e = (lx - 1)*n; |
if( (e == 0) || (e > 64) || (e < -64) ) |
{ |
s = (s - 7.0710678118654752e-1) / (s + 7.0710678118654752e-1); |
s = (2.9142135623730950 * s - 0.5 + lx) * nn * LOGE2; |
} |
else |
{ |
s = LOGE2 * e; |
} |
if( s > MAXLOG ) |
{ |
mtherr( "powi", OVERFLOW ); |
_SET_ERRNO(ERANGE); |
y = INFINITY; |
goto done; |
} |
#if DENORMAL |
if( s < MINLOG ) |
{ |
y = 0.0; |
goto done; |
} |
/* Handle tiny denormal answer, but with less accuracy |
* since roundoff error in 1.0/x will be amplified. |
* The precise demarcation should be the gradual underflow threshold. |
*/ |
if( (s < (-MAXLOG+2.0)) && (sign < 0) ) |
{ |
x = 1.0/x; |
sign = -sign; |
} |
#else |
/* do not produce denormal answer */ |
if( s < -MAXLOG ) |
return(0.0); |
#endif |
/* First bit of the power */ |
if( n & 1 ) |
y = x; |
else |
y = 1.0; |
w = x; |
n >>= 1; |
while( n ) |
{ |
w = w * w; /* arg to the 2-to-the-kth power */ |
if( n & 1 ) /* if that bit is set, then include in product */ |
y *= w; |
n >>= 1; |
} |
if( sign < 0 ) |
y = 1.0/y; |
done: |
if( asign ) |
{ |
/* odd power of negative number */ |
if( y == 0.0 ) |
y = NEGZERO; |
else |
y = -y; |
} |
return(y); |
} |
/programs/develop/libraries/newlib/math/powif.c |
---|
0,0 → 1,198 |
/* powi.c |
* |
* Real raised to integer power |
* |
* |
* |
* SYNOPSIS: |
* |
* float x, y, __powif(); |
* int n; |
* |
* y = powi( x, n ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns argument x raised to the nth power. |
* The routine efficiently decomposes n as a sum of powers of |
* two. The desired power is a product of two-to-the-kth |
* powers of x. Thus to compute the 32767 power of x requires |
* 28 multiplications instead of 32767 multiplications. |
* |
* |
* |
* ACCURACY: |
* |
* |
* Relative error: |
* arithmetic x domain n domain # trials peak rms |
* DEC .04,26 -26,26 100000 2.7e-16 4.3e-17 |
* IEEE .04,26 -26,26 50000 2.0e-15 3.8e-16 |
* IEEE 1,2 -1022,1023 50000 8.6e-14 1.6e-14 |
* |
* Returns MAXNUM on overflow, zero on underflow. |
* |
*/ |
/* powi.c */ |
/* |
Cephes Math Library Release 2.8: June, 2000 |
Copyright 1984, 1995, 2000 by Stephen L. Moshier |
*/ |
/* |
Modified for float from powi.c and adapted to mingw |
2002-10-01 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
#ifdef ANSIPROT |
extern float logf ( float ); |
extern float frexpf ( float, int * ); |
extern int signbitf ( float ); |
#else |
float logf(), frexpf(); |
int signbitf(); |
#endif |
extern float NEGZEROF, INFINITYF, MAXNUMF, MAXLOGF, MINLOGF, LOGE2F; |
#endif /* __MINGW32__ */ |
#ifndef _SET_ERRNO |
#define _SET_ERRNO(x) |
#endif |
float __powif( float x, int nn ) |
{ |
int n, e, sign, asign, lx; |
float w, y, s; |
/* See pow.c for these tests. */ |
if( x == 0.0F ) |
{ |
if( nn == 0 ) |
return( 1.0F ); |
else if( nn < 0 ) |
return( INFINITYF ); |
else |
{ |
if( nn & 1 ) |
return( x ); |
else |
return( 0.0 ); |
} |
} |
if( nn == 0 ) |
return( 1.0 ); |
if( nn == -1 ) |
return( 1.0/x ); |
if( x < 0.0 ) |
{ |
asign = -1; |
x = -x; |
} |
else |
asign = 0; |
if( nn < 0 ) |
{ |
sign = -1; |
n = -nn; |
} |
else |
{ |
sign = 1; |
n = nn; |
} |
/* Even power will be positive. */ |
if( (n & 1) == 0 ) |
asign = 0; |
/* Overflow detection */ |
/* Calculate approximate logarithm of answer */ |
s = frexpf( x, &lx ); |
e = (lx - 1)*n; |
if( (e == 0) || (e > 64) || (e < -64) ) |
{ |
s = (s - 7.0710678118654752e-1) / (s + 7.0710678118654752e-1); |
s = (2.9142135623730950 * s - 0.5 + lx) * nn * LOGE2F; |
} |
else |
{ |
s = LOGE2F * e; |
} |
if( s > MAXLOGF ) |
{ |
mtherr( "__powif", OVERFLOW ); |
_SET_ERRNO(ERANGE); |
y = INFINITYF; |
goto done; |
} |
#if DENORMAL |
if( s < MINLOGF ) |
{ |
y = 0.0; |
goto done; |
} |
/* Handle tiny denormal answer, but with less accuracy |
* since roundoff error in 1.0/x will be amplified. |
* The precise demarcation should be the gradual underflow threshold. |
*/ |
if( (s < (-MAXLOGF+2.0)) && (sign < 0) ) |
{ |
x = 1.0/x; |
sign = -sign; |
} |
#else |
/* do not produce denormal answer */ |
if( s < -MAXLOGF ) |
return(0.0); |
#endif |
/* First bit of the power */ |
if( n & 1 ) |
y = x; |
else |
y = 1.0; |
w = x; |
n >>= 1; |
while( n ) |
{ |
w = w * w; /* arg to the 2-to-the-kth power */ |
if( n & 1 ) /* if that bit is set, then include in product */ |
y *= w; |
n >>= 1; |
} |
if( sign < 0 ) |
y = 1.0/y; |
done: |
if( asign ) |
{ |
/* odd power of negative number */ |
if( y == 0.0 ) |
y = NEGZEROF; |
else |
y = -y; |
} |
return(y); |
} |
/programs/develop/libraries/newlib/math/powil.c |
---|
0,0 → 1,179 |
/* __powil.c |
* |
* Real raised to integer power, long double precision |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, __powil(); |
* int n; |
* |
* y = __powil( x, n ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns argument x raised to the nth power. |
* The routine efficiently decomposes n as a sum of powers of |
* two. The desired power is a product of two-to-the-kth |
* powers of x. Thus to compute the 32767 power of x requires |
* 28 multiplications instead of 32767 multiplications. |
* |
* |
* |
* ACCURACY: |
* |
* |
* Relative error: |
* arithmetic x domain n domain # trials peak rms |
* IEEE .001,1000 -1022,1023 50000 4.3e-17 7.8e-18 |
* IEEE 1,2 -1022,1023 20000 3.9e-17 7.6e-18 |
* IEEE .99,1.01 0,8700 10000 3.6e-16 7.2e-17 |
* |
* Returns INFINITY on overflow, zero on underflow. |
* |
*/ |
/* __powil.c */ |
/* |
Cephes Math Library Release 2.2: December, 1990 |
Copyright 1984, 1990 by Stephen L. Moshier |
Direct inquiries to 30 Frost Street, Cambridge, MA 02140 |
*/ |
/* |
Modified for mingw |
2002-07-22 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
extern long double MAXNUML, MAXLOGL, MINLOGL; |
extern long double LOGE2L; |
#ifdef ANSIPROT |
extern long double frexpl ( long double, int * ); |
#else |
long double frexpl(); |
#endif |
#endif /* __MINGW32__ */ |
#ifndef _SET_ERRNO |
#define _SET_ERRNO(x) |
#endif |
long double __powil( x, nn ) |
long double x; |
int nn; |
{ |
long double w, y; |
long double s; |
int n, e, sign, asign, lx; |
if( x == 0.0L ) |
{ |
if( nn == 0 ) |
return( 1.0L ); |
else if( nn < 0 ) |
return( INFINITYL ); |
else |
return( 0.0L ); |
} |
if( nn == 0 ) |
return( 1.0L ); |
if( x < 0.0L ) |
{ |
asign = -1; |
x = -x; |
} |
else |
asign = 0; |
if( nn < 0 ) |
{ |
sign = -1; |
n = -nn; |
} |
else |
{ |
sign = 1; |
n = nn; |
} |
/* Overflow detection */ |
/* Calculate approximate logarithm of answer */ |
s = x; |
s = frexpl( s, &lx ); |
e = (lx - 1)*n; |
if( (e == 0) || (e > 64) || (e < -64) ) |
{ |
s = (s - 7.0710678118654752e-1L) / (s + 7.0710678118654752e-1L); |
s = (2.9142135623730950L * s - 0.5L + lx) * nn * LOGE2L; |
} |
else |
{ |
s = LOGE2L * e; |
} |
if( s > MAXLOGL ) |
{ |
mtherr( "__powil", OVERFLOW ); |
_SET_ERRNO(ERANGE); |
y = INFINITYL; |
goto done; |
} |
if( s < MINLOGL ) |
{ |
mtherr( "__powil", UNDERFLOW ); |
_SET_ERRNO(ERANGE); |
return(0.0L); |
} |
/* Handle tiny denormal answer, but with less accuracy |
* since roundoff error in 1.0/x will be amplified. |
* The precise demarcation should be the gradual underflow threshold. |
*/ |
if( s < (-MAXLOGL+2.0L) ) |
{ |
x = 1.0L/x; |
sign = -sign; |
} |
/* First bit of the power */ |
if( n & 1 ) |
y = x; |
else |
{ |
y = 1.0L; |
asign = 0; |
} |
w = x; |
n >>= 1; |
while( n ) |
{ |
w = w * w; /* arg to the 2-to-the-kth power */ |
if( n & 1 ) /* if that bit is set, then include in product */ |
y *= w; |
n >>= 1; |
} |
done: |
if( asign ) |
y = -y; /* odd power of negative number */ |
if( sign < 0 ) |
y = 1.0L/y; |
return(y); |
} |
/programs/develop/libraries/newlib/math/powl.c |
---|
0,0 → 1,804 |
/* powl.c |
* |
* Power function, long double precision |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, z, powl(); |
* |
* z = powl( x, y ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Computes x raised to the yth power. Analytically, |
* |
* x**y = exp( y log(x) ). |
* |
* Following Cody and Waite, this program uses a lookup table |
* of 2**-i/32 and pseudo extended precision arithmetic to |
* obtain several extra bits of accuracy in both the logarithm |
* and the exponential. |
* |
* |
* |
* ACCURACY: |
* |
* The relative error of pow(x,y) can be estimated |
* by y dl ln(2), where dl is the absolute error of |
* the internally computed base 2 logarithm. At the ends |
* of the approximation interval the logarithm equal 1/32 |
* and its relative error is about 1 lsb = 1.1e-19. Hence |
* the predicted relative error in the result is 2.3e-21 y . |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* |
* IEEE +-1000 40000 2.8e-18 3.7e-19 |
* .001 < x < 1000, with log(x) uniformly distributed. |
* -1000 < y < 1000, y uniformly distributed. |
* |
* IEEE 0,8700 60000 6.5e-18 1.0e-18 |
* 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed. |
* |
* |
* ERROR MESSAGES: |
* |
* message condition value returned |
* pow overflow x**y > MAXNUM INFINITY |
* pow underflow x**y < 1/MAXNUM 0.0 |
* pow domain x<0 and y noninteger 0.0 |
* |
*/ |
/* |
Cephes Math Library Release 2.7: May, 1998 |
Copyright 1984, 1991, 1998 by Stephen L. Moshier |
*/ |
/* |
Modified for mingw |
2002-07-22 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
static char fname[] = {"powl"}; |
#endif |
#ifndef _SET_ERRNO |
#define _SET_ERRNO(x) |
#endif |
/* Table size */ |
#define NXT 32 |
/* log2(Table size) */ |
#define LNXT 5 |
#ifdef UNK |
/* log(1+x) = x - .5x^2 + x^3 * P(z)/Q(z) |
* on the domain 2^(-1/32) - 1 <= x <= 2^(1/32) - 1 |
*/ |
static long double P[] = { |
8.3319510773868690346226E-4L, |
4.9000050881978028599627E-1L, |
1.7500123722550302671919E0L, |
1.4000100839971580279335E0L, |
}; |
static long double Q[] = { |
/* 1.0000000000000000000000E0L,*/ |
5.2500282295834889175431E0L, |
8.4000598057587009834666E0L, |
4.2000302519914740834728E0L, |
}; |
/* A[i] = 2^(-i/32), rounded to IEEE long double precision. |
* If i is even, A[i] + B[i/2] gives additional accuracy. |
*/ |
static long double A[33] = { |
1.0000000000000000000000E0L, |
9.7857206208770013448287E-1L, |
9.5760328069857364691013E-1L, |
9.3708381705514995065011E-1L, |
9.1700404320467123175367E-1L, |
8.9735453750155359320742E-1L, |
8.7812608018664974155474E-1L, |
8.5930964906123895780165E-1L, |
8.4089641525371454301892E-1L, |
8.2287773907698242225554E-1L, |
8.0524516597462715409607E-1L, |
7.8799042255394324325455E-1L, |
7.7110541270397041179298E-1L, |
7.5458221379671136985669E-1L, |
7.3841307296974965571198E-1L, |
7.2259040348852331001267E-1L, |
7.0710678118654752438189E-1L, |
6.9195494098191597746178E-1L, |
6.7712777346844636413344E-1L, |
6.6261832157987064729696E-1L, |
6.4841977732550483296079E-1L, |
6.3452547859586661129850E-1L, |
6.2092890603674202431705E-1L, |
6.0762367999023443907803E-1L, |
5.9460355750136053334378E-1L, |
5.8186242938878875689693E-1L, |
5.6939431737834582684856E-1L, |
5.5719337129794626814472E-1L, |
5.4525386633262882960438E-1L, |
5.3357020033841180906486E-1L, |
5.2213689121370692017331E-1L, |
5.1094857432705833910408E-1L, |
5.0000000000000000000000E-1L, |
}; |
static long double B[17] = { |
0.0000000000000000000000E0L, |
2.6176170809902549338711E-20L, |
-1.0126791927256478897086E-20L, |
1.3438228172316276937655E-21L, |
1.2207982955417546912101E-20L, |
-6.3084814358060867200133E-21L, |
1.3164426894366316434230E-20L, |
-1.8527916071632873716786E-20L, |
1.8950325588932570796551E-20L, |
1.5564775779538780478155E-20L, |
6.0859793637556860974380E-21L, |
-2.0208749253662532228949E-20L, |
1.4966292219224761844552E-20L, |
3.3540909728056476875639E-21L, |
-8.6987564101742849540743E-22L, |
-1.2327176863327626135542E-20L, |
0.0000000000000000000000E0L, |
}; |
/* 2^x = 1 + x P(x), |
* on the interval -1/32 <= x <= 0 |
*/ |
static long double R[] = { |
1.5089970579127659901157E-5L, |
1.5402715328927013076125E-4L, |
1.3333556028915671091390E-3L, |
9.6181291046036762031786E-3L, |
5.5504108664798463044015E-2L, |
2.4022650695910062854352E-1L, |
6.9314718055994530931447E-1L, |
}; |
#define douba(k) A[k] |
#define doubb(k) B[k] |
#define MEXP (NXT*16384.0L) |
/* The following if denormal numbers are supported, else -MEXP: */ |
#ifdef DENORMAL |
#define MNEXP (-NXT*(16384.0L+64.0L)) |
#else |
#define MNEXP (-NXT*16384.0L) |
#endif |
/* log2(e) - 1 */ |
#define LOG2EA 0.44269504088896340735992L |
#endif |
#ifdef IBMPC |
static const unsigned short P[] = { |
0xb804,0xa8b7,0xc6f4,0xda6a,0x3ff4, XPD |
0x7de9,0xcf02,0x58c0,0xfae1,0x3ffd, XPD |
0x405a,0x3722,0x67c9,0xe000,0x3fff, XPD |
0xcd99,0x6b43,0x87ca,0xb333,0x3fff, XPD |
}; |
static const unsigned short Q[] = { |
/* 0x0000,0x0000,0x0000,0x8000,0x3fff, */ |
0x6307,0xa469,0x3b33,0xa800,0x4001, XPD |
0xfec2,0x62d7,0xa51c,0x8666,0x4002, XPD |
0xda32,0xd072,0xa5d7,0x8666,0x4001, XPD |
}; |
static const unsigned short A[] = { |
0x0000,0x0000,0x0000,0x8000,0x3fff, XPD |
0x033a,0x722a,0xb2db,0xfa83,0x3ffe, XPD |
0xcc2c,0x2486,0x7d15,0xf525,0x3ffe, XPD |
0xf5cb,0xdcda,0xb99b,0xefe4,0x3ffe, XPD |
0x392f,0xdd24,0xc6e7,0xeac0,0x3ffe, XPD |
0x48a8,0x7c83,0x06e7,0xe5b9,0x3ffe, XPD |
0xe111,0x2a94,0xdeec,0xe0cc,0x3ffe, XPD |
0x3755,0xdaf2,0xb797,0xdbfb,0x3ffe, XPD |
0x6af4,0xd69d,0xfcca,0xd744,0x3ffe, XPD |
0xe45a,0xf12a,0x1d91,0xd2a8,0x3ffe, XPD |
0x80e4,0x1f84,0x8c15,0xce24,0x3ffe, XPD |
0x27a3,0x6e2f,0xbd86,0xc9b9,0x3ffe, XPD |
0xdadd,0x5506,0x2a11,0xc567,0x3ffe, XPD |
0x9456,0x6670,0x4cca,0xc12c,0x3ffe, XPD |
0x36bf,0x580c,0xa39f,0xbd08,0x3ffe, XPD |
0x9ee9,0x62fb,0xaf47,0xb8fb,0x3ffe, XPD |
0x6484,0xf9de,0xf333,0xb504,0x3ffe, XPD |
0x2590,0xd2ac,0xf581,0xb123,0x3ffe, XPD |
0x4ac6,0x42a1,0x3eea,0xad58,0x3ffe, XPD |
0x0ef8,0xea7c,0x5ab4,0xa9a1,0x3ffe, XPD |
0x38ea,0xb151,0xd6a9,0xa5fe,0x3ffe, XPD |
0x6819,0x0c49,0x4303,0xa270,0x3ffe, XPD |
0x11ae,0x91a1,0x3260,0x9ef5,0x3ffe, XPD |
0x5539,0xd54e,0x39b9,0x9b8d,0x3ffe, XPD |
0xa96f,0x8db8,0xf051,0x9837,0x3ffe, XPD |
0x0961,0xfef7,0xefa8,0x94f4,0x3ffe, XPD |
0xc336,0xab11,0xd373,0x91c3,0x3ffe, XPD |
0x53c0,0x45cd,0x398b,0x8ea4,0x3ffe, XPD |
0xd6e7,0xea8b,0xc1e3,0x8b95,0x3ffe, XPD |
0x8527,0x92da,0x0e80,0x8898,0x3ffe, XPD |
0x7b15,0xcc48,0xc367,0x85aa,0x3ffe, XPD |
0xa1d7,0xac2b,0x8698,0x82cd,0x3ffe, XPD |
0x0000,0x0000,0x0000,0x8000,0x3ffe, XPD |
}; |
static const unsigned short B[] = { |
0x0000,0x0000,0x0000,0x0000,0x0000, XPD |
0x1f87,0xdb30,0x18f5,0xf73a,0x3fbd, XPD |
0xac15,0x3e46,0x2932,0xbf4a,0xbfbc, XPD |
0x7944,0xba66,0xa091,0xcb12,0x3fb9, XPD |
0xff78,0x40b4,0x2ee6,0xe69a,0x3fbc, XPD |
0xc895,0x5069,0xe383,0xee53,0xbfbb, XPD |
0x7cde,0x9376,0x4325,0xf8ab,0x3fbc, XPD |
0xa10c,0x25e0,0xc093,0xaefd,0xbfbd, XPD |
0x7d3e,0xea95,0x1366,0xb2fb,0x3fbd, XPD |
0x5d89,0xeb34,0x5191,0x9301,0x3fbd, XPD |
0x80d9,0xb883,0xfb10,0xe5eb,0x3fbb, XPD |
0x045d,0x288c,0xc1ec,0xbedd,0xbfbd, XPD |
0xeded,0x5c85,0x4630,0x8d5a,0x3fbd, XPD |
0x9d82,0xe5ac,0x8e0a,0xfd6d,0x3fba, XPD |
0x6dfd,0xeb58,0xaf14,0x8373,0xbfb9, XPD |
0xf938,0x7aac,0x91cf,0xe8da,0xbfbc, XPD |
0x0000,0x0000,0x0000,0x0000,0x0000, XPD |
}; |
static const unsigned short R[] = { |
0xa69b,0x530e,0xee1d,0xfd2a,0x3fee, XPD |
0xc746,0x8e7e,0x5960,0xa182,0x3ff2, XPD |
0x63b6,0xadda,0xfd6a,0xaec3,0x3ff5, XPD |
0xc104,0xfd99,0x5b7c,0x9d95,0x3ff8, XPD |
0xe05e,0x249d,0x46b8,0xe358,0x3ffa, XPD |
0x5d1d,0x162c,0xeffc,0xf5fd,0x3ffc, XPD |
0x79aa,0xd1cf,0x17f7,0xb172,0x3ffe, XPD |
}; |
/* 10 byte sizes versus 12 byte */ |
#define douba(k) (*(long double *)(&A[(sizeof( long double )/2)*(k)])) |
#define doubb(k) (*(long double *)(&B[(sizeof( long double )/2)*(k)])) |
#define MEXP (NXT*16384.0L) |
#ifdef DENORMAL |
#define MNEXP (-NXT*(16384.0L+64.0L)) |
#else |
#define MNEXP (-NXT*16384.0L) |
#endif |
static const |
union |
{ |
unsigned short L[6]; |
long double ld; |
} log2ea = {{0xc2ef,0x705f,0xeca5,0xe2a8,0x3ffd, XPD}}; |
#define LOG2EA (log2ea.ld) |
/* |
#define LOG2EA 0.44269504088896340735992L |
*/ |
#endif |
#ifdef MIEEE |
static long P[] = { |
0x3ff40000,0xda6ac6f4,0xa8b7b804, |
0x3ffd0000,0xfae158c0,0xcf027de9, |
0x3fff0000,0xe00067c9,0x3722405a, |
0x3fff0000,0xb33387ca,0x6b43cd99, |
}; |
static long Q[] = { |
/* 0x3fff0000,0x80000000,0x00000000, */ |
0x40010000,0xa8003b33,0xa4696307, |
0x40020000,0x8666a51c,0x62d7fec2, |
0x40010000,0x8666a5d7,0xd072da32, |
}; |
static long A[] = { |
0x3fff0000,0x80000000,0x00000000, |
0x3ffe0000,0xfa83b2db,0x722a033a, |
0x3ffe0000,0xf5257d15,0x2486cc2c, |
0x3ffe0000,0xefe4b99b,0xdcdaf5cb, |
0x3ffe0000,0xeac0c6e7,0xdd24392f, |
0x3ffe0000,0xe5b906e7,0x7c8348a8, |
0x3ffe0000,0xe0ccdeec,0x2a94e111, |
0x3ffe0000,0xdbfbb797,0xdaf23755, |
0x3ffe0000,0xd744fcca,0xd69d6af4, |
0x3ffe0000,0xd2a81d91,0xf12ae45a, |
0x3ffe0000,0xce248c15,0x1f8480e4, |
0x3ffe0000,0xc9b9bd86,0x6e2f27a3, |
0x3ffe0000,0xc5672a11,0x5506dadd, |
0x3ffe0000,0xc12c4cca,0x66709456, |
0x3ffe0000,0xbd08a39f,0x580c36bf, |
0x3ffe0000,0xb8fbaf47,0x62fb9ee9, |
0x3ffe0000,0xb504f333,0xf9de6484, |
0x3ffe0000,0xb123f581,0xd2ac2590, |
0x3ffe0000,0xad583eea,0x42a14ac6, |
0x3ffe0000,0xa9a15ab4,0xea7c0ef8, |
0x3ffe0000,0xa5fed6a9,0xb15138ea, |
0x3ffe0000,0xa2704303,0x0c496819, |
0x3ffe0000,0x9ef53260,0x91a111ae, |
0x3ffe0000,0x9b8d39b9,0xd54e5539, |
0x3ffe0000,0x9837f051,0x8db8a96f, |
0x3ffe0000,0x94f4efa8,0xfef70961, |
0x3ffe0000,0x91c3d373,0xab11c336, |
0x3ffe0000,0x8ea4398b,0x45cd53c0, |
0x3ffe0000,0x8b95c1e3,0xea8bd6e7, |
0x3ffe0000,0x88980e80,0x92da8527, |
0x3ffe0000,0x85aac367,0xcc487b15, |
0x3ffe0000,0x82cd8698,0xac2ba1d7, |
0x3ffe0000,0x80000000,0x00000000, |
}; |
static long B[51] = { |
0x00000000,0x00000000,0x00000000, |
0x3fbd0000,0xf73a18f5,0xdb301f87, |
0xbfbc0000,0xbf4a2932,0x3e46ac15, |
0x3fb90000,0xcb12a091,0xba667944, |
0x3fbc0000,0xe69a2ee6,0x40b4ff78, |
0xbfbb0000,0xee53e383,0x5069c895, |
0x3fbc0000,0xf8ab4325,0x93767cde, |
0xbfbd0000,0xaefdc093,0x25e0a10c, |
0x3fbd0000,0xb2fb1366,0xea957d3e, |
0x3fbd0000,0x93015191,0xeb345d89, |
0x3fbb0000,0xe5ebfb10,0xb88380d9, |
0xbfbd0000,0xbeddc1ec,0x288c045d, |
0x3fbd0000,0x8d5a4630,0x5c85eded, |
0x3fba0000,0xfd6d8e0a,0xe5ac9d82, |
0xbfb90000,0x8373af14,0xeb586dfd, |
0xbfbc0000,0xe8da91cf,0x7aacf938, |
0x00000000,0x00000000,0x00000000, |
}; |
static long R[] = { |
0x3fee0000,0xfd2aee1d,0x530ea69b, |
0x3ff20000,0xa1825960,0x8e7ec746, |
0x3ff50000,0xaec3fd6a,0xadda63b6, |
0x3ff80000,0x9d955b7c,0xfd99c104, |
0x3ffa0000,0xe35846b8,0x249de05e, |
0x3ffc0000,0xf5fdeffc,0x162c5d1d, |
0x3ffe0000,0xb17217f7,0xd1cf79aa, |
}; |
#define douba(k) (*(long double *)&A[3*(k)]) |
#define doubb(k) (*(long double *)&B[3*(k)]) |
#define MEXP (NXT*16384.0L) |
#ifdef DENORMAL |
#define MNEXP (-NXT*(16384.0L+64.0L)) |
#else |
#define MNEXP (-NXT*16382.0L) |
#endif |
static long L[3] = {0x3ffd0000,0xe2a8eca5,0x705fc2ef}; |
#define LOG2EA (*(long double *)(&L[0])) |
#endif |
#define F W |
#define Fa Wa |
#define Fb Wb |
#define G W |
#define Ga Wa |
#define Gb u |
#define H W |
#define Ha Wb |
#define Hb Wb |
#ifndef __MINGW32__ |
extern long double MAXNUML; |
#endif |
static VOLATILE long double z; |
static long double w, W, Wa, Wb, ya, yb, u; |
#ifdef __MINGW32__ |
static __inline__ long double reducl( long double ); |
extern long double __powil ( long double, int ); |
extern long double powl ( long double x, long double y); |
#else |
#ifdef ANSIPROT |
extern long double floorl ( long double ); |
extern long double fabsl ( long double ); |
extern long double frexpl ( long double, int * ); |
extern long double ldexpl ( long double, int ); |
extern long double polevll ( long double, void *, int ); |
extern long double p1evll ( long double, void *, int ); |
extern long double __powil ( long double, int ); |
extern int isnanl ( long double ); |
extern int isfinitel ( long double ); |
static long double reducl( long double ); |
extern int signbitl ( long double ); |
#else |
long double floorl(), fabsl(), frexpl(), ldexpl(); |
long double polevll(), p1evll(), __powil(); |
static long double reducl(); |
int isnanl(), isfinitel(), signbitl(); |
#endif /* __MINGW32__ */ |
#ifdef INFINITIES |
extern long double INFINITYL; |
#else |
#define INFINITYL MAXNUML |
#endif |
#ifdef NANS |
extern long double NANL; |
#endif |
#ifdef MINUSZERO |
extern long double NEGZEROL; |
#endif |
#endif /* __MINGW32__ */ |
#ifdef __MINGW32__ |
/* No error checking. We handle Infs and zeros ourselves. */ |
static __inline__ long double |
__fast_ldexpl (long double x, int expn) |
{ |
long double res; |
__asm__ ("fscale" |
: "=t" (res) |
: "0" (x), "u" ((long double) expn)); |
return res; |
} |
#define ldexpl __fast_ldexpl |
#endif |
long double powl( x, y ) |
long double x, y; |
{ |
/* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */ |
int i, nflg, iyflg, yoddint; |
long e; |
if( y == 0.0L ) |
return( 1.0L ); |
#ifdef NANS |
if( isnanl(x) ) |
{ |
_SET_ERRNO (EDOM); |
return( x ); |
} |
if( isnanl(y) ) |
{ |
_SET_ERRNO (EDOM); |
return( y ); |
} |
#endif |
if( y == 1.0L ) |
return( x ); |
if( isinfl(y) && (x == -1.0L || x == 1.0L) ) |
return( y ); |
if( x == 1.0L ) |
return( 1.0L ); |
if( y >= MAXNUML ) |
{ |
_SET_ERRNO (ERANGE); |
#ifdef INFINITIES |
if( x > 1.0L ) |
return( INFINITYL ); |
#else |
if( x > 1.0L ) |
return( MAXNUML ); |
#endif |
if( x > 0.0L && x < 1.0L ) |
return( 0.0L ); |
#ifdef INFINITIES |
if( x < -1.0L ) |
return( INFINITYL ); |
#else |
if( x < -1.0L ) |
return( MAXNUML ); |
#endif |
if( x > -1.0L && x < 0.0L ) |
return( 0.0L ); |
} |
if( y <= -MAXNUML ) |
{ |
_SET_ERRNO (ERANGE); |
if( x > 1.0L ) |
return( 0.0L ); |
#ifdef INFINITIES |
if( x > 0.0L && x < 1.0L ) |
return( INFINITYL ); |
#else |
if( x > 0.0L && x < 1.0L ) |
return( MAXNUML ); |
#endif |
if( x < -1.0L ) |
return( 0.0L ); |
#ifdef INFINITIES |
if( x > -1.0L && x < 0.0L ) |
return( INFINITYL ); |
#else |
if( x > -1.0L && x < 0.0L ) |
return( MAXNUML ); |
#endif |
} |
if( x >= MAXNUML ) |
{ |
#if INFINITIES |
if( y > 0.0L ) |
return( INFINITYL ); |
#else |
if( y > 0.0L ) |
return( MAXNUML ); |
#endif |
return( 0.0L ); |
} |
w = floorl(y); |
/* Set iyflg to 1 if y is an integer. */ |
iyflg = 0; |
if( w == y ) |
iyflg = 1; |
/* Test for odd integer y. */ |
yoddint = 0; |
if( iyflg ) |
{ |
ya = fabsl(y); |
ya = floorl(0.5L * ya); |
yb = 0.5L * fabsl(w); |
if( ya != yb ) |
yoddint = 1; |
} |
if( x <= -MAXNUML ) |
{ |
if( y > 0.0L ) |
{ |
#ifdef INFINITIES |
if( yoddint ) |
return( -INFINITYL ); |
return( INFINITYL ); |
#else |
if( yoddint ) |
return( -MAXNUML ); |
return( MAXNUML ); |
#endif |
} |
if( y < 0.0L ) |
{ |
#ifdef MINUSZERO |
if( yoddint ) |
return( NEGZEROL ); |
#endif |
return( 0.0 ); |
} |
} |
nflg = 0; /* flag = 1 if x<0 raised to integer power */ |
if( x <= 0.0L ) |
{ |
if( x == 0.0L ) |
{ |
if( y < 0.0 ) |
{ |
#ifdef MINUSZERO |
if( signbitl(x) && yoddint ) |
return( -INFINITYL ); |
#endif |
#ifdef INFINITIES |
return( INFINITYL ); |
#else |
return( MAXNUML ); |
#endif |
} |
if( y > 0.0 ) |
{ |
#ifdef MINUSZERO |
if( signbitl(x) && yoddint ) |
return( NEGZEROL ); |
#endif |
return( 0.0 ); |
} |
if( y == 0.0L ) |
return( 1.0L ); /* 0**0 */ |
else |
return( 0.0L ); /* 0**y */ |
} |
else |
{ |
if( iyflg == 0 ) |
{ /* noninteger power of negative number */ |
mtherr( fname, DOMAIN ); |
_SET_ERRNO (EDOM); |
#ifdef NANS |
return(NANL); |
#else |
return(0.0L); |
#endif |
} |
nflg = 1; |
} |
} |
/* Integer power of an integer. */ |
if( iyflg ) |
{ |
i = w; |
w = floorl(x); |
if( (w == x) && (fabsl(y) < 32768.0) ) |
{ |
w = __powil( x, (int) y ); |
return( w ); |
} |
} |
if( nflg ) |
x = fabsl(x); |
/* separate significand from exponent */ |
x = frexpl( x, &i ); |
e = i; |
/* find significand in antilog table A[] */ |
i = 1; |
if( x <= douba(17) ) |
i = 17; |
if( x <= douba(i+8) ) |
i += 8; |
if( x <= douba(i+4) ) |
i += 4; |
if( x <= douba(i+2) ) |
i += 2; |
if( x >= douba(1) ) |
i = -1; |
i += 1; |
/* Find (x - A[i])/A[i] |
* in order to compute log(x/A[i]): |
* |
* log(x) = log( a x/a ) = log(a) + log(x/a) |
* |
* log(x/a) = log(1+v), v = x/a - 1 = (x-a)/a |
*/ |
x -= douba(i); |
x -= doubb(i/2); |
x /= douba(i); |
/* rational approximation for log(1+v): |
* |
* log(1+v) = v - v**2/2 + v**3 P(v) / Q(v) |
*/ |
z = x*x; |
w = x * ( z * polevll( x, P, 3 ) / p1evll( x, Q, 3 ) ); |
w = w - ldexpl( z, -1 ); /* w - 0.5 * z */ |
/* Convert to base 2 logarithm: |
* multiply by log2(e) = 1 + LOG2EA |
*/ |
z = LOG2EA * w; |
z += w; |
z += LOG2EA * x; |
z += x; |
/* Compute exponent term of the base 2 logarithm. */ |
w = -i; |
w = ldexpl( w, -LNXT ); /* divide by NXT */ |
w += e; |
/* Now base 2 log of x is w + z. */ |
/* Multiply base 2 log by y, in extended precision. */ |
/* separate y into large part ya |
* and small part yb less than 1/NXT |
*/ |
ya = reducl(y); |
yb = y - ya; |
/* (w+z)(ya+yb) |
* = w*ya + w*yb + z*y |
*/ |
F = z * y + w * yb; |
Fa = reducl(F); |
Fb = F - Fa; |
G = Fa + w * ya; |
Ga = reducl(G); |
Gb = G - Ga; |
H = Fb + Gb; |
Ha = reducl(H); |
w = ldexpl( Ga + Ha, LNXT ); |
/* Test the power of 2 for overflow */ |
if( w > MEXP ) |
{ |
_SET_ERRNO (ERANGE); |
mtherr( fname, OVERFLOW ); |
return( MAXNUML ); |
} |
if( w < MNEXP ) |
{ |
_SET_ERRNO (ERANGE); |
mtherr( fname, UNDERFLOW ); |
return( 0.0L ); |
} |
e = w; |
Hb = H - Ha; |
if( Hb > 0.0L ) |
{ |
e += 1; |
Hb -= (1.0L/NXT); /*0.0625L;*/ |
} |
/* Now the product y * log2(x) = Hb + e/NXT. |
* |
* Compute base 2 exponential of Hb, |
* where -0.0625 <= Hb <= 0. |
*/ |
z = Hb * polevll( Hb, R, 6 ); /* z = 2**Hb - 1 */ |
/* Express e/NXT as an integer plus a negative number of (1/NXT)ths. |
* Find lookup table entry for the fractional power of 2. |
*/ |
if( e < 0 ) |
i = 0; |
else |
i = 1; |
i = e/NXT + i; |
e = NXT*i - e; |
w = douba( e ); |
z = w * z; /* 2**-e * ( 1 + (2**Hb-1) ) */ |
z = z + w; |
z = ldexpl( z, i ); /* multiply by integer power of 2 */ |
if( nflg ) |
{ |
/* For negative x, |
* find out if the integer exponent |
* is odd or even. |
*/ |
w = ldexpl( y, -1 ); |
w = floorl(w); |
w = ldexpl( w, 1 ); |
if( w != y ) |
z = -z; /* odd exponent */ |
} |
return( z ); |
} |
static __inline__ long double |
__convert_inf_to_maxnum(long double x) |
{ |
if (isinf(x)) |
return (x > 0.0L ? MAXNUML : -MAXNUML); |
else |
return x; |
} |
/* Find a multiple of 1/NXT that is within 1/NXT of x. */ |
static __inline__ long double reducl(x) |
long double x; |
{ |
long double t; |
/* If the call to ldexpl overflows, set it to MAXNUML. |
This avoids Inf - Inf = Nan result when calculating the 'small' |
part of a reduction. Instead, the small part becomes Inf, |
causing under/overflow when adding it to the 'large' part. |
There must be a cleaner way of doing this. */ |
t = __convert_inf_to_maxnum (ldexpl( x, LNXT )); |
t = floorl( t ); |
t = ldexpl( t, -LNXT ); |
return(t); |
} |
/programs/develop/libraries/newlib/math/quad.h |
---|
0,0 → 1,271 |
/* Software floating-point emulation. |
Definitions for IEEE Quad Precision. |
Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz), |
David S. Miller (davem@redhat.com) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
#if _FP_W_TYPE_SIZE < 32 |
#error "Here's a nickel, kid. Go buy yourself a real computer." |
#endif |
#if _FP_W_TYPE_SIZE < 64 |
#define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE) |
#else |
#define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE) |
#endif |
#define _FP_FRACBITS_Q 113 |
#define _FP_FRACXBITS_Q (_FP_FRACTBITS_Q - _FP_FRACBITS_Q) |
#define _FP_WFRACBITS_Q (_FP_WORKBITS + _FP_FRACBITS_Q) |
#define _FP_WFRACXBITS_Q (_FP_FRACTBITS_Q - _FP_WFRACBITS_Q) |
#define _FP_EXPBITS_Q 15 |
#define _FP_EXPBIAS_Q 16383 |
#define _FP_EXPMAX_Q 32767 |
#define _FP_QNANBIT_Q \ |
((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE) |
#define _FP_QNANBIT_SH_Q \ |
((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE) |
#define _FP_IMPLBIT_Q \ |
((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE) |
#define _FP_IMPLBIT_SH_Q \ |
((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE) |
#define _FP_OVERFLOW_Q \ |
((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE)) |
typedef float TFtype __attribute__((mode(TF))); |
#if _FP_W_TYPE_SIZE < 64 |
union _FP_UNION_Q |
{ |
TFtype flt; |
struct |
{ |
#if __BYTE_ORDER == __BIG_ENDIAN |
unsigned sign : 1; |
unsigned exp : _FP_EXPBITS_Q; |
unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3); |
unsigned long frac2 : _FP_W_TYPE_SIZE; |
unsigned long frac1 : _FP_W_TYPE_SIZE; |
unsigned long frac0 : _FP_W_TYPE_SIZE; |
#else |
unsigned long frac0 : _FP_W_TYPE_SIZE; |
unsigned long frac1 : _FP_W_TYPE_SIZE; |
unsigned long frac2 : _FP_W_TYPE_SIZE; |
unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3); |
unsigned exp : _FP_EXPBITS_Q; |
unsigned sign : 1; |
#endif /* not bigendian */ |
} bits __attribute__((packed)); |
}; |
#define FP_DECL_Q(X) _FP_DECL(4,X) |
#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_4(Q,X,val) |
#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_4_P(Q,X,val) |
#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_4(Q,val,X) |
#define FP_PACK_RAW_QP(val,X) \ |
do { \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_4_P(Q,val,X); \ |
} while (0) |
#define FP_UNPACK_Q(X,val) \ |
do { \ |
_FP_UNPACK_RAW_4(Q,X,val); \ |
_FP_UNPACK_CANONICAL(Q,4,X); \ |
} while (0) |
#define FP_UNPACK_QP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_4_P(Q,X,val); \ |
_FP_UNPACK_CANONICAL(Q,4,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_Q(X,val) \ |
do { \ |
_FP_UNPACK_RAW_4(Q,X,val); \ |
_FP_UNPACK_SEMIRAW(Q,4,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_QP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_4_P(Q,X,val); \ |
_FP_UNPACK_SEMIRAW(Q,4,X); \ |
} while (0) |
#define FP_PACK_Q(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(Q,4,X); \ |
_FP_PACK_RAW_4(Q,val,X); \ |
} while (0) |
#define FP_PACK_QP(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(Q,4,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_4_P(Q,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_Q(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(Q,4,X); \ |
_FP_PACK_RAW_4(Q,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_QP(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(Q,4,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_4_P(Q,val,X); \ |
} while (0) |
#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X) |
#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X) |
#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y) |
#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,4,R,X,Y) |
#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,4,R,X,Y) |
#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,4,R,X,Y) |
#define FP_SQRT_Q(R,X) _FP_SQRT(Q,4,R,X) |
#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_4(R,S,T,X,Q) |
#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,4,r,X,Y,un) |
#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,4,r,X,Y) |
#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,4,r,X,Y) |
#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,4,r,X,rsz,rsg) |
#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,4,X,r,rs,rt) |
#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4(X) |
#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4(X) |
#else /* not _FP_W_TYPE_SIZE < 64 */ |
union _FP_UNION_Q |
{ |
TFtype flt /* __attribute__((mode(TF))) */ ; |
struct { |
_FP_W_TYPE a, b; |
} longs; |
struct { |
#if __BYTE_ORDER == __BIG_ENDIAN |
unsigned sign : 1; |
unsigned exp : _FP_EXPBITS_Q; |
_FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE; |
_FP_W_TYPE frac0 : _FP_W_TYPE_SIZE; |
#else |
_FP_W_TYPE frac0 : _FP_W_TYPE_SIZE; |
_FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE; |
unsigned exp : _FP_EXPBITS_Q; |
unsigned sign : 1; |
#endif |
} bits; |
}; |
#define FP_DECL_Q(X) _FP_DECL(2,X) |
#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_2(Q,X,val) |
#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_2_P(Q,X,val) |
#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_2(Q,val,X) |
#define FP_PACK_RAW_QP(val,X) \ |
do { \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_2_P(Q,val,X); \ |
} while (0) |
#define FP_UNPACK_Q(X,val) \ |
do { \ |
_FP_UNPACK_RAW_2(Q,X,val); \ |
_FP_UNPACK_CANONICAL(Q,2,X); \ |
} while (0) |
#define FP_UNPACK_QP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_2_P(Q,X,val); \ |
_FP_UNPACK_CANONICAL(Q,2,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_Q(X,val) \ |
do { \ |
_FP_UNPACK_RAW_2(Q,X,val); \ |
_FP_UNPACK_SEMIRAW(Q,2,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_QP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_2_P(Q,X,val); \ |
_FP_UNPACK_SEMIRAW(Q,2,X); \ |
} while (0) |
#define FP_PACK_Q(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(Q,2,X); \ |
_FP_PACK_RAW_2(Q,val,X); \ |
} while (0) |
#define FP_PACK_QP(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(Q,2,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_2_P(Q,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_Q(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(Q,2,X); \ |
_FP_PACK_RAW_2(Q,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_QP(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(Q,2,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_2_P(Q,val,X); \ |
} while (0) |
#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,2,X) |
#define FP_NEG_Q(R,X) _FP_NEG(Q,2,R,X) |
#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,2,R,X,Y) |
#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,2,R,X,Y) |
#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,2,R,X,Y) |
#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,2,R,X,Y) |
#define FP_SQRT_Q(R,X) _FP_SQRT(Q,2,R,X) |
#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q) |
#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,2,r,X,Y,un) |
#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,2,r,X,Y) |
#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,2,r,X,Y) |
#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,2,r,X,rsz,rsg) |
#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,2,X,r,rs,rt) |
#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2(X) |
#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X) |
#endif /* not _FP_W_TYPE_SIZE < 64 */ |
/programs/develop/libraries/newlib/math/remainder.S |
---|
0,0 → 1,19 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "remainder.S" |
.text |
.align 4 |
.globl _remainder |
.def _remainder; .scl 2; .type 32; .endef |
_remainder: |
fldl 12(%esp) |
fldl 4(%esp) |
1: fprem1 |
fstsw %ax |
sahf |
jp 1b |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/remainderf.S |
---|
0,0 → 1,19 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "remainderf.S" |
.text |
.align 4 |
.globl _remainder |
.def _remainderf; .scl 2; .type 32; .endef |
_remainderf: |
flds 8(%esp) |
flds 4(%esp) |
1: fprem1 |
fstsw %ax |
sahf |
jp 1b |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/remainderl.S |
---|
0,0 → 1,22 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "remainderl.S" |
.text |
.align 4 |
.globl _remainderl |
.def _remainderl; .scl 2; .type 32; .endef |
_remainderl: |
fldt 16(%esp) |
fldt 4(%esp) |
1: fprem1 |
fstsw %ax |
sahf |
jp 1b |
fstp %st(1) |
ret |
/programs/develop/libraries/newlib/math/remquo.S |
---|
0,0 → 1,38 |
/* |
* Written by Ulrich Drepper <drepper@cygnus.com>. |
* Based on e_remainder by J.T. Conklin <jtc@netbsd.org>. |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.ne |
* Public domain. |
*/ |
.file "remquo.S" |
.text |
.align 4; |
.globl _remquo; |
_remquo: |
fldl 4 +8(%esp) |
fldl 4(%esp) |
1: fprem1 |
fstsw %ax |
sahf |
jp 1b |
fstp %st(1) |
movl %eax, %ecx |
shrl $8, %eax |
shrl $12, %ecx |
andl $4, %ecx |
andl $3, %eax |
orl %eax, %ecx |
movl $0xef2960, %eax |
shrl %cl, %eax |
andl $3, %eax |
movl 4 +8 +8(%esp), %ecx |
movl 4 +4(%esp), %edx |
xorl 4 +8 +4(%esp), %edx |
testl $0x80000000, %edx |
jz 1f |
negl %eax |
1: movl %eax, (%ecx) |
ret |
/programs/develop/libraries/newlib/math/remquof.S |
---|
0,0 → 1,38 |
/* |
* Written by Ulrich Drepper <drepper@cygnus.com>. |
* Based on e_remainder by J.T. Conklin <jtc@netbsd.org>. |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.ne |
* Public domain. |
*/ |
.file "remquo.S" |
.text |
.align 4; |
.globl _remquof; |
_remquof: |
flds 4 +4(%esp) |
flds 4(%esp) |
1: fprem1 |
fstsw %ax |
sahf |
jp 1b |
fstp %st(1) |
movl %eax, %ecx |
shrl $8, %eax |
shrl $12, %ecx |
andl $4, %ecx |
andl $3, %eax |
orl %eax, %ecx |
movl $0xef2960, %eax |
shrl %cl, %eax |
andl $3, %eax |
movl 4 +4 +4(%esp), %ecx |
movl 4(%esp), %edx |
xorl 4 +4(%esp), %edx |
testl $0x80000000, %edx |
jz 1f |
negl %eax |
1: movl %eax, (%ecx) |
ret |
/programs/develop/libraries/newlib/math/remquol.S |
---|
0,0 → 1,36 |
/* |
* Written by Ulrich Drepper <drepper@cygnus.com>. |
* Based on e_remainder by J.T. Conklin <jtc@netbsd.org>. |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
* Public domain. |
*/ |
.text |
.align 4; |
.globl _remquol; |
_remquol: |
fldt 4 +12(%esp) |
fldt 4(%esp) |
1: fprem1 |
fstsw %ax |
sahf |
jp 1b |
fstp %st(1) |
movl %eax, %ecx |
shrl $8, %eax |
shrl $12, %ecx |
andl $4, %ecx |
andl $3, %eax |
orl %eax, %ecx |
movl $0xef2960, %eax |
shrl %cl, %eax |
andl $3, %eax |
movl 4 +12 +12(%esp), %ecx |
movl 4 +8(%esp), %edx |
xorl 4 +12 +8(%esp), %edx |
testl $0x8000, %edx |
jz 1f |
negl %eax |
1: movl %eax, (%ecx) |
ret |
/programs/develop/libraries/newlib/math/rint.c |
---|
0,0 → 1,6 |
#include <math.h> |
double rint (double x){ |
double retval; |
__asm__ ("frndint;" : "=t" (retval) : "0" (x)); |
return retval; |
} |
/programs/develop/libraries/newlib/math/rintf.c |
---|
0,0 → 1,7 |
#include <math.h> |
float rintf (float x){ |
float retval; |
__asm__ ("frndint;": "=t" (retval) : "0" (x)); |
return retval; |
} |
/programs/develop/libraries/newlib/math/rintl.c |
---|
0,0 → 1,7 |
#include <math.h> |
long double rintl (long double x){ |
long double retval; |
__asm__ ("frndint;": "=t" (retval) : "0" (x)); |
return retval; |
} |
/programs/develop/libraries/newlib/math/round_generic.c |
---|
0,0 → 1,51 |
/* |
* round_generic.c |
* |
* $Id: round_generic.c,v 1.1 2008/06/03 18:42:21 keithmarshall Exp $ |
* |
* Provides a generic implementation for the `round()', `roundf()' |
* and `roundl()' functions; compile with `-D FUNCTION=name', with |
* `name' set to each of these three in turn, to create separate |
* object files for each of the three functions. |
* |
* Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
* |
* This is free software. You may redistribute and/or modify it as you |
* see fit, without restriction of copyright. |
* |
* This software is provided "as is", in the hope that it may be useful, |
* but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of |
* MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no |
* time will the author accept any form of liability for any damages, |
* however caused, resulting from the use of this software. |
* |
*/ |
#ifndef FUNCTION |
/* |
* Normally specified with `-D FUNCTION=name', on the command line. |
* Valid FUNCTION names are `round', `roundf' and `roundl'; specifying |
* anything else will most likely cause a compilation error. If user |
* did not specify any FUNCTION name, default to `round'. |
*/ |
#define FUNCTION round |
#endif |
#include "round_internal.h" |
/* Generic implementation. |
* The user is required to specify the FUNCTION name; |
* the RETURN_TYPE and INPUT_TYPE macros resolve to appropriate |
* type declarations, to match the selected FUNCTION prototype. |
*/ |
RETURN_TYPE FUNCTION( INPUT_TYPE x ) |
{ |
/* Round to nearest integer, away from zero for half-way. |
* |
* We split it with the `round_internal()' function in |
* a private header file, so that it may be shared by this, |
* `lround()' and `llround()' implementations. |
*/ |
return isfinite( x ) ? round_internal( x ) : x; |
} |
/* $RCSfile: round_generic.c,v $$Revision: 1.1 $: end of file */ |
/programs/develop/libraries/newlib/math/round_internal.h |
---|
0,0 → 1,155 |
#ifndef _ROUND_INTERNAL_H |
/* |
* round_internal.h |
* |
* $Id: round_internal.h,v 1.1 2008/06/03 18:42:21 keithmarshall Exp $ |
* |
* Provides a generic implementation of the numerical rounding |
* algorithm, which is shared by all functions in the `round()', |
* `lround()' and `llround()' families. |
* |
* Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
* |
* This is free software. You may redistribute and/or modify it as you |
* see fit, without restriction of copyright. |
* |
* This software is provided "as is", in the hope that it may be useful, |
* but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of |
* MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no |
* time will the author accept any form of liability for any damages, |
* however caused, resulting from the use of this software. |
* |
*/ |
#define _ROUND_INTERNAL_H |
#include <math.h> |
#include <fenv.h> |
#define TYPE_PASTE( NAME, TYPE ) NAME##TYPE |
#define INPUT_TYPE INPUT_TYPEDEF( FUNCTION ) |
#define INPUT_TYPEDEF( FUNCTION ) TYPE_PASTE( FUNCTION, _input_type ) |
/* |
* The types for the formal parameter, to each of the derived functions. |
*/ |
#define round_input_type double |
#define roundf_input_type float |
#define roundl_input_type long double |
#define lround_input_type double |
#define lroundf_input_type float |
#define lroundl_input_type long double |
#define llround_input_type double |
#define llroundf_input_type float |
#define llroundl_input_type long double |
#define RETURN_TYPE RETURN_TYPEDEF( FUNCTION ) |
#define RETURN_TYPEDEF( FUNCTION ) TYPE_PASTE( FUNCTION, _return_type ) |
/* |
* The types for the return value, from each of the derived functions. |
*/ |
#define round_return_type double |
#define roundf_return_type float |
#define roundl_return_type long double |
#define lround_return_type long |
#define lroundf_return_type long |
#define lroundl_return_type long |
#define llround_return_type long long |
#define llroundf_return_type long long |
#define llroundl_return_type long long |
#define MAX_RETURN_VALUE RETURN_MAX( FUNCTION ) |
#define RETURN_MAX( FUNCTION ) TYPE_PASTE( FUNCTION, _return_max ) |
/* |
* The maximum values which may be returned by each of the derived functions |
* in the `lround' or the `llround' families. |
*/ |
#define lround_return_max LONG_MAX |
#define lroundf_return_max LONG_MAX |
#define lroundl_return_max LONG_MAX |
#define llround_return_max LLONG_MAX |
#define llroundf_return_max LLONG_MAX |
#define llroundl_return_max LLONG_MAX |
#define MIN_RETURN_VALUE RETURN_MIN( FUNCTION ) |
#define RETURN_MIN( FUNCTION ) TYPE_PASTE( FUNCTION, _return_min ) |
/* |
* The minimum values which may be returned by each of the derived functions |
* in the `lround' or the `llround' families. |
*/ |
#define lround_return_min LONG_MIN |
#define lroundf_return_min LONG_MIN |
#define lroundl_return_min LONG_MIN |
#define llround_return_min LLONG_MIN |
#define llroundf_return_min LLONG_MIN |
#define llroundl_return_min LLONG_MIN |
#define REF_VALUE( VALUE ) REF_TYPE( FUNCTION, VALUE ) |
#define REF_TYPE( FUNC, VAL ) TYPE_PASTE( FUNC, _ref )( VAL ) |
/* |
* Macros for expressing constant values of the appropriate data type, |
* for use in each of the derived functions. |
*/ |
#define round_ref( VALUE ) VALUE |
#define lround_ref( VALUE ) VALUE |
#define llround_ref( VALUE ) VALUE |
#define roundl_ref( VALUE ) TYPE_PASTE( VALUE, L ) |
#define lroundl_ref( VALUE ) TYPE_PASTE( VALUE, L ) |
#define llroundl_ref( VALUE ) TYPE_PASTE( VALUE, L ) |
#define roundf_ref( VALUE ) TYPE_PASTE( VALUE, F ) |
#define lroundf_ref( VALUE ) TYPE_PASTE( VALUE, F ) |
#define llroundf_ref( VALUE ) TYPE_PASTE( VALUE, F ) |
static __inline__ |
INPUT_TYPE __attribute__(( always_inline )) round_internal( INPUT_TYPE x ) |
#define ROUND_MODES ( FE_TONEAREST | FE_UPWARD | FE_DOWNWARD | FE_TOWARDZERO ) |
{ |
/* Generic helper function, for rounding of the input parameter value to |
* the nearest integer value. |
*/ |
INPUT_TYPE z; |
unsigned short saved_CW, tmp_required_CW; |
/* Rounding method suggested by Danny Smith <dannysmith@users.sf.net> |
* |
* Save the FPU control word state, set rounding mode TONEAREST, round the |
* input value, then restore the original FPU control word state. |
*/ |
__asm__( "fnstcw %0;" : "=m"( saved_CW )); |
tmp_required_CW = ( saved_CW & ~ROUND_MODES ) | FE_TONEAREST; |
__asm__( "fldcw %0;" :: "m"( tmp_required_CW )); |
__asm__( "frndint;" : "=t"( z ) : "0"( x )); |
__asm__( "fldcw %0;" :: "m"( saved_CW )); |
/* We now have a possible rounded value; unfortunately the FPU uses the |
* `round-to-even' rule for exact mid-way cases, where both C99 and POSIX |
* require us to always round away from zero, so we need to adjust those |
* mid-way cases which the FPU rounded in the wrong direction. |
* |
* Correction method suggested by Greg Chicares <gchicares@sbcglobal.net> |
*/ |
return x < REF_VALUE( 0.0 ) |
? /* |
* For negative input values, an incorrectly rounded value will be |
* exactly 0.5 greater than the original value; when we find such an |
* exact rounding offset, we must subtract an additional 1.0 from the |
* rounded result, otherwise we return the rounded result unchanged. |
*/ |
z - x == REF_VALUE( 0.5 ) ? z - REF_VALUE( 1.0 ) : z |
: /* For positive input values, an incorrectly rounded value will be |
* exactly 0.5 less than the original value; when we find such an exact |
* rounding offset, we must add an additional 1.0 to the rounded result, |
* otherwise we return the rounded result unchanged. |
*/ |
x - z == REF_VALUE( 0.5 ) ? z + REF_VALUE( 1.0 ) : z; |
} |
#endif /* !defined _ROUND_INTERNAL_H: $RCSfile: round_internal.h,v $: end of file */ |
/programs/develop/libraries/newlib/math/s_erf.c |
---|
0,0 → 1,345 |
/* @(#)s_erf.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. |
* ==================================================== |
*/ |
/* double erf(double x) |
* double erfc(double x) |
* x |
* 2 |\ |
* erf(x) = --------- | exp(-t*t)dt |
* sqrt(pi) \| |
* 0 |
* |
* erfc(x) = 1-erf(x) |
* Note that |
* erf(-x) = -erf(x) |
* erfc(-x) = 2 - erfc(x) |
* |
* Method: |
* 1. For |x| in [0, 0.84375] |
* erf(x) = x + x*R(x^2) |
* erfc(x) = 1 - erf(x) if x in [-.84375,0.25] |
* = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] |
* where R = P/Q where P is an odd poly of degree 8 and |
* Q is an odd poly of degree 10. |
* -57.90 |
* | R - (erf(x)-x)/x | <= 2 |
* |
* |
* Remark. The formula is derived by noting |
* erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) |
* and that |
* 2/sqrt(pi) = 1.128379167095512573896158903121545171688 |
* is close to one. The interval is chosen because the fix |
* point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is |
* near 0.6174), and by some experiment, 0.84375 is chosen to |
* guarantee the error is less than one ulp for erf. |
* |
* 2. For |x| in [0.84375,1.25], let s = |x| - 1, and |
* c = 0.84506291151 rounded to single (24 bits) |
* erf(x) = sign(x) * (c + P1(s)/Q1(s)) |
* erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 |
* 1+(c+P1(s)/Q1(s)) if x < 0 |
* |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 |
* Remark: here we use the taylor series expansion at x=1. |
* erf(1+s) = erf(1) + s*Poly(s) |
* = 0.845.. + P1(s)/Q1(s) |
* That is, we use rational approximation to approximate |
* erf(1+s) - (c = (single)0.84506291151) |
* Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] |
* where |
* P1(s) = degree 6 poly in s |
* Q1(s) = degree 6 poly in s |
* |
* 3. For x in [1.25,1/0.35(~2.857143)], |
* erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) |
* erf(x) = 1 - erfc(x) |
* where |
* R1(z) = degree 7 poly in z, (z=1/x^2) |
* S1(z) = degree 8 poly in z |
* |
* 4. For x in [1/0.35,28] |
* erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 |
* = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0 |
* = 2.0 - tiny (if x <= -6) |
* erf(x) = sign(x)*(1.0 - erfc(x)) if x < 6, else |
* erf(x) = sign(x)*(1.0 - tiny) |
* where |
* R2(z) = degree 6 poly in z, (z=1/x^2) |
* S2(z) = degree 7 poly in z |
* |
* Note1: |
* To compute exp(-x*x-0.5625+R/S), let s be a single |
* precision number and s := x; then |
* -x*x = -s*s + (s-x)*(s+x) |
* exp(-x*x-0.5626+R/S) = |
* exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S); |
* Note2: |
* Here 4 and 5 make use of the asymptotic series |
* exp(-x*x) |
* erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) ) |
* x*sqrt(pi) |
* We use rational approximation to approximate |
* g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625 |
* Here is the error bound for R1/S1 and R2/S2 |
* |R1/S1 - f(x)| < 2**(-62.57) |
* |R2/S2 - f(x)| < 2**(-61.52) |
* |
* 5. For inf > x >= 28 |
* erf(x) = sign(x) *(1 - tiny) (raise inexact) |
* erfc(x) = tiny*tiny (raise underflow) if x > 0 |
* = 2 - tiny if x<0 |
* |
* 7. Special case: |
* erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, |
* erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, |
* erfc/erf(NaN) is NaN |
*/ |
/* #include "fdlibm.h" */ |
#include <math.h> |
#include <stdint.h> |
#include <errno.h> |
#define __ieee754_exp exp |
typedef union |
{ |
double value; |
struct |
{ |
uint32_t lsw; |
uint32_t msw; |
} parts; |
} ieee_double_shape_type; |
static inline int __get_hi_word(const double x) |
{ |
ieee_double_shape_type u; |
u.value = x; |
return u.parts.msw; |
} |
static inline void __trunc_lo_word(double *x) |
{ |
ieee_double_shape_type u; |
u.value = *x; |
u.parts.lsw = 0; |
*x = u.value; |
} |
#ifdef __STDC__ |
static const double |
#else |
static double |
#endif |
tiny = 1e-300, |
half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ |
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ |
two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ |
/* c = (float)0.84506291151 */ |
erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ |
/* |
* Coefficients for approximation to erf on [0,0.84375] |
*/ |
efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */ |
efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ |
pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ |
pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ |
pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ |
pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ |
pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ |
qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ |
qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ |
qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ |
qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ |
qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ |
/* |
* Coefficients for approximation to erf in [0.84375,1.25] |
*/ |
pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ |
pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ |
pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ |
pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ |
pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ |
pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ |
pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ |
qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ |
qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ |
qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ |
qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ |
qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ |
qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ |
/* |
* Coefficients for approximation to erfc in [1.25,1/0.35] |
*/ |
ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ |
ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ |
ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ |
ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ |
ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ |
ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ |
ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ |
ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ |
sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ |
sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ |
sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ |
sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ |
sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ |
sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ |
sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ |
sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ |
/* |
* Coefficients for approximation to erfc in [1/.35,28] |
*/ |
rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ |
rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ |
rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ |
rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ |
rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ |
rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ |
rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ |
sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ |
sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ |
sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ |
sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ |
sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ |
sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ |
sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ |
#ifdef __STDC__ |
double erf(double x) |
#else |
double erf(x) |
double x; |
#endif |
{ |
int hx,ix,i; |
double R,S,P,Q,s,y,z,r; |
hx = __get_hi_word(x); |
ix = hx&0x7fffffff; |
if(ix>=0x7ff00000) { /* erf(nan)=nan */ |
i = ((unsigned)hx>>31)<<1; |
return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */ |
} |
if(ix < 0x3feb0000) { /* |x|<0.84375 */ |
if(ix < 0x3e300000) { /* |x|<2**-28 */ |
if (ix < 0x00800000) |
return 0.125*(8.0*x+efx8*x); /*avoid underflow */ |
return x + efx*x; |
} |
z = x*x; |
r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); |
s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); |
y = r/s; |
return x + x*y; |
} |
if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ |
s = fabs(x)-one; |
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); |
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); |
if(hx>=0) return erx + P/Q; else return -erx - P/Q; |
} |
if (ix >= 0x40180000) { /* inf>|x|>=6 */ |
if(hx>=0) return one-tiny; else return tiny-one; |
} |
x = fabs(x); |
s = one/(x*x); |
if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */ |
R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( |
ra5+s*(ra6+s*ra7)))))); |
S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( |
sa5+s*(sa6+s*(sa7+s*sa8))))))); |
} else { /* |x| >= 1/0.35 */ |
R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( |
rb5+s*rb6))))); |
S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( |
sb5+s*(sb6+s*sb7)))))); |
} |
z = x; |
__trunc_lo_word(&z); |
r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S); |
if(hx>=0) return one-r/x; else return r/x-one; |
} |
#ifdef __STDC__ |
double erfc(double x) |
#else |
double erfc(x) |
double x; |
#endif |
{ |
int hx,ix; |
double R,S,P,Q,s,y,z,r; |
hx = __get_hi_word(x); |
ix = hx&0x7fffffff; |
if(ix>=0x7ff00000) { /* erfc(nan)=nan */ |
/* erfc(+-inf)=0,2 */ |
return (double)(((unsigned)hx>>31)<<1)+one/x; |
} |
if(ix < 0x3feb0000) { /* |x|<0.84375 */ |
if(ix < 0x3c700000) /* |x|<2**-56 */ |
return one-x; |
z = x*x; |
r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); |
s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); |
y = r/s; |
if(hx < 0x3fd00000) { /* x<1/4 */ |
return one-(x+x*y); |
} else { |
r = x*y; |
r += (x-half); |
return half - r ; |
} |
} |
if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ |
s = fabs(x)-one; |
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); |
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); |
if(hx>=0) { |
z = one-erx; return z - P/Q; |
} else { |
z = erx+P/Q; return one+z; |
} |
} |
if (ix < 0x403c0000) { /* |x|<28 */ |
x = fabs(x); |
s = one/(x*x); |
if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/ |
R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( |
ra5+s*(ra6+s*ra7)))))); |
S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( |
sa5+s*(sa6+s*(sa7+s*sa8))))))); |
} else { /* |x| >= 1/.35 ~ 2.857143 */ |
if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */ |
R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( |
rb5+s*rb6))))); |
S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( |
sb5+s*(sb6+s*sb7)))))); |
} |
z = x; |
__trunc_lo_word(&z); |
r = __ieee754_exp(-z*z-0.5625)* |
__ieee754_exp((z-x)*(z+x)+R/S); |
if(hx>0) return r/x; else return two-r/x; |
} else { |
/* set range error */ |
errno = ERANGE; |
if(hx>0) return tiny*tiny; else return two-tiny; |
} |
} |
/programs/develop/libraries/newlib/math/s_expm1.S |
---|
0,0 → 1,70 |
/* ix87 specific implementation of exp(x)-1. |
Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. |
Based on code by John C. Bowman <bowman@ipp-garching.mpg.de>. |
Corrections by H.J. Lu (hjl@gnu.ai.mit.edu), 1997. |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
02111-1307 USA. */ |
/* Using: e^x - 1 = 2^(x * log2(e)) - 1 */ |
.file "s_expm1.s" |
.text |
.align 4 |
minus1: .double -1.0 |
one: .double 1.0 |
l2e: .tfloat 1.442695040888963407359924681002 |
.align 4 |
.globl ___expm1 |
.def __expm1; .scl 2; .type 32; .endef |
___expm1: |
fldl 4(%esp) # x |
fxam # Is NaN or +-Inf? |
fstsw %ax |
movb $0x45, %ch |
andb %ah, %ch |
cmpb $0x40, %ch |
je 3f # If +-0, jump. |
cmpb $0x05, %ch |
je 2f # If +-Inf, jump. |
fldt l2e # log2(e) : x |
fmulp # log2(e)*x |
fld %st # log2(e)*x : log2(e)*x |
frndint # int(log2(e)*x) : log2(e)*x |
fsubr %st, %st(1) # int(log2(e)*x) : fract(log2(e)*x) |
fxch # fract(log2(e)*x) : int(log2(e)*x) |
f2xm1 # 2^fract(log2(e)*x)-1 : int(log2(e)*x) |
fscale # 2^(log2(e)*x)-2^int(log2(e)*x) : int(log2(e)*x) |
fxch # int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) |
fldl one # 1 : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) |
fscale # 2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) |
fsubrl one # 1-2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) |
fstp %st(1) # 1-2^int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) |
fsubrp %st, %st(1) # 2^(log2(e)*x) |
ret |
2: testl $0x200, %eax # Test sign. |
jz 3f # If positive, jump. |
fstp %st |
fldl minus1 # Set result to -1.0. |
3: ret |
/programs/develop/libraries/newlib/math/s_fpclassify.c |
---|
0,0 → 1,31 |
/* Copyright (C) 2002, 2007 by Red Hat, Incorporated. All rights reserved. |
* |
* Permission to use, copy, modify, and distribute this software |
* is freely granted, provided that this notice is preserved. |
*/ |
#include "fdlibm.h" |
int |
__fpclassifyd (double x) |
{ |
__uint32_t msw, lsw; |
EXTRACT_WORDS(msw,lsw,x); |
if ((msw == 0x00000000 && lsw == 0x00000000) || |
(msw == 0x80000000 && lsw == 0x00000000)) |
return FP_ZERO; |
else if ((msw >= 0x00100000 && msw <= 0x7fefffff) || |
(msw >= 0x80100000 && msw <= 0xffefffff)) |
return FP_NORMAL; |
else if ((msw >= 0x00000000 && msw <= 0x000fffff) || |
(msw >= 0x80000000 && msw <= 0x800fffff)) |
/* zero is already handled above */ |
return FP_SUBNORMAL; |
else if ((msw == 0x7ff00000 && lsw == 0x00000000) || |
(msw == 0xfff00000 && lsw == 0x00000000)) |
return FP_INFINITE; |
else |
return FP_NAN; |
} |
/programs/develop/libraries/newlib/math/s_isnand.c |
---|
0,0 → 1,31 |
/* |
* ==================================================== |
* 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. |
* ==================================================== |
*/ |
/* |
* __isnand(x) returns 1 is x is nan, else 0; |
* no branching! |
*/ |
#include "fdlibm.h" |
int |
_DEFUN (__isnand, (x), |
double x) |
{ |
__int32_t hx,lx; |
EXTRACT_WORDS(hx,lx,x); |
hx &= 0x7fffffff; |
hx |= (__uint32_t)(lx|(-lx))>>31; |
hx = 0x7ff00000 - hx; |
return (int)(((__uint32_t)(hx))>>31); |
} |
/programs/develop/libraries/newlib/math/s_modf.c |
---|
0,0 → 1,131 |
/* @(#)s_modf.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* 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. |
* ==================================================== |
*/ |
/* |
FUNCTION |
<<modf>>, <<modff>>---split fractional and integer parts |
INDEX |
modf |
INDEX |
modff |
ANSI_SYNOPSIS |
#include <math.h> |
double modf(double <[val]>, double *<[ipart]>); |
float modff(float <[val]>, float *<[ipart]>); |
TRAD_SYNOPSIS |
#include <math.h> |
double modf(<[val]>, <[ipart]>) |
double <[val]>; |
double *<[ipart]>; |
float modff(<[val]>, <[ipart]>) |
float <[val]>; |
float *<[ipart]>; |
DESCRIPTION |
<<modf>> splits the double <[val]> apart into an integer part |
and a fractional part, returning the fractional part and |
storing the integer part in <<*<[ipart]>>>. No rounding |
whatsoever is done; the sum of the integer and fractional |
parts is guaranteed to be exactly equal to <[val]>. That |
is, if <[realpart]> = modf(<[val]>, &<[intpart]>); then |
`<<<[realpart]>+<[intpart]>>>' is the same as <[val]>. |
<<modff>> is identical, save that it takes and returns |
<<float>> rather than <<double>> values. |
RETURNS |
The fractional part is returned. Each result has the same |
sign as the supplied argument <[val]>. |
PORTABILITY |
<<modf>> is ANSI C. <<modff>> is an extension. |
QUICKREF |
modf ansi pure |
modff - pure |
*/ |
/* |
* modf(double x, double *iptr) |
* return fraction part of x, and return x's integral part in *iptr. |
* Method: |
* Bit twiddling. |
* |
* Exception: |
* No exception. |
*/ |
#include "fdlibm.h" |
#ifndef _DOUBLE_IS_32BITS |
#ifdef __STDC__ |
static const double one = 1.0; |
#else |
static double one = 1.0; |
#endif |
#ifdef __STDC__ |
double modf(double x, double *iptr) |
#else |
double modf(x, iptr) |
double x,*iptr; |
#endif |
{ |
__int32_t i0,i1,j0; |
__uint32_t i; |
EXTRACT_WORDS(i0,i1,x); |
j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */ |
if(j0<20) { /* integer part in high x */ |
if(j0<0) { /* |x|<1 */ |
INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */ |
return x; |
} else { |
i = (0x000fffff)>>j0; |
if(((i0&i)|i1)==0) { /* x is integral */ |
__uint32_t high; |
*iptr = x; |
GET_HIGH_WORD(high,x); |
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */ |
return x; |
} else { |
INSERT_WORDS(*iptr,i0&(~i),0); |
return x - *iptr; |
} |
} |
} else if (j0>51) { /* no fraction part */ |
__uint32_t high; |
*iptr = x*one; |
GET_HIGH_WORD(high,x); |
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */ |
return x; |
} else { /* fraction part in low x */ |
i = ((__uint32_t)(0xffffffff))>>(j0-20); |
if((i1&i)==0) { /* x is integral */ |
__uint32_t high; |
*iptr = x; |
GET_HIGH_WORD(high,x); |
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */ |
return x; |
} else { |
INSERT_WORDS(*iptr,i0,i1&(~i)); |
return x - *iptr; |
} |
} |
} |
#endif /* _DOUBLE_IS_32BITS */ |
/programs/develop/libraries/newlib/math/s_roundf.c |
---|
0,0 → 1,70 |
/* Round float to integer away from zero. |
Copyright (C) 1997 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
02111-1307 USA. */ |
#include <math.h> |
#include "fdlibm.h" |
static const float huge = 1.0e30; |
float roundf (float x) |
{ |
int i0, j0; |
GET_FLOAT_WORD (i0, x); |
j0 = ((i0 >> 23) & 0xff) - 0x7f; |
if (j0 < 23) |
{ |
if (j0 < 0) |
{ |
if (huge + x > 0.0F) |
{ |
i0 &= 0x80000000; |
if (j0 == -1) |
i0 |= 0x3f800000; |
} |
} |
else |
{ |
unsigned int i = 0x007fffff >> j0; |
if ((i0 & i) == 0) |
/* X is integral. */ |
return x; |
if (huge + x > 0.0F) |
{ |
/* Raise inexact if x != 0. */ |
i0 += 0x00400000 >> j0; |
i0 &= ~i; |
} |
} |
} |
else |
{ |
if (j0 == 0x80) |
/* Inf or NaN. */ |
return x + x; |
else |
return x; |
} |
SET_FLOAT_WORD (x, i0); |
return x; |
} |
/programs/develop/libraries/newlib/math/s_signbit.c |
---|
0,0 → 1,30 |
/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. |
* |
* Permission to use, copy, modify, and distribute this software |
* is freely granted, provided that this notice is preserved. |
*/ |
#include "fdlibm.h" |
int __signbitf (float x); |
int __signbitd (double x); |
int |
__signbitf (float x) |
{ |
unsigned int w; |
GET_FLOAT_WORD(w,x); |
return (w & 0x80000000); |
} |
int |
__signbitd (double x) |
{ |
unsigned int msw; |
GET_HIGH_WORD(msw, x); |
return (msw & 0x80000000); |
} |
/programs/develop/libraries/newlib/math/s_tanh.c |
---|
0,0 → 1,80 |
/* @(#)s_tanh.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* 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. |
* ==================================================== |
*/ |
/* Tanh(x) |
* Return the Hyperbolic Tangent of x |
* |
* Method : |
* x -x |
* e - e |
* 0. tanh(x) is defined to be ----------- |
* x -x |
* e + e |
* 1. reduce x to non-negative by tanh(-x) = -tanh(x). |
* 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x) |
* -t |
* 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x) |
* t + 2 |
* 2 |
* 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t=expm1(2x) |
* t + 2 |
* 22.0 < x <= INF : tanh(x) := 1. |
* |
* Special cases: |
* tanh(NaN) is NaN; |
* only tanh(0)=0 is exact for finite argument. |
*/ |
#include <math.h> |
#include "fdlibm.h" |
#ifdef __STDC__ |
static const double one=1.0, two=2.0, tiny = 1.0e-300; |
#else |
static double one=1.0, two=2.0, tiny = 1.0e-300; |
#endif |
double tanh(double x) |
{ |
double t,z; |
int jx,ix,lx; |
/* High word of |x|. */ |
EXTRACT_WORDS(jx,lx,x); |
ix = jx&0x7fffffff; |
/* x is INF or NaN */ |
if(ix>=0x7ff00000) { |
if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ |
else return one/x-one; /* tanh(NaN) = NaN */ |
} |
/* |x| < 22 */ |
if (ix < 0x40360000) { /* |x|<22 */ |
if ((ix | lx) == 0) |
return x; /* x == +-0 */ |
if (ix<0x3c800000) /* |x|<2**-55 */ |
return x*(one+x); /* tanh(small) = small */ |
if (ix>=0x3ff00000) { /* |x|>=1 */ |
t = __expm1(two*fabs(x)); |
z = one - two/(t+two); |
} else { |
t = __expm1(-two*fabs(x)); |
z= -t/(t+two); |
} |
/* |x| > 22, return +-1 */ |
} else { |
z = one - tiny; /* raised inexact flag */ |
} |
return (jx>=0)? z: -z; |
} |
/programs/develop/libraries/newlib/math/scalbn.S |
---|
0,0 → 1,19 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "scalbn.S" |
.text |
.align 4 |
.globl _scalbn |
.def _scalbn; .scl 2; .type 32; .endef |
_scalbn: |
fildl 12(%esp) |
fldl 4(%esp) |
fscale |
fstp %st(1) |
ret |
.globl _scalbln |
.set _scalbln,_scalbn |
/programs/develop/libraries/newlib/math/scalbnf.S |
---|
0,0 → 1,19 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
*/ |
.file "scalbnf.S" |
.text |
.align 4 |
.globl _scalbnf |
.def _scalbnf; .scl 2; .type 32; .endef |
_scalbnf: |
fildl 8(%esp) |
flds 4(%esp) |
fscale |
fstp %st(1) |
ret |
.globl _scalblnf |
.set _scalblnf,_scalbnf |
/programs/develop/libraries/newlib/math/scalbnl.S |
---|
0,0 → 1,20 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Changes for long double by Ulrich Drepper <drepper@cygnus.com> |
* Public domain. |
*/ |
.file "scalbnl.S" |
.text |
.align 4 |
.globl _scalbnl |
.def _scalbnl; .scl 2; .type 32; .endef |
_scalbnl: |
fildl 16(%esp) |
fldt 4(%esp) |
fscale |
fstp %st(1) |
ret |
.globl _scalblnl |
.set _scalblnl,_scalbnl |
/programs/develop/libraries/newlib/math/sf_erf.c |
---|
0,0 → 1,267 |
/* sf_erf.c -- float version of s_erf.c. |
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. |
*/ |
/* |
* ==================================================== |
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
* |
* Developed at SunPro, a Sun Microsystems, Inc. business. |
* Permission to use, copy, modify, and distribute this |
* software is freely granted, provided that this notice |
* is preserved. |
* ==================================================== |
*/ |
/* |
#include "fdlibm.h" |
*/ |
#include <math.h> |
#include <stdint.h> |
#include <errno.h> |
#define __ieee754_expf expf |
typedef union |
{ |
float value; |
uint32_t word; |
} ieee_float_shape_type; |
/* Get a 32 bit int from a float. */ |
static inline int |
__get_float_word(float d) |
{ |
ieee_float_shape_type u; |
u.value = d; |
return u.word; |
} |
/* Set a float from a 32 bit int. */ |
#define SET_FLOAT_WORD(d,i) \ |
do { \ |
ieee_float_shape_type sf_u; \ |
sf_u.word = (i); \ |
(d) = sf_u.value; \ |
} while (0) |
static inline void __trunc_float_word(float * x) |
{ |
ieee_float_shape_type u; |
u.value = * x; |
u.word &= 0xfffff000; |
} |
#ifdef __v810__ |
#define const |
#endif |
#ifdef __STDC__ |
static const float |
#else |
static float |
#endif |
tiny = 1e-30, |
half= 5.0000000000e-01, /* 0x3F000000 */ |
one = 1.0000000000e+00, /* 0x3F800000 */ |
two = 2.0000000000e+00, /* 0x40000000 */ |
/* c = (subfloat)0.84506291151 */ |
erx = 8.4506291151e-01, /* 0x3f58560b */ |
/* |
* Coefficients for approximation to erf on [0,0.84375] |
*/ |
efx = 1.2837916613e-01, /* 0x3e0375d4 */ |
efx8= 1.0270333290e+00, /* 0x3f8375d4 */ |
pp0 = 1.2837916613e-01, /* 0x3e0375d4 */ |
pp1 = -3.2504209876e-01, /* 0xbea66beb */ |
pp2 = -2.8481749818e-02, /* 0xbce9528f */ |
pp3 = -5.7702702470e-03, /* 0xbbbd1489 */ |
pp4 = -2.3763017452e-05, /* 0xb7c756b1 */ |
qq1 = 3.9791721106e-01, /* 0x3ecbbbce */ |
qq2 = 6.5022252500e-02, /* 0x3d852a63 */ |
qq3 = 5.0813062117e-03, /* 0x3ba68116 */ |
qq4 = 1.3249473704e-04, /* 0x390aee49 */ |
qq5 = -3.9602282413e-06, /* 0xb684e21a */ |
/* |
* Coefficients for approximation to erf in [0.84375,1.25] |
*/ |
pa0 = -2.3621185683e-03, /* 0xbb1acdc6 */ |
pa1 = 4.1485610604e-01, /* 0x3ed46805 */ |
pa2 = -3.7220788002e-01, /* 0xbebe9208 */ |
pa3 = 3.1834661961e-01, /* 0x3ea2fe54 */ |
pa4 = -1.1089469492e-01, /* 0xbde31cc2 */ |
pa5 = 3.5478305072e-02, /* 0x3d1151b3 */ |
pa6 = -2.1663755178e-03, /* 0xbb0df9c0 */ |
qa1 = 1.0642088205e-01, /* 0x3dd9f331 */ |
qa2 = 5.4039794207e-01, /* 0x3f0a5785 */ |
qa3 = 7.1828655899e-02, /* 0x3d931ae7 */ |
qa4 = 1.2617121637e-01, /* 0x3e013307 */ |
qa5 = 1.3637083583e-02, /* 0x3c5f6e13 */ |
qa6 = 1.1984500103e-02, /* 0x3c445aa3 */ |
/* |
* Coefficients for approximation to erfc in [1.25,1/0.35] |
*/ |
ra0 = -9.8649440333e-03, /* 0xbc21a093 */ |
ra1 = -6.9385856390e-01, /* 0xbf31a0b7 */ |
ra2 = -1.0558626175e+01, /* 0xc128f022 */ |
ra3 = -6.2375331879e+01, /* 0xc2798057 */ |
ra4 = -1.6239666748e+02, /* 0xc322658c */ |
ra5 = -1.8460508728e+02, /* 0xc3389ae7 */ |
ra6 = -8.1287437439e+01, /* 0xc2a2932b */ |
ra7 = -9.8143291473e+00, /* 0xc11d077e */ |
sa1 = 1.9651271820e+01, /* 0x419d35ce */ |
sa2 = 1.3765776062e+02, /* 0x4309a863 */ |
sa3 = 4.3456588745e+02, /* 0x43d9486f */ |
sa4 = 6.4538726807e+02, /* 0x442158c9 */ |
sa5 = 4.2900814819e+02, /* 0x43d6810b */ |
sa6 = 1.0863500214e+02, /* 0x42d9451f */ |
sa7 = 6.5702495575e+00, /* 0x40d23f7c */ |
sa8 = -6.0424413532e-02, /* 0xbd777f97 */ |
/* |
* Coefficients for approximation to erfc in [1/.35,28] |
*/ |
rb0 = -9.8649431020e-03, /* 0xbc21a092 */ |
rb1 = -7.9928326607e-01, /* 0xbf4c9dd4 */ |
rb2 = -1.7757955551e+01, /* 0xc18e104b */ |
rb3 = -1.6063638306e+02, /* 0xc320a2ea */ |
rb4 = -6.3756646729e+02, /* 0xc41f6441 */ |
rb5 = -1.0250950928e+03, /* 0xc480230b */ |
rb6 = -4.8351919556e+02, /* 0xc3f1c275 */ |
sb1 = 3.0338060379e+01, /* 0x41f2b459 */ |
sb2 = 3.2579251099e+02, /* 0x43a2e571 */ |
sb3 = 1.5367296143e+03, /* 0x44c01759 */ |
sb4 = 3.1998581543e+03, /* 0x4547fdbb */ |
sb5 = 2.5530502930e+03, /* 0x451f90ce */ |
sb6 = 4.7452853394e+02, /* 0x43ed43a7 */ |
sb7 = -2.2440952301e+01; /* 0xc1b38712 */ |
#ifdef __STDC__ |
float erff(float x) |
#else |
float erff(x) |
float x; |
#endif |
{ |
int32_t hx,ix,i; |
float R,S,P,Q,s,y,z,r; |
hx = __get_float_word(x); |
ix = hx&0x7fffffff; |
if(!(ix<0x7f800000L)) { /* erf(nan)=nan */ |
i = ((uint32_t)hx>>31)<<1; |
return (float)(1-i)+one/x; /* erf(+-inf)=+-1 */ |
} |
if(ix < 0x3f580000) { /* |x|<0.84375 */ |
if(ix < 0x31800000) { /* |x|<2**-28 */ |
if (ix < 0x04000000) |
/*avoid underflow */ |
return (float)0.125*((float)8.0*x+efx8*x); |
return x + efx*x; |
} |
z = x*x; |
r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); |
s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); |
y = r/s; |
return x + x*y; |
} |
if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ |
s = fabsf(x)-one; |
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); |
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); |
if(hx>=0) return erx + P/Q; else return -erx - P/Q; |
} |
if (ix >= 0x40c00000) { /* inf>|x|>=6 */ |
if(hx>=0) return one-tiny; else return tiny-one; |
} |
x = fabsf(x); |
s = one/(x*x); |
if(ix< 0x4036DB6E) { /* |x| < 1/0.35 */ |
R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( |
ra5+s*(ra6+s*ra7)))))); |
S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( |
sa5+s*(sa6+s*(sa7+s*sa8))))))); |
} else { /* |x| >= 1/0.35 */ |
R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( |
rb5+s*rb6))))); |
S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( |
sb5+s*(sb6+s*sb7)))))); |
} |
z = x; |
__trunc_float_word (&z); |
r = __ieee754_expf(-z*z-(float)0.5625)*__ieee754_expf((z-x)*(z+x)+R/S); |
if(hx>=0) return one-r/x; else return r/x-one; |
} |
#ifdef __STDC__ |
float erfcf(float x) |
#else |
float erfcf(x) |
float x; |
#endif |
{ |
int32_t hx,ix; |
float R,S,P,Q,s,y,z,r; |
hx = __get_float_word(x); |
ix = hx&0x7fffffff; |
if(!(ix<0x7f800000L)) { /* erfc(nan)=nan */ |
/* erfc(+-inf)=0,2 */ |
return (float)(((uint32_t)hx>>31)<<1)+one/x; |
} |
if(ix < 0x3f580000) { /* |x|<0.84375 */ |
if(ix < 0x23800000) /* |x|<2**-56 */ |
return one-x; |
z = x*x; |
r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); |
s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); |
y = r/s; |
if(hx < 0x3e800000) { /* x<1/4 */ |
return one-(x+x*y); |
} else { |
r = x*y; |
r += (x-half); |
return half - r ; |
} |
} |
if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ |
s = fabsf(x)-one; |
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); |
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); |
if(hx>=0) { |
z = one-erx; return z - P/Q; |
} else { |
z = erx+P/Q; return one+z; |
} |
} |
if (ix < 0x41e00000) { /* |x|<28 */ |
x = fabsf(x); |
s = one/(x*x); |
if(ix< 0x4036DB6D) { /* |x| < 1/.35 ~ 2.857143*/ |
R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( |
ra5+s*(ra6+s*ra7)))))); |
S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( |
sa5+s*(sa6+s*(sa7+s*sa8))))))); |
} else { /* |x| >= 1/.35 ~ 2.857143 */ |
if(hx<0&&ix>=0x40c00000) return two-tiny;/* x < -6 */ |
R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( |
rb5+s*rb6))))); |
S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( |
sb5+s*(sb6+s*sb7)))))); |
} |
z = x; |
__trunc_float_word (&z); |
r = __ieee754_expf(-z*z-(float)0.5625)* |
__ieee754_expf((z-x)*(z+x)+R/S); |
if(hx>0) return r/x; else return two-r/x; |
} else { |
/* set range error */ |
errno = ERANGE; |
if(hx>0) return tiny*tiny; else return two-tiny; |
} |
} |
/programs/develop/libraries/newlib/math/signbit.c |
---|
0,0 → 1,21 |
#define __FP_SIGNBIT 0x0200 |
int __signbit (double x) { |
unsigned short sw; |
__asm__ ("fxam; fstsw %%ax;" |
: "=a" (sw) |
: "t" (x) ); |
return (sw & __FP_SIGNBIT) != 0; |
} |
int __signbitd (double x) { |
unsigned short sw; |
__asm__ ("fxam; fstsw %%ax;" |
: "=a" (sw) |
: "t" (x) ); |
return (sw & __FP_SIGNBIT) != 0; |
} |
#undef signbit |
int __attribute__ ((alias ("__signbit"))) signbit (double); |
/programs/develop/libraries/newlib/math/signbitf.c |
---|
0,0 → 1,10 |
#define __FP_SIGNBIT 0x0200 |
int __signbitf (float x) { |
unsigned short sw; |
__asm__ ("fxam; fstsw %%ax;" |
: "=a" (sw) |
: "t" (x) ); |
return (sw & __FP_SIGNBIT) != 0; |
} |
int __attribute__ ((alias ("__signbitf"))) signbitf (float); |
/programs/develop/libraries/newlib/math/signbitl.c |
---|
0,0 → 1,11 |
#define __FP_SIGNBIT 0x0200 |
int __signbitl (long double x) { |
unsigned short sw; |
__asm__ ("fxam; fstsw %%ax;" |
: "=a" (sw) |
: "t" (x) ); |
return (sw & __FP_SIGNBIT) != 0; |
} |
int __attribute__ ((alias ("__signbitl"))) signbitl (long double); |
/programs/develop/libraries/newlib/math/sin.S |
---|
0,0 → 1,30 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "sin.s" |
.text |
.align 4 |
.globl _sin |
.def _sin; .scl 2; .type 32; .endef |
_sin: |
fldl 4(%esp) |
fsin |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fnstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fsin |
ret |
/programs/develop/libraries/newlib/math/sinf.S |
---|
0,0 → 1,32 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "sinf.S" |
.text |
.align 4 |
.globl _sinf |
.def _sinf; .scl 2; .type 32; .endef |
_sinf: |
flds 4(%esp) |
fsin |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fnstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fsin |
ret |
/programs/develop/libraries/newlib/math/single.h |
---|
0,0 → 1,151 |
/* Software floating-point emulation. |
Definitions for IEEE Single Precision. |
Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz), |
David S. Miller (davem@redhat.com) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
#if _FP_W_TYPE_SIZE < 32 |
#error "Here's a nickel kid. Go buy yourself a real computer." |
#endif |
#define _FP_FRACTBITS_S _FP_W_TYPE_SIZE |
#define _FP_FRACBITS_S 24 |
#define _FP_FRACXBITS_S (_FP_FRACTBITS_S - _FP_FRACBITS_S) |
#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S) |
#define _FP_WFRACXBITS_S (_FP_FRACTBITS_S - _FP_WFRACBITS_S) |
#define _FP_EXPBITS_S 8 |
#define _FP_EXPBIAS_S 127 |
#define _FP_EXPMAX_S 255 |
#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2)) |
#define _FP_QNANBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2+_FP_WORKBITS)) |
#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1)) |
#define _FP_IMPLBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1+_FP_WORKBITS)) |
#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S)) |
/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be |
chosen by the target machine. */ |
typedef float SFtype __attribute__((mode(SF))); |
union _FP_UNION_S |
{ |
SFtype flt; |
struct { |
#if __BYTE_ORDER == __BIG_ENDIAN |
unsigned sign : 1; |
unsigned exp : _FP_EXPBITS_S; |
unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); |
#else |
unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); |
unsigned exp : _FP_EXPBITS_S; |
unsigned sign : 1; |
#endif |
} bits __attribute__((packed)); |
}; |
#define FP_DECL_S(X) _FP_DECL(1,X) |
#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val) |
#define FP_UNPACK_RAW_SP(X,val) _FP_UNPACK_RAW_1_P(S,X,val) |
#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X) |
#define FP_PACK_RAW_SP(val,X) \ |
do { \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_1_P(S,val,X); \ |
} while (0) |
#define FP_UNPACK_S(X,val) \ |
do { \ |
_FP_UNPACK_RAW_1(S,X,val); \ |
_FP_UNPACK_CANONICAL(S,1,X); \ |
} while (0) |
#define FP_UNPACK_SP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_1_P(S,X,val); \ |
_FP_UNPACK_CANONICAL(S,1,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_S(X,val) \ |
do { \ |
_FP_UNPACK_RAW_1(S,X,val); \ |
_FP_UNPACK_SEMIRAW(S,1,X); \ |
} while (0) |
#define FP_UNPACK_SEMIRAW_SP(X,val) \ |
do { \ |
_FP_UNPACK_RAW_1_P(S,X,val); \ |
_FP_UNPACK_SEMIRAW(S,1,X); \ |
} while (0) |
#define FP_PACK_S(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(S,1,X); \ |
_FP_PACK_RAW_1(S,val,X); \ |
} while (0) |
#define FP_PACK_SP(val,X) \ |
do { \ |
_FP_PACK_CANONICAL(S,1,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_1_P(S,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_S(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(S,1,X); \ |
_FP_PACK_RAW_1(S,val,X); \ |
} while (0) |
#define FP_PACK_SEMIRAW_SP(val,X) \ |
do { \ |
_FP_PACK_SEMIRAW(S,1,X); \ |
if (!FP_INHIBIT_RESULTS) \ |
_FP_PACK_RAW_1_P(S,val,X); \ |
} while (0) |
#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN(S,1,X) |
#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X) |
#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y) |
#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y) |
#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y) |
#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y) |
#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X) |
#define _FP_SQRT_MEAT_S(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q) |
#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un) |
#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y) |
#define FP_CMP_UNORD_S(r,X,Y) _FP_CMP_UNORD(S,1,r,X,Y) |
#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg) |
#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt) |
#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1(X) |
#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1(X) |
/programs/develop/libraries/newlib/math/sinhf.c |
---|
0,0 → 1,3 |
#include <math.h> |
float sinhf (float x) |
{return (float) sinh (x);} |
/programs/develop/libraries/newlib/math/sinhl.c |
---|
0,0 → 1,172 |
/* sinhl.c |
* |
* Hyperbolic sine, long double precision |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, sinhl(); |
* |
* y = sinhl( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns hyperbolic sine of argument in the range MINLOGL to |
* MAXLOGL. |
* |
* The range is partitioned into two segments. If |x| <= 1, a |
* rational function of the form x + x**3 P(x)/Q(x) is employed. |
* Otherwise the calculation is sinh(x) = ( exp(x) - exp(-x) )/2. |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE -2,2 10000 1.5e-19 3.9e-20 |
* IEEE +-10000 30000 1.1e-19 2.8e-20 |
* |
*/ |
/* |
Cephes Math Library Release 2.7: January, 1998 |
Copyright 1984, 1991, 1998 by Stephen L. Moshier |
*/ |
/* |
Modified for mingw |
2002-07-22 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
#endif |
#ifndef _SET_ERRNO |
#define _SET_ERRNO(x) |
#endif |
#ifdef UNK |
static long double P[] = { |
1.7550769032975377032681E-6L, |
4.1680702175874268714539E-4L, |
3.0993532520425419002409E-2L, |
9.9999999999999999998002E-1L, |
}; |
static long double Q[] = { |
1.7453965448620151484660E-8L, |
-5.9116673682651952419571E-6L, |
1.0599252315677389339530E-3L, |
-1.1403880487744749056675E-1L, |
6.0000000000000000000200E0L, |
}; |
#endif |
#ifdef IBMPC |
static const unsigned short P[] = { |
0xec6a,0xd942,0xfbb3,0xeb8f,0x3feb, XPD |
0x365e,0xb30a,0xe437,0xda86,0x3ff3, XPD |
0x8890,0x01f6,0x2612,0xfde6,0x3ff9, XPD |
0x0000,0x0000,0x0000,0x8000,0x3fff, XPD |
}; |
static const unsigned short Q[] = { |
0x4edd,0x4c21,0xad09,0x95ed,0x3fe5, XPD |
0x4376,0x9b70,0xd605,0xc65c,0xbfed, XPD |
0xc8ad,0x5d21,0x3069,0x8aed,0x3ff5, XPD |
0x9c32,0x6374,0x2d4b,0xe98d,0xbffb, XPD |
0x0000,0x0000,0x0000,0xc000,0x4001, XPD |
}; |
#endif |
#ifdef MIEEE |
static long P[] = { |
0x3feb0000,0xeb8ffbb3,0xd942ec6a, |
0x3ff30000,0xda86e437,0xb30a365e, |
0x3ff90000,0xfde62612,0x01f68890, |
0x3fff0000,0x80000000,0x00000000, |
}; |
static long Q[] = { |
0x3fe50000,0x95edad09,0x4c214edd, |
0xbfed0000,0xc65cd605,0x9b704376, |
0x3ff50000,0x8aed3069,0x5d21c8ad, |
0xbffb0000,0xe98d2d4b,0x63749c32, |
0x40010000,0xc0000000,0x00000000, |
}; |
#endif |
#ifndef __MINGW32__ |
extern long double MAXNUML, MAXLOGL, MINLOGL, LOGE2L; |
#ifdef ANSIPROT |
extern long double fabsl ( long double ); |
extern long double expl ( long double ); |
extern long double polevll ( long double, void *, int ); |
extern long double p1evll ( long double, void *, int ); |
#else |
long double fabsl(), expl(), polevll(), p1evll(); |
#endif |
#ifdef INFINITIES |
extern long double INFINITYL; |
#endif |
#ifdef NANS |
extern long double NANL; |
#endif |
#endif /* __MINGW32__ */ |
long double sinhl(x) |
long double x; |
{ |
long double a; |
#ifdef MINUSZERO |
if( x == 0.0 ) |
return(x); |
#endif |
#ifdef NANS |
if (isnanl(x)) |
{ |
_SET_ERRNO(EDOM); |
} |
#endif |
a = fabsl(x); |
if( (x > (MAXLOGL + LOGE2L)) || (x > -(MINLOGL-LOGE2L) ) ) |
{ |
mtherr( "sinhl", DOMAIN ); |
_SET_ERRNO(ERANGE); |
#ifdef INFINITIES |
if( x > 0.0L ) |
return( INFINITYL ); |
else |
return( -INFINITYL ); |
#else |
if( x > 0.0L ) |
return( MAXNUML ); |
else |
return( -MAXNUML ); |
#endif |
} |
if( a > 1.0L ) |
{ |
if( a >= (MAXLOGL - LOGE2L) ) |
{ |
a = expl(0.5L*a); |
a = (0.5L * a) * a; |
if( x < 0.0L ) |
a = -a; |
return(a); |
} |
a = expl(a); |
a = 0.5L*a - (0.5L/a); |
if( x < 0.0L ) |
a = -a; |
return(a); |
} |
a *= a; |
return( x + x * a * (polevll(a,P,3)/polevll(a,Q,4)) ); |
} |
/programs/develop/libraries/newlib/math/sinl.S |
---|
0,0 → 1,32 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "sinl.S" |
.text |
.align 4 |
.globl _sinl |
.def _sinl; .scl 2; .type 32; .endef |
_sinl: |
fldt 4(%esp) |
fsin |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fnstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fsin |
ret |
/programs/develop/libraries/newlib/math/soft-fp.h |
---|
0,0 → 1,199 |
/* Software floating-point emulation. |
Copyright (C) 1997,1998,1999,2000,2002,2003,2005,2006,2007 |
Free Software Foundation, Inc. |
This file is part of the GNU C Library. |
Contributed by Richard Henderson (rth@cygnus.com), |
Jakub Jelinek (jj@ultra.linux.cz), |
David S. Miller (davem@redhat.com) and |
Peter Maydell (pmaydell@chiark.greenend.org.uk). |
The GNU C Library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
In addition to the permissions in the GNU Lesser General Public |
License, the Free Software Foundation gives you unlimited |
permission to link the compiled version of this file into |
combinations with other programs, and to distribute those |
combinations without any restriction coming from the use of this |
file. (The Lesser General Public License restrictions do apply in |
other respects; for example, they cover modification of the file, |
and distribution when not linked into a combine executable.) |
The GNU C Library 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 |
Lesser General Public License for more details. |
You should have received a copy of the GNU Lesser General Public |
License along with the GNU C Library; if not, write to the Free |
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, |
MA 02110-1301, USA. */ |
#ifndef SOFT_FP_H |
#define SOFT_FP_H |
#define _FP_WORKBITS 3 |
#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3) |
#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2) |
#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1) |
#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0) |
#ifndef FP_RND_NEAREST |
# define FP_RND_NEAREST 0 |
# define FP_RND_ZERO 1 |
# define FP_RND_PINF 2 |
# define FP_RND_MINF 3 |
#endif |
#ifndef FP_ROUNDMODE |
# define FP_ROUNDMODE FP_RND_NEAREST |
#endif |
/* By default don't care about exceptions. */ |
#ifndef FP_EX_INVALID |
#define FP_EX_INVALID 0 |
#endif |
#ifndef FP_EX_OVERFLOW |
#define FP_EX_OVERFLOW 0 |
#endif |
#ifndef FP_EX_UNDERFLOW |
#define FP_EX_UNDERFLOW 0 |
#endif |
#ifndef FP_EX_DIVZERO |
#define FP_EX_DIVZERO 0 |
#endif |
#ifndef FP_EX_INEXACT |
#define FP_EX_INEXACT 0 |
#endif |
#ifndef FP_EX_DENORM |
#define FP_EX_DENORM 0 |
#endif |
#ifdef _FP_DECL_EX |
#define FP_DECL_EX \ |
int _fex = 0; \ |
_FP_DECL_EX |
#else |
#define FP_DECL_EX int _fex = 0 |
#endif |
#ifndef FP_INIT_ROUNDMODE |
#define FP_INIT_ROUNDMODE do {} while (0) |
#endif |
#ifndef FP_HANDLE_EXCEPTIONS |
#define FP_HANDLE_EXCEPTIONS do {} while (0) |
#endif |
#ifndef FP_INHIBIT_RESULTS |
/* By default we write the results always. |
* sfp-machine may override this and e.g. |
* check if some exceptions are unmasked |
* and inhibit it in such a case. |
*/ |
#define FP_INHIBIT_RESULTS 0 |
#endif |
#define FP_SET_EXCEPTION(ex) \ |
_fex |= (ex) |
#define FP_UNSET_EXCEPTION(ex) \ |
_fex &= ~(ex) |
#define FP_CLEAR_EXCEPTIONS \ |
_fex = 0 |
#define _FP_ROUND_NEAREST(wc, X) \ |
do { \ |
if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \ |
_FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \ |
} while (0) |
#define _FP_ROUND_ZERO(wc, X) (void)0 |
#define _FP_ROUND_PINF(wc, X) \ |
do { \ |
if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \ |
_FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \ |
} while (0) |
#define _FP_ROUND_MINF(wc, X) \ |
do { \ |
if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \ |
_FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \ |
} while (0) |
#define _FP_ROUND(wc, X) \ |
do { \ |
if (_FP_FRAC_LOW_##wc(X) & 7) \ |
FP_SET_EXCEPTION(FP_EX_INEXACT); \ |
switch (FP_ROUNDMODE) \ |
{ \ |
case FP_RND_NEAREST: \ |
_FP_ROUND_NEAREST(wc,X); \ |
break; \ |
case FP_RND_ZERO: \ |
_FP_ROUND_ZERO(wc,X); \ |
break; \ |
case FP_RND_PINF: \ |
_FP_ROUND_PINF(wc,X); \ |
break; \ |
case FP_RND_MINF: \ |
_FP_ROUND_MINF(wc,X); \ |
break; \ |
} \ |
} while (0) |
#define FP_CLS_NORMAL 0 |
#define FP_CLS_ZERO 1 |
#define FP_CLS_INF 2 |
#define FP_CLS_NAN 3 |
#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y)) |
#include "op-1.h" |
#include "op-2.h" |
#include "op-4.h" |
#include "op-8.h" |
#include "op-common.h" |
/* Sigh. Silly things longlong.h needs. */ |
#define UWtype _FP_W_TYPE |
#define W_TYPE_SIZE _FP_W_TYPE_SIZE |
typedef int QItype __attribute__((mode(QI))); |
typedef int SItype __attribute__((mode(SI))); |
typedef int DItype __attribute__((mode(DI))); |
typedef unsigned int UQItype __attribute__((mode(QI))); |
typedef unsigned int USItype __attribute__((mode(SI))); |
typedef unsigned int UDItype __attribute__((mode(DI))); |
#if _FP_W_TYPE_SIZE == 32 |
typedef unsigned int UHWtype __attribute__((mode(HI))); |
#elif _FP_W_TYPE_SIZE == 64 |
typedef USItype UHWtype; |
#endif |
#ifndef CMPtype |
#define CMPtype int |
#endif |
#define SI_BITS (__CHAR_BIT__ * (int)sizeof(SItype)) |
#define DI_BITS (__CHAR_BIT__ * (int)sizeof(DItype)) |
#ifndef umul_ppmm |
#ifdef _LIBC |
#include <stdlib/longlong.h> |
#else |
#include "longlong.h" |
#endif |
#endif |
#ifdef _LIBC |
#include <stdlib.h> |
#else |
extern void abort (void); |
#endif |
#endif |
/programs/develop/libraries/newlib/math/sqrtf.c |
---|
0,0 → 1,37 |
#include <math.h> |
#include <errno.h> |
extern float __QNANF; |
float |
sqrtf (float x) |
{ |
if (x < 0.0F ) |
{ |
errno = EDOM; |
return __QNANF; |
} |
else |
{ |
float res; |
asm ("fsqrt" : "=t" (res) : "0" (x)); |
return res; |
} |
} |
double |
sqrt (double x) |
{ |
if (x < 0.0F ) |
{ |
errno = EDOM; |
return __QNANF; |
} |
else |
{ |
double res; |
asm ("fsqrt" : "=t" (res) : "0" (x)); |
return res; |
} |
} |
/programs/develop/libraries/newlib/math/sqrtl.c |
---|
0,0 → 1,20 |
#include <math.h> |
#include <errno.h> |
extern long double __QNANL; |
long double |
sqrtl (long double x) |
{ |
if (x < 0.0L ) |
{ |
errno = EDOM; |
return __QNANL; |
} |
else |
{ |
long double res; |
asm ("fsqrt" : "=t" (res) : "0" (x)); |
return res; |
} |
} |
/programs/develop/libraries/newlib/math/tan.S |
---|
0,0 → 1,31 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "tan.s" |
.text |
.align 4 |
.globl _tan |
.def _tan; .scl 2; .type 32; .endef |
_tan: |
fldl 4(%esp) |
fptan |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
fstp %st(0) |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fptan |
fstp %st(0) |
ret |
/programs/develop/libraries/newlib/math/tanf.S |
---|
0,0 → 1,31 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "tanf.S" |
.text |
.align 4 |
.globl _tanf |
.def _tanf; .scl 2; .type 32; .endef |
_tanf: |
flds 4(%esp) |
fptan |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
fstp %st(0) |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fptan |
fstp %st(0) |
ret |
/programs/develop/libraries/newlib/math/tanhf.c |
---|
0,0 → 1,3 |
#include <math.h> |
float tanhf (float x) |
{return (float) tanh (x);} |
/programs/develop/libraries/newlib/math/tanhl.c |
---|
0,0 → 1,151 |
/* tanhl.c |
* |
* Hyperbolic tangent, long double precision |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, tanhl(); |
* |
* y = tanhl( x ); |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns hyperbolic tangent of argument in the range MINLOGL to |
* MAXLOGL. |
* |
* A rational function is used for |x| < 0.625. The form |
* x + x**3 P(x)/Q(x) of Cody _& Waite is employed. |
* Otherwise, |
* tanh(x) = sinh(x)/cosh(x) = 1 - 2/(exp(2x) + 1). |
* |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE -2,2 30000 1.3e-19 2.4e-20 |
* |
*/ |
/* |
Cephes Math Library Release 2.7: May, 1998 |
Copyright 1984, 1987, 1989, 1998 by Stephen L. Moshier |
*/ |
/* |
Modified for mingw |
2002-07-22 Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifdef __MINGW32__ |
#include "cephes_mconf.h" |
#else |
#include "mconf.h" |
#endif |
#ifndef _SET_ERRNO |
#define _SET_ERRNO(x) |
#endif |
#ifdef UNK |
static long double P[] = { |
-6.8473739392677100872869E-5L, |
-9.5658283111794641589011E-1L, |
-8.4053568599672284488465E1L, |
-1.3080425704712825945553E3L, |
}; |
static long double Q[] = { |
/* 1.0000000000000000000000E0L,*/ |
9.6259501838840336946872E1L, |
1.8218117903645559060232E3L, |
3.9241277114138477845780E3L, |
}; |
#endif |
#ifdef IBMPC |
static unsigned short P[] = { |
0xd2a4,0x1b0c,0x8f15,0x8f99,0xbff1, XPD |
0x5959,0x9111,0x9cc7,0xf4e2,0xbffe, XPD |
0xb576,0xef5e,0x6d57,0xa81b,0xc005, XPD |
0xe3be,0xbfbd,0x5cbc,0xa381,0xc009, XPD |
}; |
static unsigned short Q[] = { |
/*0x0000,0x0000,0x0000,0x8000,0x3fff,*/ |
0x687f,0xce24,0xdd6c,0xc084,0x4005, XPD |
0x3793,0xc95f,0xfa2f,0xe3b9,0x4009, XPD |
0xd5a2,0x1f9c,0x0b1b,0xf542,0x400a, XPD |
}; |
#endif |
#ifdef MIEEE |
static long P[] = { |
0xbff10000,0x8f998f15,0x1b0cd2a4, |
0xbffe0000,0xf4e29cc7,0x91115959, |
0xc0050000,0xa81b6d57,0xef5eb576, |
0xc0090000,0xa3815cbc,0xbfbde3be, |
}; |
static long Q[] = { |
/*0x3fff0000,0x80000000,0x00000000,*/ |
0x40050000,0xc084dd6c,0xce24687f, |
0x40090000,0xe3b9fa2f,0xc95f3793, |
0x400a0000,0xf5420b1b,0x1f9cd5a2, |
}; |
#endif |
#ifndef __MINGW32__ |
extern long double MAXLOGL; |
#ifdef ANSIPROT |
extern long double fabsl ( long double ); |
extern long double expl ( long double ); |
extern long double polevll ( long double, void *, int ); |
extern long double p1evll ( long double, void *, int ); |
#else |
long double fabsl(), expl(), polevll(), p1evll(); |
#endif |
#endif /* __MINGW32__ */ |
long double tanhl(x) |
long double x; |
{ |
long double s, z; |
#ifdef MINUSZERO |
if( x == 0.0L ) |
return(x); |
#endif |
if (isnanl(x)) |
{ |
_SET_ERRNO (EDOM); |
return x; |
} |
z = fabsl(x); |
if( z > 0.5L * MAXLOGL ) |
{ |
_SET_ERRNO (ERANGE); |
if( x > 0 ) |
return( 1.0L ); |
else |
return( -1.0L ); |
} |
if( z >= 0.625L ) |
{ |
s = expl(2.0*z); |
z = 1.0L - 2.0/(s + 1.0L); |
if( x < 0 ) |
z = -z; |
} |
else |
{ |
s = x * x; |
z = polevll( s, P, 3 )/p1evll(s, Q, 3); |
z = x * s * z; |
z = x + z; |
} |
return( z ); |
} |
/programs/develop/libraries/newlib/math/tanl.S |
---|
0,0 → 1,33 |
/* |
* Written by J.T. Conklin <jtc@netbsd.org>. |
* Public domain. |
* |
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>. |
* |
* Removed header file dependency for use in libmingwex.a by |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
.file "tanl.S" |
.text |
.align 4 |
.globl _tanl |
.def _tanl; .scl 2; .type 32; .endef |
_tanl: |
fldt 4(%esp) |
fptan |
fnstsw %ax |
testl $0x400,%eax |
jnz 1f |
fstp %st(0) |
ret |
1: fldpi |
fadd %st(0) |
fxch %st(1) |
2: fprem1 |
fstsw %ax |
testl $0x400,%eax |
jnz 2b |
fstp %st(1) |
fptan |
fstp %st(0) |
ret |
/programs/develop/libraries/newlib/math/tgamma.c |
---|
0,0 → 1,388 |
/* gamma.c |
* |
* Gamma function |
* |
* |
* |
* SYNOPSIS: |
* |
* double x, y, __tgamma_r(); |
* int* sgngam; |
* y = __tgamma_r( x, sgngam ); |
* |
* double x, y, tgamma(); |
* y = tgamma( x) |
* |
* |
* |
* DESCRIPTION: |
* |
* Returns gamma function of the argument. The result is |
* correctly signed. In the reentrant version the sign (+1 or -1) |
* is returned in the variable referenced by sgngam. |
* |
* Arguments |x| <= 34 are reduced by recurrence and the function |
* approximated by a rational function of degree 6/7 in the |
* interval (2,3). Large arguments are handled by Stirling's |
* formula. Large negative arguments are made positive using |
* a reflection formula. |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* DEC -34, 34 10000 1.3e-16 2.5e-17 |
* IEEE -170,-33 20000 2.3e-15 3.3e-16 |
* IEEE -33, 33 20000 9.4e-16 2.2e-16 |
* IEEE 33, 171.6 20000 2.3e-15 3.2e-16 |
* |
* Error for arguments outside the test range will be larger |
* owing to error amplification by the exponential function. |
* |
*/ |
/* |
Cephes Math Library Release 2.8: June, 2000 |
Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier |
*/ |
/* |
* 26-11-2002 Modified for mingw. |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifndef __MINGW32__ |
#include "mconf.h" |
#else |
#include "cephes_mconf.h" |
#endif |
#ifdef UNK |
static const double P[] = { |
1.60119522476751861407E-4, |
1.19135147006586384913E-3, |
1.04213797561761569935E-2, |
4.76367800457137231464E-2, |
2.07448227648435975150E-1, |
4.94214826801497100753E-1, |
9.99999999999999996796E-1 |
}; |
static const double Q[] = { |
-2.31581873324120129819E-5, |
5.39605580493303397842E-4, |
-4.45641913851797240494E-3, |
1.18139785222060435552E-2, |
3.58236398605498653373E-2, |
-2.34591795718243348568E-1, |
7.14304917030273074085E-2, |
1.00000000000000000320E0 |
}; |
#define MAXGAM 171.624376956302725 |
static const double LOGPI = 1.14472988584940017414; |
#endif |
#ifdef DEC |
static const unsigned short P[] = { |
0035047,0162701,0146301,0005234, |
0035634,0023437,0032065,0176530, |
0036452,0137157,0047330,0122574, |
0037103,0017310,0143041,0017232, |
0037524,0066516,0162563,0164605, |
0037775,0004671,0146237,0014222, |
0040200,0000000,0000000,0000000 |
}; |
static const unsigned short Q[] = { |
0134302,0041724,0020006,0116565, |
0035415,0072121,0044251,0025634, |
0136222,0003447,0035205,0121114, |
0036501,0107552,0154335,0104271, |
0037022,0135717,0014776,0171471, |
0137560,0034324,0165024,0037021, |
0037222,0045046,0047151,0161213, |
0040200,0000000,0000000,0000000 |
}; |
#define MAXGAM 34.84425627277176174 |
#endif |
#ifdef IBMPC |
static const unsigned short P[] = { |
0x2153,0x3998,0xfcb8,0x3f24, |
0xbfab,0xe686,0x84e3,0x3f53, |
0x14b0,0xe9db,0x57cd,0x3f85, |
0x23d3,0x18c4,0x63d9,0x3fa8, |
0x7d31,0xdcae,0x8da9,0x3fca, |
0xe312,0x3993,0xa137,0x3fdf, |
0x0000,0x0000,0x0000,0x3ff0 |
}; |
static const unsigned short Q[] = { |
0xd3af,0x8400,0x487a,0xbef8, |
0x2573,0x2915,0xae8a,0x3f41, |
0xb44a,0xe750,0x40e4,0xbf72, |
0xb117,0x5b1b,0x31ed,0x3f88, |
0xde67,0xe33f,0x5779,0x3fa2, |
0x87c2,0x9d42,0x071a,0xbfce, |
0x3c51,0xc9cd,0x4944,0x3fb2, |
0x0000,0x0000,0x0000,0x3ff0 |
}; |
#define MAXGAM 171.624376956302725 |
#endif |
#ifdef MIEEE |
static const unsigned short P[] = { |
0x3f24,0xfcb8,0x3998,0x2153, |
0x3f53,0x84e3,0xe686,0xbfab, |
0x3f85,0x57cd,0xe9db,0x14b0, |
0x3fa8,0x63d9,0x18c4,0x23d3, |
0x3fca,0x8da9,0xdcae,0x7d31, |
0x3fdf,0xa137,0x3993,0xe312, |
0x3ff0,0x0000,0x0000,0x0000 |
}; |
static const unsigned short Q[] = { |
0xbef8,0x487a,0x8400,0xd3af, |
0x3f41,0xae8a,0x2915,0x2573, |
0xbf72,0x40e4,0xe750,0xb44a, |
0x3f88,0x31ed,0x5b1b,0xb117, |
0x3fa2,0x5779,0xe33f,0xde67, |
0xbfce,0x071a,0x9d42,0x87c2, |
0x3fb2,0x4944,0xc9cd,0x3c51, |
0x3ff0,0x0000,0x0000,0x0000 |
}; |
#define MAXGAM 171.624376956302725 |
#endif |
/* Stirling's formula for the gamma function */ |
#if UNK |
static const double STIR[5] = { |
7.87311395793093628397E-4, |
-2.29549961613378126380E-4, |
-2.68132617805781232825E-3, |
3.47222221605458667310E-3, |
8.33333333333482257126E-2, |
}; |
#define MAXSTIR 143.01608 |
static const double SQTPI = 2.50662827463100050242E0; |
#endif |
#if DEC |
static const unsigned short STIR[20] = { |
0035516,0061622,0144553,0112224, |
0135160,0131531,0037460,0165740, |
0136057,0134460,0037242,0077270, |
0036143,0107070,0156306,0027751, |
0037252,0125252,0125252,0146064, |
}; |
#define MAXSTIR 26.77 |
static const unsigned short SQT[4] = { |
0040440,0066230,0177661,0034055, |
}; |
#define SQTPI *(double *)SQT |
#endif |
#if IBMPC |
static const unsigned short STIR[20] = { |
0x7293,0x592d,0xcc72,0x3f49, |
0x1d7c,0x27e6,0x166b,0xbf2e, |
0x4fd7,0x07d4,0xf726,0xbf65, |
0xc5fd,0x1b98,0x71c7,0x3f6c, |
0x5986,0x5555,0x5555,0x3fb5, |
}; |
#define MAXSTIR 143.01608 |
static const union |
{ |
unsigned short s[4]; |
double d; |
} sqt = {{0x2706,0x1ff6,0x0d93,0x4004}}; |
#define SQTPI (sqt.d) |
#endif |
#if MIEEE |
static const unsigned short STIR[20] = { |
0x3f49,0xcc72,0x592d,0x7293, |
0xbf2e,0x166b,0x27e6,0x1d7c, |
0xbf65,0xf726,0x07d4,0x4fd7, |
0x3f6c,0x71c7,0x1b98,0xc5fd, |
0x3fb5,0x5555,0x5555,0x5986, |
}; |
#define MAXSTIR 143.01608 |
static const unsigned short SQT[4] = { |
0x4004,0x0d93,0x1ff6,0x2706, |
}; |
#define SQTPI *(double *)SQT |
#endif |
#ifndef __MINGW32__ |
int sgngam = 0; |
extern int sgngam; |
extern double MAXLOG, MAXNUM, PI; |
#ifdef ANSIPROT |
extern double pow ( double, double ); |
extern double log ( double ); |
extern double exp ( double ); |
extern double sin ( double ); |
extern double polevl ( double, void *, int ); |
extern double p1evl ( double, void *, int ); |
extern double floor ( double ); |
extern double fabs ( double ); |
extern int isnan ( double ); |
extern int isfinite ( double ); |
static double stirf ( double ); |
double lgam ( double ); |
#else |
double pow(), log(), exp(), sin(), polevl(), p1evl(), floor(), fabs(); |
int isnan(), isfinite(); |
static double stirf(); |
double lgam(); |
#endif |
#ifdef INFINITIES |
extern double INFINITY; |
#endif |
#ifdef NANS |
extern double NAN; |
#endif |
#else /* __MINGW32__ */ |
static double stirf ( double ); |
#endif |
/* Gamma function computed by Stirling's formula. |
* The polynomial STIR is valid for 33 <= x <= 172. |
*/ |
static double stirf(x) |
double x; |
{ |
double y, w, v; |
w = 1.0/x; |
w = 1.0 + w * polevl( w, STIR, 4 ); |
y = exp(x); |
if( x > MAXSTIR ) |
{ /* Avoid overflow in pow() */ |
v = pow( x, 0.5 * x - 0.25 ); |
y = v * (v / y); |
} |
else |
{ |
y = pow( x, x - 0.5 ) / y; |
} |
y = SQTPI * y * w; |
return( y ); |
} |
double __tgamma_r(double x, int* sgngam) |
{ |
double p, q, z; |
int i; |
*sgngam = 1; |
#ifdef NANS |
if( isnan(x) ) |
return(x); |
#endif |
#ifdef INFINITIES |
#ifdef NANS |
if( x == INFINITY ) |
return(x); |
if( x == -INFINITY ) |
return(NAN); |
#else |
if( !isfinite(x) ) |
return(x); |
#endif |
#endif |
q = fabs(x); |
if( q > 33.0 ) |
{ |
if( x < 0.0 ) |
{ |
p = floor(q); |
if( p == q ) |
{ |
gsing: |
_SET_ERRNO(EDOM); |
mtherr( "tgamma", SING ); |
#ifdef INFINITIES |
return (INFINITY); |
#else |
return (MAXNUM); |
#endif |
} |
i = p; |
if( (i & 1) == 0 ) |
*sgngam = -1; |
z = q - p; |
if( z > 0.5 ) |
{ |
p += 1.0; |
z = q - p; |
} |
z = q * sin( PI * z ); |
if( z == 0.0 ) |
{ |
_SET_ERRNO(ERANGE); |
mtherr( "tgamma", OVERFLOW ); |
#ifdef INFINITIES |
return( *sgngam * INFINITY); |
#else |
return( *sgngam * MAXNUM); |
#endif |
} |
z = fabs(z); |
z = PI/(z * stirf(q) ); |
} |
else |
{ |
z = stirf(x); |
} |
return( *sgngam * z ); |
} |
z = 1.0; |
while( x >= 3.0 ) |
{ |
x -= 1.0; |
z *= x; |
} |
while( x < 0.0 ) |
{ |
if( x > -1.E-9 ) |
goto Small; |
z /= x; |
x += 1.0; |
} |
while( x < 2.0 ) |
{ |
if( x < 1.e-9 ) |
goto Small; |
z /= x; |
x += 1.0; |
} |
if( x == 2.0 ) |
return(z); |
x -= 2.0; |
p = polevl( x, P, 6 ); |
q = polevl( x, Q, 7 ); |
return( z * p / q ); |
Small: |
if( x == 0.0 ) |
{ |
goto gsing; |
} |
else |
return( z/((1.0 + 0.5772156649015329 * x) * x) ); |
} |
/* This is the C99 version */ |
double tgamma(double x) |
{ |
int local_sgngam=0; |
return (__tgamma_r(x, &local_sgngam)); |
} |
/programs/develop/libraries/newlib/math/tgammaf.c |
---|
0,0 → 1,265 |
/* gammaf.c |
* |
* Gamma function |
* |
* |
* |
* SYNOPSIS: |
* |
* float x, y, __tgammaf_r(); |
* int* sgngamf; |
* y = __tgammaf_r( x, sgngamf ); |
* |
* float x, y, tgammaf(); |
* y = tgammaf( x); |
* |
* |
* DESCRIPTION: |
* |
* Returns gamma function of the argument. The result is |
* correctly signed. In the reentrant version the sign (+1 or -1) |
* is returned in the variable referenced by sgngamf. |
* |
* Arguments between 0 and 10 are reduced by recurrence and the |
* function is approximated by a polynomial function covering |
* the interval (2,3). Large arguments are handled by Stirling's |
* formula. Negative arguments are made positive using |
* a reflection formula. |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE 0,-33 100,000 5.7e-7 1.0e-7 |
* IEEE -33,0 100,000 6.1e-7 1.2e-7 |
* |
* |
*/ |
/* |
Cephes Math Library Release 2.7: July, 1998 |
Copyright 1984, 1987, 1989, 1992, 1998 by Stephen L. Moshier |
*/ |
/* |
* 26-11-2002 Modified for mingw. |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifndef __MINGW32__ |
#include "mconf.h" |
#else |
#include "cephes_mconf.h" |
#endif |
/* define MAXGAM 34.84425627277176174 */ |
/* Stirling's formula for the gamma function |
* gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) ( 1 + 1/x P(1/x) ) |
* .028 < 1/x < .1 |
* relative error < 1.9e-11 |
*/ |
static const float STIR[] = { |
-2.705194986674176E-003, |
3.473255786154910E-003, |
8.333331788340907E-002, |
}; |
static const float MAXSTIR = 26.77; |
static const float SQTPIF = 2.50662827463100050242; /* sqrt( 2 pi ) */ |
#ifndef __MINGW32__ |
extern float MAXLOGF, MAXNUMF, PIF; |
#ifdef ANSIC |
float expf(float); |
float logf(float); |
float powf( float, float ); |
float sinf(float); |
float gammaf(float); |
float floorf(float); |
static float stirf(float); |
float polevlf( float, float *, int ); |
float p1evlf( float, float *, int ); |
#else |
float expf(), logf(), powf(), sinf(), floorf(); |
float polevlf(), p1evlf(); |
static float stirf(); |
#endif |
#else /* __MINGW32__ */ |
static float stirf(float); |
#endif |
/* Gamma function computed by Stirling's formula, |
* sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x)) |
* The polynomial STIR is valid for 33 <= x <= 172. |
*/ |
static float stirf( float x ) |
{ |
float y, w, v; |
w = 1.0/x; |
w = 1.0 + w * polevlf( w, STIR, 2 ); |
y = expf( -x ); |
if( x > MAXSTIR ) |
{ /* Avoid overflow in pow() */ |
v = powf( x, 0.5 * x - 0.25 ); |
y *= v; |
y *= v; |
} |
else |
{ |
y = powf( x, x - 0.5 ) * y; |
} |
y = SQTPIF * y * w; |
return( y ); |
} |
/* gamma(x+2), 0 < x < 1 */ |
static const float P[] = { |
1.536830450601906E-003, |
5.397581592950993E-003, |
4.130370201859976E-003, |
7.232307985516519E-002, |
8.203960091619193E-002, |
4.117857447645796E-001, |
4.227867745131584E-001, |
9.999999822945073E-001, |
}; |
float __tgammaf_r( float x, int* sgngamf) |
{ |
float p, q, z, nz; |
int i, direction, negative; |
#ifdef NANS |
if( isnan(x) ) |
return(x); |
#endif |
#ifdef INFINITIES |
#ifdef NANS |
if( x == INFINITYF ) |
return(x); |
if( x == -INFINITYF ) |
return(NANF); |
#else |
if( !isfinite(x) ) |
return(x); |
#endif |
#endif |
*sgngamf = 1; |
negative = 0; |
nz = 0.0; |
if( x < 0.0 ) |
{ |
negative = 1; |
q = -x; |
p = floorf(q); |
if( p == q ) |
{ |
gsing: |
_SET_ERRNO(EDOM); |
mtherr( "tgammaf", SING ); |
#ifdef INFINITIES |
return (INFINITYF); |
#else |
return (MAXNUMF); |
#endif |
} |
i = p; |
if( (i & 1) == 0 ) |
*sgngamf = -1; |
nz = q - p; |
if( nz > 0.5 ) |
{ |
p += 1.0; |
nz = q - p; |
} |
nz = q * sinf( PIF * nz ); |
if( nz == 0.0 ) |
{ |
_SET_ERRNO(ERANGE); |
mtherr( "tgamma", OVERFLOW ); |
#ifdef INFINITIES |
return( *sgngamf * INFINITYF); |
#else |
return( *sgngamf * MAXNUMF); |
#endif |
} |
if( nz < 0 ) |
nz = -nz; |
x = q; |
} |
if( x >= 10.0 ) |
{ |
z = stirf(x); |
} |
if( x < 2.0 ) |
direction = 1; |
else |
direction = 0; |
z = 1.0; |
while( x >= 3.0 ) |
{ |
x -= 1.0; |
z *= x; |
} |
/* |
while( x < 0.0 ) |
{ |
if( x > -1.E-4 ) |
goto Small; |
z *=x; |
x += 1.0; |
} |
*/ |
while( x < 2.0 ) |
{ |
if( x < 1.e-4 ) |
goto Small; |
z *=x; |
x += 1.0; |
} |
if( direction ) |
z = 1.0/z; |
if( x == 2.0 ) |
return(z); |
x -= 2.0; |
p = z * polevlf( x, P, 7 ); |
gdone: |
if( negative ) |
{ |
p = *sgngamf * PIF/(nz * p ); |
} |
return(p); |
Small: |
if( x == 0.0 ) |
{ |
goto gsing; |
} |
else |
{ |
p = z / ((1.0 + 0.5772156649015329 * x) * x); |
goto gdone; |
} |
} |
/* This is the C99 version */ |
float tgammaf(float x) |
{ |
int local_sgngamf=0; |
return (__tgammaf_r(x, &local_sgngamf)); |
} |
/programs/develop/libraries/newlib/math/tgammal.c |
---|
0,0 → 1,501 |
/* gammal.c |
* |
* Gamma function |
* |
* |
* |
* SYNOPSIS: |
* |
* long double x, y, __tgammal_r(); |
* int* sgngaml; |
* y = __tgammal_r( x, sgngaml ); |
* |
* long double x, y, tgammal(); |
* y = tgammal( x); * |
* |
* |
* DESCRIPTION: |
* |
* Returns gamma function of the argument. The result is |
* correctly signed. In the reentrant version the sign (+1 or -1) |
* is returned in the variable referenced by sgngamf. |
* |
* Arguments |x| <= 13 are reduced by recurrence and the function |
* approximated by a rational function of degree 7/8 in the |
* interval (2,3). Large arguments are handled by Stirling's |
* formula. Large negative arguments are made positive using |
* a reflection formula. |
* |
* |
* ACCURACY: |
* |
* Relative error: |
* arithmetic domain # trials peak rms |
* IEEE -40,+40 10000 3.6e-19 7.9e-20 |
* IEEE -1755,+1755 10000 4.8e-18 6.5e-19 |
* |
* Accuracy for large arguments is dominated by error in powl(). |
* |
*/ |
/* |
Copyright 1994 by Stephen L. Moshier |
*/ |
/* |
* 26-11-2002 Modified for mingw. |
* Danny Smith <dannysmith@users.sourceforge.net> |
*/ |
#ifndef __MINGW32__ |
#include "mconf.h" |
#else |
#include "cephes_mconf.h" |
#endif |
/* |
gamma(x+2) = gamma(x+2) P(x)/Q(x) |
0 <= x <= 1 |
Relative error |
n=7, d=8 |
Peak error = 1.83e-20 |
Relative error spread = 8.4e-23 |
*/ |
#if UNK |
static const long double P[8] = { |
4.212760487471622013093E-5L, |
4.542931960608009155600E-4L, |
4.092666828394035500949E-3L, |
2.385363243461108252554E-2L, |
1.113062816019361559013E-1L, |
3.629515436640239168939E-1L, |
8.378004301573126728826E-1L, |
1.000000000000000000009E0L, |
}; |
static const long double Q[9] = { |
-1.397148517476170440917E-5L, |
2.346584059160635244282E-4L, |
-1.237799246653152231188E-3L, |
-7.955933682494738320586E-4L, |
2.773706565840072979165E-2L, |
-4.633887671244534213831E-2L, |
-2.243510905670329164562E-1L, |
4.150160950588455434583E-1L, |
9.999999999999999999908E-1L, |
}; |
#endif |
#if IBMPC |
static const unsigned short P[] = { |
0x434a,0x3f22,0x2bda,0xb0b2,0x3ff0, XPD |
0xf5aa,0xe82f,0x335b,0xee2e,0x3ff3, XPD |
0xbe6c,0x3757,0xc717,0x861b,0x3ff7, XPD |
0x7f43,0x5196,0xb166,0xc368,0x3ff9, XPD |
0x9549,0x8eb5,0x8c3a,0xe3f4,0x3ffb, XPD |
0x8d75,0x23af,0xc8e4,0xb9d4,0x3ffd, XPD |
0x29cf,0x19b3,0x16c8,0xd67a,0x3ffe, XPD |
0x0000,0x0000,0x0000,0x8000,0x3fff, XPD |
}; |
static const unsigned short Q[] = { |
0x5473,0x2de8,0x1268,0xea67,0xbfee, XPD |
0x334b,0xc2f0,0xa2dd,0xf60e,0x3ff2, XPD |
0xbeed,0x1853,0xa691,0xa23d,0xbff5, XPD |
0x296e,0x7cb1,0x5dfd,0xd08f,0xbff4, XPD |
0x0417,0x7989,0xd7bc,0xe338,0x3ff9, XPD |
0x3295,0x3698,0xd580,0xbdcd,0xbffa, XPD |
0x75ef,0x3ab7,0x4ad3,0xe5bc,0xbffc, XPD |
0xe458,0x2ec7,0xfd57,0xd47c,0x3ffd, XPD |
0x0000,0x0000,0x0000,0x8000,0x3fff, XPD |
}; |
#endif |
#if MIEEE |
static const long P[24] = { |
0x3ff00000,0xb0b22bda,0x3f22434a, |
0x3ff30000,0xee2e335b,0xe82ff5aa, |
0x3ff70000,0x861bc717,0x3757be6c, |
0x3ff90000,0xc368b166,0x51967f43, |
0x3ffb0000,0xe3f48c3a,0x8eb59549, |
0x3ffd0000,0xb9d4c8e4,0x23af8d75, |
0x3ffe0000,0xd67a16c8,0x19b329cf, |
0x3fff0000,0x80000000,0x00000000, |
}; |
static const long Q[27] = { |
0xbfee0000,0xea671268,0x2de85473, |
0x3ff20000,0xf60ea2dd,0xc2f0334b, |
0xbff50000,0xa23da691,0x1853beed, |
0xbff40000,0xd08f5dfd,0x7cb1296e, |
0x3ff90000,0xe338d7bc,0x79890417, |
0xbffa0000,0xbdcdd580,0x36983295, |
0xbffc0000,0xe5bc4ad3,0x3ab775ef, |
0x3ffd0000,0xd47cfd57,0x2ec7e458, |
0x3fff0000,0x80000000,0x00000000, |
}; |
#endif |
/* |
static const long double P[] = { |
-3.01525602666895735709e0L, |
-3.25157411956062339893e1L, |
-2.92929976820724030353e2L, |
-1.70730828800510297666e3L, |
-7.96667499622741999770e3L, |
-2.59780216007146401957e4L, |
-5.99650230220855581642e4L, |
-7.15743521530849602425e4L |
}; |
static const long double Q[] = { |
1.00000000000000000000e0L, |
-1.67955233807178858919e1L, |
8.85946791747759881659e1L, |
5.69440799097468430177e1L, |
-1.98526250512761318471e3L, |
3.31667508019495079814e3L, |
1.60577839621734713377e4L, |
-2.97045081369399940529e4L, |
-7.15743521530849602412e4L |
}; |
*/ |
#define MAXGAML 1755.455L |
/*static const long double LOGPI = 1.14472988584940017414L;*/ |
/* Stirling's formula for the gamma function |
gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x)) |
z(x) = x |
13 <= x <= 1024 |
Relative error |
n=8, d=0 |
Peak error = 9.44e-21 |
Relative error spread = 8.8e-4 |
*/ |
#if UNK |
static const long double STIR[9] = { |
7.147391378143610789273E-4L, |
-2.363848809501759061727E-5L, |
-5.950237554056330156018E-4L, |
6.989332260623193171870E-5L, |
7.840334842744753003862E-4L, |
-2.294719747873185405699E-4L, |
-2.681327161876304418288E-3L, |
3.472222222230075327854E-3L, |
8.333333333333331800504E-2L, |
}; |
#endif |
#if IBMPC |
static const unsigned short STIR[] = { |
0x6ede,0x69f7,0x54e3,0xbb5d,0x3ff4, XPD |
0xc395,0x0295,0x4443,0xc64b,0xbfef, XPD |
0xba6f,0x7c59,0x5e47,0x9bfb,0xbff4, XPD |
0x5704,0x1a39,0xb11d,0x9293,0x3ff1, XPD |
0x30b7,0x1a21,0x98b2,0xcd87,0x3ff4, XPD |
0xbef3,0x7023,0x6a08,0xf09e,0xbff2, XPD |
0x3a1c,0x5ac8,0x3478,0xafb9,0xbff6, XPD |
0xc3c9,0x906e,0x38e3,0xe38e,0x3ff6, XPD |
0xa1d5,0xaaaa,0xaaaa,0xaaaa,0x3ffb, XPD |
}; |
#endif |
#if MIEEE |
static const long STIR[27] = { |
0x3ff40000,0xbb5d54e3,0x69f76ede, |
0xbfef0000,0xc64b4443,0x0295c395, |
0xbff40000,0x9bfb5e47,0x7c59ba6f, |
0x3ff10000,0x9293b11d,0x1a395704, |
0x3ff40000,0xcd8798b2,0x1a2130b7, |
0xbff20000,0xf09e6a08,0x7023bef3, |
0xbff60000,0xafb93478,0x5ac83a1c, |
0x3ff60000,0xe38e38e3,0x906ec3c9, |
0x3ffb0000,0xaaaaaaaa,0xaaaaa1d5, |
}; |
#endif |
#define MAXSTIR 1024.0L |
static const long double SQTPI = 2.50662827463100050242E0L; |
/* 1/gamma(x) = z P(z) |
* z(x) = 1/x |
* 0 < x < 0.03125 |
* Peak relative error 4.2e-23 |
*/ |
#if UNK |
static const long double S[9] = { |
-1.193945051381510095614E-3L, |
7.220599478036909672331E-3L, |
-9.622023360406271645744E-3L, |
-4.219773360705915470089E-2L, |
1.665386113720805206758E-1L, |
-4.200263503403344054473E-2L, |
-6.558780715202540684668E-1L, |
5.772156649015328608253E-1L, |
1.000000000000000000000E0L, |
}; |
#endif |
#if IBMPC |
static const unsigned short S[] = { |
0xbaeb,0xd6d3,0x25e5,0x9c7e,0xbff5, XPD |
0xfe9a,0xceb4,0xc74e,0xec9a,0x3ff7, XPD |
0x9225,0xdfef,0xb0e9,0x9da5,0xbff8, XPD |
0x10b0,0xec17,0x87dc,0xacd7,0xbffa, XPD |
0x6b8d,0x7515,0x1905,0xaa89,0x3ffc, XPD |
0xf183,0x126b,0xf47d,0xac0a,0xbffa, XPD |
0x7bf6,0x57d1,0xa013,0xa7e7,0xbffe, XPD |
0xc7a9,0x7db0,0x67e3,0x93c4,0x3ffe, XPD |
0x0000,0x0000,0x0000,0x8000,0x3fff, XPD |
}; |
#endif |
#if MIEEE |
static const long S[27] = { |
0xbff50000,0x9c7e25e5,0xd6d3baeb, |
0x3ff70000,0xec9ac74e,0xceb4fe9a, |
0xbff80000,0x9da5b0e9,0xdfef9225, |
0xbffa0000,0xacd787dc,0xec1710b0, |
0x3ffc0000,0xaa891905,0x75156b8d, |
0xbffa0000,0xac0af47d,0x126bf183, |
0xbffe0000,0xa7e7a013,0x57d17bf6, |
0x3ffe0000,0x93c467e3,0x7db0c7a9, |
0x3fff0000,0x80000000,0x00000000, |
}; |
#endif |
/* 1/gamma(-x) = z P(z) |
* z(x) = 1/x |
* 0 < x < 0.03125 |
* Peak relative error 5.16e-23 |
* Relative error spread = 2.5e-24 |
*/ |
#if UNK |
static const long double SN[9] = { |
1.133374167243894382010E-3L, |
7.220837261893170325704E-3L, |
9.621911155035976733706E-3L, |
-4.219773343731191721664E-2L, |
-1.665386113944413519335E-1L, |
-4.200263503402112910504E-2L, |
6.558780715202536547116E-1L, |
5.772156649015328608727E-1L, |
-1.000000000000000000000E0L, |
}; |
#endif |
#if IBMPC |
static const unsigned short SN[] = { |
0x5dd1,0x02de,0xb9f7,0x948d,0x3ff5, XPD |
0x989b,0xdd68,0xc5f1,0xec9c,0x3ff7, XPD |
0x2ca1,0x18f0,0x386f,0x9da5,0x3ff8, XPD |
0x783f,0x41dd,0x87d1,0xacd7,0xbffa, XPD |
0x7a5b,0xd76d,0x1905,0xaa89,0xbffc, XPD |
0x7f64,0x1234,0xf47d,0xac0a,0xbffa, XPD |
0x5e26,0x57d1,0xa013,0xa7e7,0x3ffe, XPD |
0xc7aa,0x7db0,0x67e3,0x93c4,0x3ffe, XPD |
0x0000,0x0000,0x0000,0x8000,0xbfff, XPD |
}; |
#endif |
#if MIEEE |
static const long SN[27] = { |
0x3ff50000,0x948db9f7,0x02de5dd1, |
0x3ff70000,0xec9cc5f1,0xdd68989b, |
0x3ff80000,0x9da5386f,0x18f02ca1, |
0xbffa0000,0xacd787d1,0x41dd783f, |
0xbffc0000,0xaa891905,0xd76d7a5b, |
0xbffa0000,0xac0af47d,0x12347f64, |
0x3ffe0000,0xa7e7a013,0x57d15e26, |
0x3ffe0000,0x93c467e3,0x7db0c7aa, |
0xbfff0000,0x80000000,0x00000000, |
}; |
#endif |
#ifndef __MINGW32__ |
extern long double MAXLOGL, MAXNUML, PIL; |
/* #define PIL 3.14159265358979323846L */ |
/* #define MAXNUML 1.189731495357231765021263853E4932L */ |
#ifdef ANSIPROT |
extern long double fabsl ( long double ); |
extern long double lgaml ( long double ); |
extern long double logl ( long double ); |
extern long double expl ( long double ); |
extern long double gammal ( long double ); |
extern long double sinl ( long double ); |
extern long double floorl ( long double ); |
extern long double powl ( long double, long double ); |
extern long double polevll ( long double, void *, int ); |
extern long double p1evll ( long double, void *, int ); |
extern int isnanl ( long double ); |
extern int isfinitel ( long double ); |
static long double stirf ( long double ); |
#else |
long double fabsl(), lgaml(), logl(), expl(), gammal(), sinl(); |
long double floorl(), powl(), polevll(), p1evll(), isnanl(), isfinitel(); |
static long double stirf(); |
#endif |
#ifdef INFINITIES |
extern long double INFINITYL; |
#endif |
#ifdef NANS |
extern long double NANL; |
#endif |
#else /* __MINGW32__ */ |
static long double stirf ( long double ); |
#endif |
/* Gamma function computed by Stirling's formula. */ |
static long double stirf(x) |
long double x; |
{ |
long double y, w, v; |
w = 1.0L/x; |
/* For large x, use rational coefficients from the analytical expansion. */ |
if( x > 1024.0L ) |
w = (((((6.97281375836585777429E-5L * w |
+ 7.84039221720066627474E-4L) * w |
- 2.29472093621399176955E-4L) * w |
- 2.68132716049382716049E-3L) * w |
+ 3.47222222222222222222E-3L) * w |
+ 8.33333333333333333333E-2L) * w |
+ 1.0L; |
else |
w = 1.0L + w * polevll( w, STIR, 8 ); |
y = expl(x); |
if( x > MAXSTIR ) |
{ /* Avoid overflow in pow() */ |
v = powl( x, 0.5L * x - 0.25L ); |
y = v * (v / y); |
} |
else |
{ |
y = powl( x, x - 0.5L ) / y; |
} |
y = SQTPI * y * w; |
return( y ); |
} |
long double __tgammal_r(long double x, int* sgngaml) |
{ |
long double p, q, z; |
int i; |
*sgngaml = 1; |
#ifdef NANS |
if( isnanl(x) ) |
return(NANL); |
#endif |
#ifdef INFINITIES |
#ifdef NANS |
if( x == INFINITYL ) |
return(x); |
if( x == -INFINITYL ) |
return(NANL); |
#else |
if( !isfinite(x) ) |
return(x); |
#endif |
#endif |
q = fabsl(x); |
if( q > 13.0L ) |
{ |
if( q > MAXGAML ) |
goto goverf; |
if( x < 0.0L ) |
{ |
p = floorl(q); |
if( p == q ) |
{ |
gsing: |
_SET_ERRNO(EDOM); |
mtherr( "tgammal", SING ); |
#ifdef INFINITIES |
return (INFINITYL); |
#else |
return( *sgngaml * MAXNUML); |
#endif |
} |
i = p; |
if( (i & 1) == 0 ) |
*sgngaml = -1; |
z = q - p; |
if( z > 0.5L ) |
{ |
p += 1.0L; |
z = q - p; |
} |
z = q * sinl( PIL * z ); |
z = fabsl(z) * stirf(q); |
if( z <= PIL/MAXNUML ) |
{ |
goverf: |
_SET_ERRNO(ERANGE); |
mtherr( "tgammal", OVERFLOW ); |
#ifdef INFINITIES |
return( *sgngaml * INFINITYL); |
#else |
return( *sgngaml * MAXNUML); |
#endif |
} |
z = PIL/z; |
} |
else |
{ |
z = stirf(x); |
} |
return( *sgngaml * z ); |
} |
z = 1.0L; |
while( x >= 3.0L ) |
{ |
x -= 1.0L; |
z *= x; |
} |
while( x < -0.03125L ) |
{ |
z /= x; |
x += 1.0L; |
} |
if( x <= 0.03125L ) |
goto Small; |
while( x < 2.0L ) |
{ |
z /= x; |
x += 1.0L; |
} |
if( x == 2.0L ) |
return(z); |
x -= 2.0L; |
p = polevll( x, P, 7 ); |
q = polevll( x, Q, 8 ); |
return( z * p / q ); |
Small: |
if( x == 0.0L ) |
{ |
goto gsing; |
} |
else |
{ |
if( x < 0.0L ) |
{ |
x = -x; |
q = z / (x * polevll( x, SN, 8 )); |
} |
else |
q = z / (x * polevll( x, S, 8 )); |
} |
return q; |
} |
/* This is the C99 version. */ |
long double tgammal(long double x) |
{ |
int local_sgngaml=0; |
return (__tgammal_r(x, &local_sgngaml)); |
} |
/programs/develop/libraries/newlib/math/trunc.c |
---|
0,0 → 1,16 |
#include <fenv.h> |
#include <math.h> |
double |
trunc (double _x){ |
double retval; |
unsigned short saved_cw; |
unsigned short tmp_cw; |
__asm__ ("fnstcw %0;" : "=m" (saved_cw)); /* save FPU control word */ |
tmp_cw = (saved_cw & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) |
| FE_TOWARDZERO; |
__asm__ ("fldcw %0;" : : "m" (tmp_cw)); |
__asm__ ("frndint;" : "=t" (retval) : "0" (_x)); /* round towards zero */ |
__asm__ ("fldcw %0;" : : "m" (saved_cw) ); /* restore saved control word */ |
return retval; |
} |
/programs/develop/libraries/newlib/math/truncf.c |
---|
0,0 → 1,17 |
#include <fenv.h> |
#include <math.h> |
float |
truncf (float _x) |
{ |
float retval; |
unsigned short saved_cw; |
unsigned short tmp_cw; |
__asm__ ("fnstcw %0;" : "=m" (saved_cw)); /* save FPU control word */ |
tmp_cw = (saved_cw & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) |
| FE_TOWARDZERO; |
__asm__ ("fldcw %0;" : : "m" (tmp_cw)); |
__asm__ ("frndint;" : "=t" (retval) : "0" (_x)); /* round towards zero */ |
__asm__ ("fldcw %0;" : : "m" (saved_cw) ); /* restore saved control word */ |
return retval; |
} |
/programs/develop/libraries/newlib/math/truncl.c |
---|
0,0 → 1,16 |
#include <fenv.h> |
#include <math.h> |
long double |
truncl (long double _x){ |
long double retval; |
unsigned short saved_cw; |
unsigned short tmp_cw; |
__asm__ ("fnstcw %0;" : "=m" (saved_cw)); /* save FPU control word */ |
tmp_cw = (saved_cw & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) |
| FE_TOWARDZERO; |
__asm__ ("fldcw %0;" : : "m" (tmp_cw)); |
__asm__ ("frndint;" : "=t" (retval) : "0" (_x)); /* round towards zero */ |
__asm__ ("fldcw %0;" : : "m" (saved_cw) ); /* restore saved control word */ |
return retval; |
} |
/programs/develop/libraries/newlib/math/w_atan2.c |
---|
0,0 → 1,90 |
/* @(#)w_atan2.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* 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. |
* ==================================================== |
* |
*/ |
/* |
FUNCTION |
<<atan2>>, <<atan2f>>---arc tangent of y/x |
INDEX |
atan2 |
INDEX |
atan2f |
ANSI_SYNOPSIS |
#include <math.h> |
double atan2(double <[y]>,double <[x]>); |
float atan2f(float <[y]>,float <[x]>); |
TRAD_SYNOPSIS |
#include <math.h> |
double atan2(<[y]>,<[x]>); |
double <[y]>; |
double <[x]>; |
float atan2f(<[y]>,<[x]>); |
float <[y]>; |
float <[x]>; |
DESCRIPTION |
<<atan2>> computes the inverse tangent (arc tangent) of <[y]>/<[x]>. |
<<atan2>> produces the correct result even for angles near |
@ifnottex |
pi/2 or -pi/2 |
@end ifnottex |
@tex |
$\pi/2$ or $-\pi/2$ |
@end tex |
(that is, when <[x]> is near 0). |
<<atan2f>> is identical to <<atan2>>, save that it takes and returns |
<<float>>. |
RETURNS |
<<atan2>> and <<atan2f>> return a value in radians, in the range of |
@ifnottex |
-pi to pi. |
@end ifnottex |
@tex |
$-\pi$ to $\pi$. |
@end tex |
You can modify error handling for these functions using <<matherr>>. |
PORTABILITY |
<<atan2>> is ANSI C. <<atan2f>> is an extension. |
*/ |
/* |
* wrapper atan2(y,x) |
*/ |
#include "fdlibm.h" |
#include <errno.h> |
#ifndef _DOUBLE_IS_32BITS |
#ifdef __STDC__ |
double atan2(double y, double x) /* wrapper atan2 */ |
#else |
double atan2(y,x) /* wrapper atan2 */ |
double y,x; |
#endif |
{ |
return __ieee754_atan2(y,x); |
} |
#endif /* defined(_DOUBLE_IS_32BITS) */ |
/programs/develop/libraries/newlib/math/w_hypot.c |
---|
0,0 → 1,111 |
/* @(#)w_hypot.c 5.1 93/09/24 */ |
/* |
* ==================================================== |
* 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. |
* ==================================================== |
*/ |
/* |
FUNCTION |
<<hypot>>, <<hypotf>>---distance from origin |
INDEX |
hypot |
INDEX |
hypotf |
ANSI_SYNOPSIS |
#include <math.h> |
double hypot(double <[x]>, double <[y]>); |
float hypotf(float <[x]>, float <[y]>); |
TRAD_SYNOPSIS |
double hypot(<[x]>, <[y]>) |
double <[x]>, <[y]>; |
float hypotf(<[x]>, <[y]>) |
float <[x]>, <[y]>; |
DESCRIPTION |
<<hypot>> calculates the Euclidean distance |
@tex |
$\sqrt{x^2+y^2}$ |
@end tex |
@ifnottex |
<<sqrt(<[x]>*<[x]> + <[y]>*<[y]>)>> |
@end ifnottex |
between the origin (0,0) and a point represented by the |
Cartesian coordinates (<[x]>,<[y]>). <<hypotf>> differs only |
in the type of its arguments and result. |
RETURNS |
Normally, the distance value is returned. On overflow, |
<<hypot>> returns <<HUGE_VAL>> and sets <<errno>> to |
<<ERANGE>>. |
You can change the error treatment with <<matherr>>. |
PORTABILITY |
<<hypot>> and <<hypotf>> are not ANSI C. */ |
/* |
* wrapper hypot(x,y) |
*/ |
#define _IEEE_LIBM |
#include "fdlibm.h" |
#include <errno.h> |
#ifndef _DOUBLE_IS_32BITS |
#ifdef __STDC__ |
double hypot(double x, double y)/* wrapper hypot */ |
#else |
double hypot(x,y) /* wrapper hypot */ |
double x,y; |
#endif |
{ |
#ifdef _IEEE_LIBM |
return __ieee754_hypot(x,y); |
#else |
double z; |
struct exception exc; |
z = __ieee754_hypot(x,y); |
if(_LIB_VERSION == _IEEE_) return z; |
if((!finite(z))&&finite(x)&&finite(y)) { |
/* hypot(finite,finite) overflow */ |
#ifndef HUGE_VAL |
#define HUGE_VAL inf |
double inf = 0.0; |
SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */ |
#endif |
exc.type = OVERFLOW; |
exc.name = "hypot"; |
exc.err = 0; |
exc.arg1 = x; |
exc.arg2 = y; |
if (_LIB_VERSION == _SVID_) |
exc.retval = HUGE; |
else |
exc.retval = HUGE_VAL; |
if (_LIB_VERSION == _POSIX_) |
errno = ERANGE; |
else if (!matherr(&exc)) { |
errno = ERANGE; |
} |
if (exc.err != 0) |
errno = exc.err; |
return exc.retval; |
} else |
return z; |
#endif |
} |
#endif /* defined(_DOUBLE_IS_32BITS) */ |
/programs/develop/libraries/newlib/math |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/newlib/pe/list.h |
---|
0,0 → 1,707 |
#ifndef _LINUX_LIST_H |
#define _LINUX_LIST_H |
/* |
* Simple doubly linked list implementation. |
* |
* Some of the internal functions ("__xxx") are useful when |
* manipulating whole lists rather than single entries, as |
* sometimes we already know the next/prev entries and we can |
* generate better code by using them directly rather than |
* using the generic single-entry routines. |
*/ |
/** |
* container_of - cast a member of a structure out to the containing structure |
* @ptr: the pointer to the member. |
* @type: the type of the container struct this is embedded in. |
* @member: the name of the member within the struct. |
* |
*/ |
#define container_of(ptr, type, member) ({ \ |
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ |
(type *)( (char *)__mptr - offsetof(type,member) );}) |
#define LIST_POISON1 ((struct list_head*)0xFFFF0100) |
#define LIST_POISON2 ((struct list_head*)0xFFFF0200) |
#define prefetch(x) __builtin_prefetch(x) |
struct list_head { |
struct list_head *next, *prev; |
}; |
#define LIST_HEAD_INIT(name) { &(name), &(name) } |
#define LIST_HEAD(name) \ |
struct list_head name = LIST_HEAD_INIT(name) |
static inline void INIT_LIST_HEAD(struct list_head *list) |
{ |
list->next = list; |
list->prev = list; |
} |
/* |
* Insert a new entry between two known consecutive entries. |
* |
* This is only for internal list manipulation where we know |
* the prev/next entries already! |
*/ |
#ifndef CONFIG_DEBUG_LIST |
static inline void __list_add(struct list_head *new, |
struct list_head *prev, |
struct list_head *next) |
{ |
next->prev = new; |
new->next = next; |
new->prev = prev; |
prev->next = new; |
} |
#else |
extern void __list_add(struct list_head *new, |
struct list_head *prev, |
struct list_head *next); |
#endif |
/** |
* list_add - add a new entry |
* @new: new entry to be added |
* @head: list head to add it after |
* |
* Insert a new entry after the specified head. |
* This is good for implementing stacks. |
*/ |
static inline void list_add(struct list_head *new, struct list_head *head) |
{ |
__list_add(new, head, head->next); |
} |
/** |
* list_add_tail - add a new entry |
* @new: new entry to be added |
* @head: list head to add it before |
* |
* Insert a new entry before the specified head. |
* This is useful for implementing queues. |
*/ |
static inline void list_add_tail(struct list_head *new, struct list_head *head) |
{ |
__list_add(new, head->prev, head); |
} |
/* |
* Delete a list entry by making the prev/next entries |
* point to each other. |
* |
* This is only for internal list manipulation where we know |
* the prev/next entries already! |
*/ |
static inline void __list_del(struct list_head * prev, struct list_head * next) |
{ |
next->prev = prev; |
prev->next = next; |
} |
/** |
* list_del - deletes entry from list. |
* @entry: the element to delete from the list. |
* Note: list_empty() on entry does not return true after this, the entry is |
* in an undefined state. |
*/ |
#ifndef CONFIG_DEBUG_LIST |
static inline void list_del(struct list_head *entry) |
{ |
__list_del(entry->prev, entry->next); |
entry->next = LIST_POISON1; |
entry->prev = LIST_POISON2; |
} |
#else |
extern void list_del(struct list_head *entry); |
#endif |
/** |
* list_replace - replace old entry by new one |
* @old : the element to be replaced |
* @new : the new element to insert |
* |
* If @old was empty, it will be overwritten. |
*/ |
static inline void list_replace(struct list_head *old, |
struct list_head *new) |
{ |
new->next = old->next; |
new->next->prev = new; |
new->prev = old->prev; |
new->prev->next = new; |
} |
static inline void list_replace_init(struct list_head *old, |
struct list_head *new) |
{ |
list_replace(old, new); |
INIT_LIST_HEAD(old); |
} |
/** |
* list_del_init - deletes entry from list and reinitialize it. |
* @entry: the element to delete from the list. |
*/ |
static inline void list_del_init(struct list_head *entry) |
{ |
__list_del(entry->prev, entry->next); |
INIT_LIST_HEAD(entry); |
} |
/** |
* list_move - delete from one list and add as another's head |
* @list: the entry to move |
* @head: the head that will precede our entry |
*/ |
static inline void list_move(struct list_head *list, struct list_head *head) |
{ |
__list_del(list->prev, list->next); |
list_add(list, head); |
} |
/** |
* list_move_tail - delete from one list and add as another's tail |
* @list: the entry to move |
* @head: the head that will follow our entry |
*/ |
static inline void list_move_tail(struct list_head *list, |
struct list_head *head) |
{ |
__list_del(list->prev, list->next); |
list_add_tail(list, head); |
} |
/** |
* list_is_last - tests whether @list is the last entry in list @head |
* @list: the entry to test |
* @head: the head of the list |
*/ |
static inline int list_is_last(const struct list_head *list, |
const struct list_head *head) |
{ |
return list->next == head; |
} |
/** |
* list_empty - tests whether a list is empty |
* @head: the list to test. |
*/ |
static inline int list_empty(const struct list_head *head) |
{ |
return head->next == head; |
} |
/** |
* list_empty_careful - tests whether a list is empty and not being modified |
* @head: the list to test |
* |
* Description: |
* tests whether a list is empty _and_ checks that no other CPU might be |
* in the process of modifying either member (next or prev) |
* |
* NOTE: using list_empty_careful() without synchronization |
* can only be safe if the only activity that can happen |
* to the list entry is list_del_init(). Eg. it cannot be used |
* if another CPU could re-list_add() it. |
*/ |
static inline int list_empty_careful(const struct list_head *head) |
{ |
struct list_head *next = head->next; |
return (next == head) && (next == head->prev); |
} |
/** |
* list_is_singular - tests whether a list has just one entry. |
* @head: the list to test. |
*/ |
static inline int list_is_singular(const struct list_head *head) |
{ |
return !list_empty(head) && (head->next == head->prev); |
} |
static inline void __list_cut_position(struct list_head *list, |
struct list_head *head, struct list_head *entry) |
{ |
struct list_head *new_first = entry->next; |
list->next = head->next; |
list->next->prev = list; |
list->prev = entry; |
entry->next = list; |
head->next = new_first; |
new_first->prev = head; |
} |
/** |
* list_cut_position - cut a list into two |
* @list: a new list to add all removed entries |
* @head: a list with entries |
* @entry: an entry within head, could be the head itself |
* and if so we won't cut the list |
* |
* This helper moves the initial part of @head, up to and |
* including @entry, from @head to @list. You should |
* pass on @entry an element you know is on @head. @list |
* should be an empty list or a list you do not care about |
* losing its data. |
* |
*/ |
static inline void list_cut_position(struct list_head *list, |
struct list_head *head, struct list_head *entry) |
{ |
if (list_empty(head)) |
return; |
if (list_is_singular(head) && |
(head->next != entry && head != entry)) |
return; |
if (entry == head) |
INIT_LIST_HEAD(list); |
else |
__list_cut_position(list, head, entry); |
} |
static inline void __list_splice(const struct list_head *list, |
struct list_head *prev, |
struct list_head *next) |
{ |
struct list_head *first = list->next; |
struct list_head *last = list->prev; |
first->prev = prev; |
prev->next = first; |
last->next = next; |
next->prev = last; |
} |
/** |
* list_splice - join two lists, this is designed for stacks |
* @list: the new list to add. |
* @head: the place to add it in the first list. |
*/ |
static inline void list_splice(const struct list_head *list, |
struct list_head *head) |
{ |
if (!list_empty(list)) |
__list_splice(list, head, head->next); |
} |
/** |
* list_splice_tail - join two lists, each list being a queue |
* @list: the new list to add. |
* @head: the place to add it in the first list. |
*/ |
static inline void list_splice_tail(struct list_head *list, |
struct list_head *head) |
{ |
if (!list_empty(list)) |
__list_splice(list, head->prev, head); |
} |
/** |
* list_splice_init - join two lists and reinitialise the emptied list. |
* @list: the new list to add. |
* @head: the place to add it in the first list. |
* |
* The list at @list is reinitialised |
*/ |
static inline void list_splice_init(struct list_head *list, |
struct list_head *head) |
{ |
if (!list_empty(list)) { |
__list_splice(list, head, head->next); |
INIT_LIST_HEAD(list); |
} |
} |
/** |
* list_splice_tail_init - join two lists and reinitialise the emptied list |
* @list: the new list to add. |
* @head: the place to add it in the first list. |
* |
* Each of the lists is a queue. |
* The list at @list is reinitialised |
*/ |
static inline void list_splice_tail_init(struct list_head *list, |
struct list_head *head) |
{ |
if (!list_empty(list)) { |
__list_splice(list, head->prev, head); |
INIT_LIST_HEAD(list); |
} |
} |
/** |
* list_entry - get the struct for this entry |
* @ptr: the &struct list_head pointer. |
* @type: the type of the struct this is embedded in. |
* @member: the name of the list_struct within the struct. |
*/ |
#define list_entry(ptr, type, member) \ |
container_of(ptr, type, member) |
/** |
* list_first_entry - get the first element from a list |
* @ptr: the list head to take the element from. |
* @type: the type of the struct this is embedded in. |
* @member: the name of the list_struct within the struct. |
* |
* Note, that list is expected to be not empty. |
*/ |
#define list_first_entry(ptr, type, member) \ |
list_entry((ptr)->next, type, member) |
/** |
* list_for_each - iterate over a list |
* @pos: the &struct list_head to use as a loop cursor. |
* @head: the head for your list. |
*/ |
#define list_for_each(pos, head) \ |
for (pos = (head)->next; prefetch(pos->next), pos != (head); \ |
pos = pos->next) |
/** |
* __list_for_each - iterate over a list |
* @pos: the &struct list_head to use as a loop cursor. |
* @head: the head for your list. |
* |
* This variant differs from list_for_each() in that it's the |
* simplest possible list iteration code, no prefetching is done. |
* Use this for code that knows the list to be very short (empty |
* or 1 entry) most of the time. |
*/ |
#define __list_for_each(pos, head) \ |
for (pos = (head)->next; pos != (head); pos = pos->next) |
/** |
* list_for_each_prev - iterate over a list backwards |
* @pos: the &struct list_head to use as a loop cursor. |
* @head: the head for your list. |
*/ |
#define list_for_each_prev(pos, head) \ |
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ |
pos = pos->prev) |
/** |
* list_for_each_safe - iterate over a list safe against removal of list entry |
* @pos: the &struct list_head to use as a loop cursor. |
* @n: another &struct list_head to use as temporary storage |
* @head: the head for your list. |
*/ |
#define list_for_each_safe(pos, n, head) \ |
for (pos = (head)->next, n = pos->next; pos != (head); \ |
pos = n, n = pos->next) |
/** |
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry |
* @pos: the &struct list_head to use as a loop cursor. |
* @n: another &struct list_head to use as temporary storage |
* @head: the head for your list. |
*/ |
#define list_for_each_prev_safe(pos, n, head) \ |
for (pos = (head)->prev, n = pos->prev; \ |
prefetch(pos->prev), pos != (head); \ |
pos = n, n = pos->prev) |
/** |
* list_for_each_entry - iterate over list of given type |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
*/ |
#define list_for_each_entry(pos, head, member) \ |
for (pos = list_entry((head)->next, typeof(*pos), member); \ |
prefetch(pos->member.next), &pos->member != (head); \ |
pos = list_entry(pos->member.next, typeof(*pos), member)) |
/** |
* list_for_each_entry_reverse - iterate backwards over list of given type. |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
*/ |
#define list_for_each_entry_reverse(pos, head, member) \ |
for (pos = list_entry((head)->prev, typeof(*pos), member); \ |
prefetch(pos->member.prev), &pos->member != (head); \ |
pos = list_entry(pos->member.prev, typeof(*pos), member)) |
/** |
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() |
* @pos: the type * to use as a start point |
* @head: the head of the list |
* @member: the name of the list_struct within the struct. |
* |
* Prepares a pos entry for use as a start point in list_for_each_entry_continue(). |
*/ |
#define list_prepare_entry(pos, head, member) \ |
((pos) ? : list_entry(head, typeof(*pos), member)) |
/** |
* list_for_each_entry_continue - continue iteration over list of given type |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Continue to iterate over list of given type, continuing after |
* the current position. |
*/ |
#define list_for_each_entry_continue(pos, head, member) \ |
for (pos = list_entry(pos->member.next, typeof(*pos), member); \ |
prefetch(pos->member.next), &pos->member != (head); \ |
pos = list_entry(pos->member.next, typeof(*pos), member)) |
/** |
* list_for_each_entry_continue_reverse - iterate backwards from the given point |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Start to iterate over list of given type backwards, continuing after |
* the current position. |
*/ |
#define list_for_each_entry_continue_reverse(pos, head, member) \ |
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ |
prefetch(pos->member.prev), &pos->member != (head); \ |
pos = list_entry(pos->member.prev, typeof(*pos), member)) |
/** |
* list_for_each_entry_from - iterate over list of given type from the current point |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Iterate over list of given type, continuing from current position. |
*/ |
#define list_for_each_entry_from(pos, head, member) \ |
for (; prefetch(pos->member.next), &pos->member != (head); \ |
pos = list_entry(pos->member.next, typeof(*pos), member)) |
/** |
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
* @pos: the type * to use as a loop cursor. |
* @n: another type * to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
*/ |
#define list_for_each_entry_safe(pos, n, head, member) \ |
for (pos = list_entry((head)->next, typeof(*pos), member), \ |
n = list_entry(pos->member.next, typeof(*pos), member); \ |
&pos->member != (head); \ |
pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
/** |
* list_for_each_entry_safe_continue |
* @pos: the type * to use as a loop cursor. |
* @n: another type * to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Iterate over list of given type, continuing after current point, |
* safe against removal of list entry. |
*/ |
#define list_for_each_entry_safe_continue(pos, n, head, member) \ |
for (pos = list_entry(pos->member.next, typeof(*pos), member), \ |
n = list_entry(pos->member.next, typeof(*pos), member); \ |
&pos->member != (head); \ |
pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
/** |
* list_for_each_entry_safe_from |
* @pos: the type * to use as a loop cursor. |
* @n: another type * to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Iterate over list of given type from current point, safe against |
* removal of list entry. |
*/ |
#define list_for_each_entry_safe_from(pos, n, head, member) \ |
for (n = list_entry(pos->member.next, typeof(*pos), member); \ |
&pos->member != (head); \ |
pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
/** |
* list_for_each_entry_safe_reverse |
* @pos: the type * to use as a loop cursor. |
* @n: another type * to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Iterate backwards over list of given type, safe against removal |
* of list entry. |
*/ |
#define list_for_each_entry_safe_reverse(pos, n, head, member) \ |
for (pos = list_entry((head)->prev, typeof(*pos), member), \ |
n = list_entry(pos->member.prev, typeof(*pos), member); \ |
&pos->member != (head); \ |
pos = n, n = list_entry(n->member.prev, typeof(*n), member)) |
/* |
* Double linked lists with a single pointer list head. |
* Mostly useful for hash tables where the two pointer list head is |
* too wasteful. |
* You lose the ability to access the tail in O(1). |
*/ |
struct hlist_head { |
struct hlist_node *first; |
}; |
struct hlist_node { |
struct hlist_node *next, **pprev; |
}; |
#define HLIST_HEAD_INIT { .first = NULL } |
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } |
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) |
static inline void INIT_HLIST_NODE(struct hlist_node *h) |
{ |
h->next = NULL; |
h->pprev = NULL; |
} |
static inline int hlist_unhashed(const struct hlist_node *h) |
{ |
return !h->pprev; |
} |
static inline int hlist_empty(const struct hlist_head *h) |
{ |
return !h->first; |
} |
static inline void __hlist_del(struct hlist_node *n) |
{ |
struct hlist_node *next = n->next; |
struct hlist_node **pprev = n->pprev; |
*pprev = next; |
if (next) |
next->pprev = pprev; |
} |
static inline void hlist_del(struct hlist_node *n) |
{ |
__hlist_del(n); |
n->next = (struct hlist_node*)LIST_POISON1; |
n->pprev = (struct hlist_node**)LIST_POISON2; |
} |
static inline void hlist_del_init(struct hlist_node *n) |
{ |
if (!hlist_unhashed(n)) { |
__hlist_del(n); |
INIT_HLIST_NODE(n); |
} |
} |
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) |
{ |
struct hlist_node *first = h->first; |
n->next = first; |
if (first) |
first->pprev = &n->next; |
h->first = n; |
n->pprev = &h->first; |
} |
/* next must be != NULL */ |
static inline void hlist_add_before(struct hlist_node *n, |
struct hlist_node *next) |
{ |
n->pprev = next->pprev; |
n->next = next; |
next->pprev = &n->next; |
*(n->pprev) = n; |
} |
static inline void hlist_add_after(struct hlist_node *n, |
struct hlist_node *next) |
{ |
next->next = n->next; |
n->next = next; |
next->pprev = &n->next; |
if(next->next) |
next->next->pprev = &next->next; |
} |
/* |
* Move a list from one list head to another. Fixup the pprev |
* reference of the first entry if it exists. |
*/ |
static inline void hlist_move_list(struct hlist_head *old, |
struct hlist_head *new) |
{ |
new->first = old->first; |
if (new->first) |
new->first->pprev = &new->first; |
old->first = NULL; |
} |
#define hlist_entry(ptr, type, member) container_of(ptr,type,member) |
#define hlist_for_each(pos, head) \ |
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ |
pos = pos->next) |
#define hlist_for_each_safe(pos, n, head) \ |
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ |
pos = n) |
/** |
* hlist_for_each_entry - iterate over list of given type |
* @tpos: the type * to use as a loop cursor. |
* @pos: the &struct hlist_node to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the hlist_node within the struct. |
*/ |
#define hlist_for_each_entry(tpos, pos, head, member) \ |
for (pos = (head)->first; \ |
pos && ({ prefetch(pos->next); 1;}) && \ |
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
pos = pos->next) |
/** |
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point |
* @tpos: the type * to use as a loop cursor. |
* @pos: the &struct hlist_node to use as a loop cursor. |
* @member: the name of the hlist_node within the struct. |
*/ |
#define hlist_for_each_entry_continue(tpos, pos, member) \ |
for (pos = (pos)->next; \ |
pos && ({ prefetch(pos->next); 1;}) && \ |
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
pos = pos->next) |
/** |
* hlist_for_each_entry_from - iterate over a hlist continuing from current point |
* @tpos: the type * to use as a loop cursor. |
* @pos: the &struct hlist_node to use as a loop cursor. |
* @member: the name of the hlist_node within the struct. |
*/ |
#define hlist_for_each_entry_from(tpos, pos, member) \ |
for (; pos && ({ prefetch(pos->next); 1;}) && \ |
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
pos = pos->next) |
/** |
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
* @tpos: the type * to use as a loop cursor. |
* @pos: the &struct hlist_node to use as a loop cursor. |
* @n: another &struct hlist_node to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the hlist_node within the struct. |
*/ |
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ |
for (pos = (head)->first; \ |
pos && ({ n = pos->next; 1; }) && \ |
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
pos = n) |
#endif |
/programs/develop/libraries/newlib/pe/loader.c |
---|
0,0 → 1,652 |
#include <stdint.h> |
#include <stdio.h> |
#include <string.h> |
#include <alloca.h> |
#include <malloc.h> |
#include <setjmp.h> |
#include <envz.h> |
#include <sys/kos_io.h> |
#include "list.h" |
#include "pe.h" |
#define unlikely(x) __builtin_expect(!!(x), 0) |
//#define DBG(format,...) printf(format,##__VA_ARGS__) |
#define DBG(format,...) |
void __fastcall init_loader(void *libc_image); |
void* __fastcall create_image(void *raw); |
int __fastcall link_image(void *img_base); |
int __fastcall do_exec(uint32_t my_app, uint32_t *params); |
extern char* __appenv; |
extern int __appenv_size; |
typedef struct tag_module module_t; |
struct app_hdr |
{ |
char banner[8]; |
int version; |
int start; |
int iend; |
int memsize; |
int stacktop; |
char *cmdline; |
char *path; |
}; |
struct tag_module |
{ |
struct list_head list; |
char *img_name; |
char *img_path; |
uint32_t refcount; |
void *start; |
uint32_t end; |
void *entry; |
PIMAGE_NT_HEADERS32 img_hdr; |
PIMAGE_SECTION_HEADER img_sec; |
PIMAGE_EXPORT_DIRECTORY img_exp; |
}; |
typedef struct |
{ |
struct list_head list; |
char *path; |
int path_len; |
}dll_path_t; |
module_t* load_module(const char *name); |
LIST_HEAD(dll_list); |
LIST_HEAD(path_list); |
static module_t libc_dll; |
static char libc_name[] = "libc.dll"; |
static char libc_path[] = "/sys/lib/libc.dll"; |
static inline int IsPowerOf2(uint32_t val) |
{ |
if(val == 0) |
return 0; |
return (val & (val - 1)) == 0; |
} |
int validate_pe(void *raw, size_t raw_size, int is_exec) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
dos = (PIMAGE_DOS_HEADER)raw; |
if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) ) |
return 0; |
if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0) |
return 0; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
if( (uint32_t)nt < (uint32_t)raw) |
return 0; |
if(nt->Signature != IMAGE_NT_SIGNATURE) |
return 0; |
if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) |
return 0; |
if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) |
return 0; |
if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) |
return 0; |
if( is_exec && nt->OptionalHeader.ImageBase != 0) |
return 0; |
if(nt->OptionalHeader.SectionAlignment < 4096) |
{ |
if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) |
return 0; |
} |
else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment) |
return 0; |
if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) || |
!IsPowerOf2(nt->OptionalHeader.FileAlignment)) |
return 0; |
if(nt->FileHeader.NumberOfSections > 96) |
return 0; |
return 1; |
} |
void __fastcall init_loader(void *libc_image) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
PIMAGE_EXPORT_DIRECTORY exp; |
struct app_hdr *header; |
dll_path_t *path; |
int len; |
char *p; |
if(__appenv_size) |
{ |
char *env; |
env = envz_get(__appenv, __appenv_size, "PATH"); |
if( env ) |
{ |
while( *env ) |
{ |
p = env; |
while(*p) |
{ |
if( *p == 0x0D) |
break; |
else if( *p == 0x0A) |
break; |
else if( *p == ':') |
break; |
p++; |
}; |
len = p-env; |
if(len) |
{ |
char *p1; |
p1 = (char*)malloc(len+1); |
memcpy(p1, env, len); |
p1[len]=0; |
path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
INIT_LIST_HEAD(&path->list); |
path->path = p1; |
path->path_len = len; |
DBG("add libraries path %s\n", path->path); |
list_add_tail(&path->list, &path_list); |
}; |
if(*p == ':') |
{ |
env = p+1; |
continue; |
} |
else break; |
}; |
}; |
}; |
header = (struct app_hdr*)NULL; |
len = strrchr(header->path, '/') - header->path+1; |
p = (char*)malloc(len+1); |
memcpy(p, header->path, len); |
p[len]=0; |
path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
INIT_LIST_HEAD(&path->list); |
path->path = p; |
path->path_len = len; |
DBG("add libraries path %s\n", path->path); |
list_add_tail(&path->list, &path_list); |
#if 0 |
path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
INIT_LIST_HEAD(&path->list); |
path->path = "/sys/lib/"; |
path->path_len = 9; /* FIXME */ |
DBG("add libraries path %s\n", path->path); |
list_add_tail(&path->list, &path_list); |
#endif |
INIT_LIST_HEAD(&libc_dll.list); |
libc_dll.img_name = libc_name; |
libc_dll.img_path = libc_path; |
libc_dll.refcount = 1; |
dos = (PIMAGE_DOS_HEADER)libc_image; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, libc_image, |
nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
libc_dll.start = libc_image; |
libc_dll.end = MakePtr(uint32_t,libc_image, nt->OptionalHeader.SizeOfImage); |
libc_dll.img_hdr = nt; |
libc_dll.img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
libc_dll.img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,libc_image, |
nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
list_add_tail(&libc_dll.list, &dll_list); |
}; |
const module_t* find_module(const char *name) |
{ |
module_t* mod; |
list_for_each_entry(mod, &dll_list, list) |
{ |
if( !strncmp(name, mod->img_name, 16)) |
return mod; |
}; |
return load_module(name); |
}; |
static inline void sec_copy(void *dst, void *src, size_t len) |
{ |
__asm__ __volatile__ ( |
"shrl $2, %%ecx \n\t" |
"rep movsl" |
: |
:"c"(len),"S"(src),"D"(dst) |
:"cc"); |
__asm__ __volatile__ ( |
"" |
:::"ecx","esi","edi"); |
}; |
static inline void *user_alloc(size_t size) |
{ |
void *val; |
__asm__ __volatile__( |
"int $0x40" |
:"=eax"(val) |
:"a"(68),"b"(12),"c"(size)); |
return val; |
} |
void* __fastcall create_image(void *raw) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
PIMAGE_SECTION_HEADER img_sec; |
void *img_base; |
uint32_t sec_align; |
int i; |
dos = (PIMAGE_DOS_HEADER)raw; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
img_base = user_alloc(nt->OptionalHeader.SizeOfImage); |
if(unlikely(img_base == NULL)) |
return 0; |
sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders); |
img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32)); |
sec_align = nt->OptionalHeader.SectionAlignment; |
for(i=0; i< nt->FileHeader.NumberOfSections; i++) |
{ |
void *src_ptr; |
void *dest_ptr; |
size_t sec_size; |
if ( img_sec->SizeOfRawData && img_sec->PointerToRawData ) |
{ |
src_ptr = MakePtr(void*, raw, img_sec->PointerToRawData); |
dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress); |
sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData); |
}; |
img_sec++; |
}; |
if(nt->OptionalHeader.DataDirectory[5].Size) |
{ |
PIMAGE_BASE_RELOCATION reloc; |
uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase; |
reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base, |
nt->OptionalHeader.DataDirectory[5].VirtualAddress); |
while ( reloc->SizeOfBlock != 0 ) |
{ |
uint32_t cnt; |
uint16_t *entry; |
uint16_t reltype; |
uint32_t offs; |
cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t); |
entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) ); |
for ( i=0; i < cnt; i++ ) |
{ |
uint16_t *p16; |
uint32_t *p32; |
reltype = (*entry & 0xF000) >> 12; |
offs = (*entry & 0x0FFF) + reloc->VirtualAddress; |
switch(reltype) |
{ |
case 1: |
p16 = MakePtr(uint16_t*, img_base, offs); |
*p16+= (uint16_t)(delta>>16); |
break; |
case 2: |
p16 = MakePtr(uint16_t*, img_base, offs); |
*p16+= (uint16_t)delta; |
break; |
case 3: |
p32 = MakePtr(uint32_t*, img_base, offs); |
*p32+= delta; |
} |
entry++; |
} |
reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock); |
} |
}; |
return img_base; |
}; |
int __fastcall link_image(void *img_base) |
{ |
static jmp_buf loader_env; |
static recursion = -1; |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
int warn = 0; |
recursion++; |
if( !recursion ) |
{ |
if( unlikely(setjmp(loader_env) != 0)) |
{ |
recursion = -1; |
return 0; |
}; |
}; |
dos = (PIMAGE_DOS_HEADER)img_base; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
if(nt->OptionalHeader.DataDirectory[1].Size) |
{ |
PIMAGE_IMPORT_DESCRIPTOR imp; |
imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base, |
nt->OptionalHeader.DataDirectory[1].VirtualAddress); |
while ( imp->Name ) |
{ |
PIMAGE_DOS_HEADER expdos; |
PIMAGE_NT_HEADERS32 expnt; |
PIMAGE_EXPORT_DIRECTORY exp; |
PIMAGE_THUNK_DATA32 thunk; |
void **iat; |
char *libname; |
uint32_t *exp_functions; |
uint16_t *exp_ordinals; |
char **exp_names; |
const module_t *api; |
libname=MakePtr(char*,imp->Name, img_base); |
DBG("import from %s\n",libname); |
api = find_module(libname); |
if(unlikely(api == NULL)) |
{ |
printf("library %s not found\n", libname); |
longjmp(loader_env, 1); |
} |
iat = MakePtr(void**,imp->FirstThunk, img_base); |
if(imp->OriginalFirstThunk !=0 ) |
{ |
thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base); |
} |
else |
{ |
thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base); |
}; |
exp = api->img_exp; |
exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start); |
exp_ordinals = MakePtr(uint16_t*, exp->AddressOfNameOrdinals,api->start); |
exp_names = MakePtr(char**, exp->AddressOfNames,api->start); |
while ( thunk->u1.AddressOfData != 0 ) |
{ |
PIMAGE_IMPORT_BY_NAME imp_name; |
if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) |
{ |
// ordinal = (*func_list) & 0x7fffffff; |
// *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal); |
// if ((*ImportAddressList) == NULL) |
// { |
// DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName); |
// RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName); |
// return STATUS_ENTRYPOINT_NOT_FOUND; |
// } |
} |
else |
{ |
char *export_name; |
uint16_t ordinal; |
void *function; |
uint32_t minn; |
uint32_t maxn; |
imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME, |
thunk->u1.AddressOfData, img_base); |
*iat = NULL; |
DBG("import %s", imp_name->Name); |
if(imp_name->Hint < exp->NumberOfNames) |
{ |
export_name = MakePtr(char*,exp_names[imp_name->Hint], |
api->start); |
if(strcmp(imp_name->Name, export_name) == 0) |
{ |
ordinal = exp_ordinals[imp_name->Hint]; |
function = MakePtr(void*,exp_functions[ordinal], api->start); |
if((uint32_t)function >= (uint32_t)exp) |
{ |
printf("forward %s\n", function); |
warn=1; |
} |
else |
{ |
DBG(" \t\tat %x\n", function); |
*iat = function; |
}; |
thunk++; // Advance to next thunk |
iat++; |
continue; |
}; |
}; |
minn = 0; |
maxn = exp->NumberOfNames - 1; |
while (minn <= maxn) |
{ |
int mid; |
int res; |
mid = (minn + maxn) / 2; |
export_name = MakePtr(char*,exp_names[mid],api->start); |
res = strcmp(export_name, imp_name->Name); |
if (res == 0) |
{ |
ordinal = exp_ordinals[mid]; |
function = MakePtr(void*,exp_functions[ordinal], api->start); |
if((uint32_t)function >= (uint32_t)exp) |
{ |
printf("forward %s\n", function); |
warn=1; |
} |
else |
{ |
DBG(" \t\tat %x\n", function); |
*iat = function; |
}; |
break; |
} |
else if (minn == maxn) |
{ |
printf(" unresolved\n",imp_name->Name); |
warn=1; |
break; |
} |
else if (res > 0) |
{ |
maxn = mid - 1; |
} |
else |
{ |
minn = mid + 1; |
} |
}; |
}; |
thunk++; // Advance to next thunk |
iat++; |
} |
imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR |
}; |
}; |
recursion--; |
if ( !warn ) |
return 1; |
else |
return 0; |
} |
void* get_entry_point(void *raw) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
dos = (PIMAGE_DOS_HEADER)raw; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
return MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint); |
} |
module_t* load_module(const char *name) |
{ |
char *path; |
int len; |
len = strlen(name); |
dll_path_t *dllpath; |
list_for_each_entry(dllpath, &path_list, list) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
PIMAGE_EXPORT_DIRECTORY exp; |
module_t *module; |
void *raw_img; |
size_t raw_size; |
void *img_base; |
path = alloca(len+dllpath->path_len+1); |
memcpy(path, dllpath->path, dllpath->path_len); |
memcpy(path+dllpath->path_len, name, len); |
path[len+dllpath->path_len]=0; |
raw_img = load_file(path, &raw_size); |
if(raw_img == NULL) |
continue; |
if( validate_pe(raw_img, raw_size, 0) == 0) |
{ |
printf("invalide module %s\n", path); |
user_free(raw_img); |
continue; |
}; |
img_base = create_image(raw_img); |
user_free(raw_img); |
if( unlikely(img_base == NULL) ) |
{ |
printf("cannot create image %s\n",path); |
continue; |
}; |
module = (module_t*)malloc(sizeof(module_t)); |
if(unlikely(module == NULL)) |
{ |
printf("%s epic fail: no enough memory\n",__FUNCTION__); |
user_free(img_base); |
return 0; |
} |
INIT_LIST_HEAD(&module->list); |
module->img_name = strdup(name); |
module->img_path = strdup(path); |
module->start = img_base; |
module->entry = get_entry_point(img_base); |
module->refcount = 1; |
dos = (PIMAGE_DOS_HEADER)img_base; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
module->end = MakePtr(uint32_t,img_base, nt->OptionalHeader.SizeOfImage); |
module->img_hdr = nt; |
module->img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
module->img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
list_add_tail(&module->list, &dll_list); |
if( link_image(img_base)) |
return module; |
return NULL; |
}; |
return NULL; |
}; |
/programs/develop/libraries/newlib/pe/pe.h |
---|
0,0 → 1,188 |
typedef unsigned short WORD; |
typedef unsigned int DWORD; |
typedef unsigned int LONG; |
typedef unsigned char BYTE; |
#define IMAGE_DOS_SIGNATURE 0x5A4D |
#define IMAGE_NT_SIGNATURE 0x00004550 |
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b |
#pragma pack(push,2) |
typedef struct _IMAGE_DOS_HEADER |
{ |
WORD e_magic; |
WORD e_cblp; |
WORD e_cp; |
WORD e_crlc; |
WORD e_cparhdr; |
WORD e_minalloc; |
WORD e_maxalloc; |
WORD e_ss; |
WORD e_sp; |
WORD e_csum; |
WORD e_ip; |
WORD e_cs; |
WORD e_lfarlc; |
WORD e_ovno; |
WORD e_res[4]; |
WORD e_oemid; |
WORD e_oeminfo; |
WORD e_res2[10]; |
LONG e_lfanew; |
} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; |
#pragma pack(pop) |
#pragma pack(push,4) |
typedef struct _IMAGE_FILE_HEADER |
{ |
WORD Machine; |
WORD NumberOfSections; |
DWORD TimeDateStamp; |
DWORD PointerToSymbolTable; |
DWORD NumberOfSymbols; |
WORD SizeOfOptionalHeader; |
WORD Characteristics; |
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; |
#define IMAGE_FILE_DLL 0x2000 |
#define IMAGE_FILE_MACHINE_I386 0x014c /* Intel 386 or later processors |
and compatible processors */ |
typedef struct _IMAGE_DATA_DIRECTORY { |
DWORD VirtualAddress; |
DWORD Size; |
} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; |
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 |
typedef struct _IMAGE_OPTIONAL_HEADER { |
WORD Magic; |
BYTE MajorLinkerVersion; |
BYTE MinorLinkerVersion; |
DWORD SizeOfCode; |
DWORD SizeOfInitializedData; |
DWORD SizeOfUninitializedData; |
DWORD AddressOfEntryPoint; |
DWORD BaseOfCode; |
DWORD BaseOfData; |
DWORD ImageBase; |
DWORD SectionAlignment; |
DWORD FileAlignment; |
WORD MajorOperatingSystemVersion; |
WORD MinorOperatingSystemVersion; |
WORD MajorImageVersion; |
WORD MinorImageVersion; |
WORD MajorSubsystemVersion; |
WORD MinorSubsystemVersion; |
DWORD Win32VersionValue; |
DWORD SizeOfImage; |
DWORD SizeOfHeaders; |
DWORD CheckSum; |
WORD Subsystem; |
WORD DllCharacteristics; |
DWORD SizeOfStackReserve; |
DWORD SizeOfStackCommit; |
DWORD SizeOfHeapReserve; |
DWORD SizeOfHeapCommit; |
DWORD LoaderFlags; |
DWORD NumberOfRvaAndSizes; |
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; |
} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; |
#pragma pack(pop) |
#pragma pack(push,4) |
typedef struct _IMAGE_NT_HEADERS |
{ |
DWORD Signature; |
IMAGE_FILE_HEADER FileHeader; |
IMAGE_OPTIONAL_HEADER OptionalHeader; |
} IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32; |
#define IMAGE_SIZEOF_SHORT_NAME 8 |
typedef struct _IMAGE_SECTION_HEADER |
{ |
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; |
union |
{ |
DWORD PhysicalAddress; |
DWORD VirtualSize; |
} Misc; |
DWORD VirtualAddress; |
DWORD SizeOfRawData; |
DWORD PointerToRawData; |
DWORD PointerToRelocations; |
DWORD PointerToLinenumbers; |
WORD NumberOfRelocations; |
WORD NumberOfLinenumbers; |
DWORD Characteristics; |
} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; |
#pragma pack(pop) |
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 |
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 |
#define IMAGE_SCN_MEM_SHARED 0x10000000 |
#define IMAGE_SCN_MEM_EXECUTE 0x20000000 |
#define IMAGE_SCN_MEM_WRITE 0x80000000 |
#pragma pack(push,4) |
typedef struct _IMAGE_BASE_RELOCATION { |
DWORD VirtualAddress; |
DWORD SizeOfBlock; |
} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; |
#pragma pack(pop) |
typedef struct _IMAGE_IMPORT_DESCRIPTOR |
{ |
union |
{ |
DWORD Characteristics; |
DWORD OriginalFirstThunk; |
}; |
DWORD TimeDateStamp; |
DWORD ForwarderChain; |
DWORD Name; |
DWORD FirstThunk; |
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR; |
typedef struct _IMAGE_THUNK_DATA32 |
{ |
union |
{ |
DWORD ForwarderString; |
DWORD Function; |
DWORD Ordinal; |
DWORD AddressOfData; |
} u1; |
} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32; |
typedef struct _IMAGE_IMPORT_BY_NAME |
{ |
WORD Hint; |
BYTE Name[1]; |
} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME; |
#define IMAGE_ORDINAL_FLAG 0x80000000 |
typedef struct _IMAGE_EXPORT_DIRECTORY { |
DWORD Characteristics; |
DWORD TimeDateStamp; |
WORD MajorVersion; |
WORD MinorVersion; |
DWORD Name; |
DWORD Base; |
DWORD NumberOfFunctions; |
DWORD NumberOfNames; |
DWORD AddressOfFunctions; |
DWORD AddressOfNames; |
DWORD AddressOfNameOrdinals; |
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; |
#define MakePtr( cast, ptr, addValue ) (cast)( (uint32_t)(ptr) + (uint32_t)(addValue) ) |
/programs/develop/libraries/newlib/pe |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/newlib/pe_app.lds |
---|
0,0 → 1,122 |
OUTPUT_FORMAT(pei-i386) |
ENTRY("__start") |
SECTIONS |
{ |
. = SIZEOF_HEADERS; |
. = ALIGN(__section_alignment__); |
.text __image_base__ + . : |
{ |
*(.init) |
*(.text) |
*(SORT(.text$*)) |
*(.text.*) |
*(.glue_7t) |
*(.glue_7) |
___CTOR_LIST__ = .; __CTOR_LIST__ = . ; |
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0); |
___DTOR_LIST__ = .; __DTOR_LIST__ = . ; |
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0); |
*(.fini) |
/* ??? Why is .gcc_exc here? */ |
*(.gcc_exc) |
PROVIDE (etext = .); |
*(.gcc_except_table) |
} |
.rdata ALIGN(__section_alignment__): |
{ |
*(.rdata) |
*(SORT(.rdata$*)) |
___RUNTIME_PSEUDO_RELOC_LIST__ = .; |
__RUNTIME_PSEUDO_RELOC_LIST__ = .; |
*(.rdata_runtime_pseudo_reloc) |
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .; |
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .; |
} |
.CRT ALIGN(__section_alignment__): |
{ |
___crt_xc_start__ = . ; |
*(SORT(.CRT$XC*)) /* C initialization */ |
___crt_xc_end__ = . ; |
___crt_xi_start__ = . ; |
*(SORT(.CRT$XI*)) /* C++ initialization */ |
___crt_xi_end__ = . ; |
___crt_xl_start__ = . ; |
*(SORT(.CRT$XL*)) /* TLS callbacks */ |
/* ___crt_xl_end__ is defined in the TLS Directory support code */ |
___crt_xp_start__ = . ; |
*(SORT(.CRT$XP*)) /* Pre-termination */ |
___crt_xp_end__ = . ; |
___crt_xt_start__ = . ; |
*(SORT(.CRT$XT*)) /* Termination */ |
___crt_xt_end__ = . ; |
} |
.data ALIGN(__section_alignment__): |
{ |
PROVIDE ( __data_start__ = .) ; |
*(.data) |
*(.data2) |
*(SORT(.data$*)) |
*(.jcr) |
__CRT_MT = .; |
LONG(0); |
PROVIDE ( __data_end__ = .) ; |
*(.data_cygwin_nocopy) |
} |
.eh_frame ALIGN(__section_alignment__): |
{ |
*(.eh_frame) |
___iend = . ; |
} |
.bss ALIGN(__section_alignment__): |
{ |
*(.bss) |
*(COMMON) |
} |
/DISCARD/ : |
{ |
*(.debug$S) |
*(.debug$T) |
*(.debug$F) |
*(.drectve) |
*(.note.GNU-stack) |
*(.edata) |
*(.comment) |
*(.debug_abbrev) |
*(.debug_info) |
*(.debug_line) |
*(.debug_frame) |
*(.debug_loc) |
*(.debug_pubnames) |
*(.debug_aranges) |
*(.debug_ranges) |
} |
.idata ALIGN(__section_alignment__): |
{ |
SORT(*)(.idata$2) |
SORT(*)(.idata$3) |
/* These zeroes mark the end of the import list. */ |
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); |
SORT(*)(.idata$4) |
SORT(*)(.idata$5) |
SORT(*)(.idata$6) |
SORT(*)(.idata$7) |
} |
.reloc ALIGN(__section_alignment__) : |
{ |
*(.reloc) |
} |
} |
/programs/develop/libraries/newlib/reent/getreent.c |
---|
4,10 → 4,6 |
#include <string.h> |
#include <reent.h> |
#ifdef __getreent |
#undef __getreent |
#endif |
static inline |
void *user_alloc(int size) |
{ |
28,21 → 24,12 |
_REENT_INIT_PTR(ent); |
__asm__ __volatile__( |
"movl %0, %%fs:0" |
"movl %0, %%fs:12" |
::"r"(ent)); |
__sinit(ent); |
} |
struct _reent * |
_DEFUN_VOID(__getreent) |
{ |
struct _reent *ent; |
__asm__ __volatile__( |
"movl %%fs:0, %0" |
:"=r"(ent)); |
return ent; |
} |
void __mutex_lock(volatile int *val) |
{ |
/programs/develop/libraries/newlib/reent/gettimeofdayr.c |
---|
0,0 → 1,113 |
/* Reentrant version of gettimeofday system call |
This implementation just calls the times/gettimeofday system calls. |
Gettimeofday may not be available on all targets. It's presence |
here is dubious. Consider it for internal use only. */ |
#include <reent.h> |
#include <time.h> |
#include <sys/time.h> |
#include <sys/times.h> |
#include <_syslist.h> |
#include <errno.h> |
/* Some targets provides their own versions of these functions. Those |
targets should define REENTRANT_SYSCALLS_PROVIDED in TARGET_CFLAGS. */ |
#ifdef _REENT_ONLY |
#ifndef REENTRANT_SYSCALLS_PROVIDED |
#define REENTRANT_SYSCALLS_PROVIDED |
#endif |
#endif |
#ifdef REENTRANT_SYSCALLS_PROVIDED |
int _dummy_gettimeofday_syscalls = 1; |
#else |
/* We use the errno variable used by the system dependent layer. */ |
#undef errno |
static int errno; |
/* |
FUNCTION |
<<_gettimeofday_r>>---Reentrant version of gettimeofday |
INDEX |
_gettimeofday_r |
ANSI_SYNOPSIS |
#include <reent.h> |
#include <time.h> |
int _gettimeofday_r(struct _reent *<[ptr]>, |
struct timeval *<[ptimeval]>, |
void *<[ptimezone]>); |
TRAD_SYNOPSIS |
#include <reent.h> |
#include <time.h> |
int _gettimeofday_r(<[ptr]>, <[ptimeval]>, <[ptimezone]>) |
struct _reent *<[ptr]>; |
struct timeval *<[ptimeval]>; |
void *<[ptimezone]>; |
DESCRIPTION |
This is a reentrant version of <<gettimeofday>>. It |
takes a pointer to the global data block, which holds |
<<errno>>. |
This function is only available for a few targets. |
Check libc.a to see if its available on yours. |
*/ |
int |
_DEFUN (_gettimeofday_r, (ptr, ptimeval, ptimezone), |
struct _reent *ptr _AND |
struct timeval *ptimeval _AND |
void *ptimezone) |
{ |
int ret; |
errno = 0; |
if ((ret = _gettimeofday (ptimeval, ptimezone)) == -1 && errno != 0) |
ptr->_errno = errno; |
return ret; |
} |
#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) |
int |
_gettimeofday (struct timeval *tv, void *tz) |
{ |
unsigned int xtmp; |
struct tm tmblk; |
if( tv ) |
{ |
tv->tv_usec = 0; |
__asm__ __volatile__("int $0x40":"=a"(xtmp):"0"(3)); |
tmblk.tm_sec = (xtmp>>16)&0xff; |
tmblk.tm_min = (xtmp>>8)&0xff; |
tmblk.tm_hour = xtmp&0xff; |
BCD_TO_BIN(tmblk.tm_sec); |
BCD_TO_BIN(tmblk.tm_min); |
BCD_TO_BIN(tmblk.tm_hour); |
__asm__ __volatile__("int $0x40":"=a"(xtmp):"0"(29)); |
tmblk.tm_mday = (xtmp>>16)&0xff; |
tmblk.tm_mon = ((xtmp>>8)&0xff)-1; |
tmblk.tm_year = ((xtmp&0xff)+2000)-1900; |
tmblk.tm_wday = tmblk.tm_yday = 0; |
tmblk.tm_isdst = -1; |
tv->tv_sec = mktime(&tmblk); |
return 0; |
} |
else |
{ |
errno = EINVAL; |
return -1; |
}; |
} |
#endif /* ! defined (REENTRANT_SYSCALLS_PROVIDED) */ |
/programs/develop/libraries/newlib/reent/openr.c |
---|
8,6 → 8,7 |
#include <stdlib.h> |
#include <string.h> |
#include <stdarg.h> |
#include <sys/kos_io.h> |
/* Some targets provides their own versions of this functions. Those |
targets should define REENTRANT_SYSCALLS_PROVIDED in TARGET_CFLAGS. */ |
49,63 → 50,7 |
*/ |
#pragma pack(push, 1) |
typedef struct |
{ |
char sec; |
char min; |
char hour; |
char rsv; |
}detime_t; |
typedef struct |
{ |
char day; |
char month; |
short year; |
}dedate_t; |
typedef struct |
{ |
unsigned attr; |
unsigned flags; |
union |
{ |
detime_t ctime; |
unsigned cr_time; |
}; |
union |
{ |
dedate_t cdate; |
unsigned cr_date; |
}; |
union |
{ |
detime_t atime; |
unsigned acc_time; |
}; |
union |
{ |
dedate_t adate; |
unsigned acc_date; |
}; |
union |
{ |
detime_t mtime; |
unsigned mod_time; |
}; |
union |
{ |
dedate_t mdate; |
unsigned mod_date; |
}; |
unsigned size; |
unsigned size_high; |
} fileinfo_t; |
#pragma pack(pop) |
#define NULL_HANDLE (int)-1 |
#define DUMMY_HANDLE (int)-2 |
126,100 → 71,7 |
extern int _fmode; |
int create_file(const char *path) |
{ |
int retval; |
__asm__ __volatile__ ( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %0, 1(%%esp) \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $2 \n\t" |
"movl %%esp, %%ebx \n\t" |
"movl $70, %%eax \n\t" |
"int $0x40 \n\t" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"r" (path) |
:"ebx"); |
return retval; |
}; |
int set_file_size(const char *path, unsigned size) |
{ |
int retval; |
__asm__ __volatile__( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %%eax, 1(%%esp) \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl %%ebx \n\t" |
"push $4 \n\t" |
"movl %%esp, %%ebx \n\t" |
"movl $70, %%eax \n\t" |
"int $0x40 \n\t" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"a" (path), "b" (size)); |
return retval; |
}; |
int get_fileinfo(const char *path, fileinfo_t *info) |
{ |
int retval; |
__asm__ __volatile__ ( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %1, 1(%%esp) \n\t" |
"pushl %%ebx \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $5 \n\t" |
"movl %%esp, %%ebx \n\t" |
"movl $70, %%eax \n\t" |
"int $0x40 \n\t" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"r" (path), "b" (info)); |
return retval; |
}; |
int read_file(const char *path, void *buff, |
size_t offset, size_t count, size_t *reads) |
{ |
int retval; |
int d0; |
__asm__ __volatile__( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %%eax, 1(%%esp) \n\t" |
"pushl %%ebx \n\t" |
"pushl %%edx \n\t" |
"pushl $0 \n\t" |
"pushl %%ecx \n\t" |
"pushl $0 \n\t" |
"movl %%esp, %%ebx \n\t" |
"mov $70, %%eax \n\t" |
"int $0x40 \n\t" |
"testl %%esi, %%esi \n\t" |
"jz 1f \n\t" |
"movl %%ebx, (%%esi) \n\t" |
"1:" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"a"(path),"b"(buff),"c"(offset),"d"(count),"S"(reads)); |
return retval; |
}; |
static inline void debug_out(const char val) |
{ |
__asm__ __volatile__( |
241,33 → 93,6 |
return ret; |
}; |
int write_file(const char *path,const void *buff, |
size_t offset, size_t count, size_t *writes) |
{ |
int retval; |
__asm__ __volatile__( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %%eax, 1(%%esp) \n\t" |
"pushl %%ebx \n\t" |
"pushl %%edx \n\t" |
"pushl $0 \n\t" |
"pushl %%ecx \n\t" |
"pushl $3 \n\t" |
"movl %%esp, %%ebx \n\t" |
"mov $70, %%eax \n\t" |
"int $0x40 \n\t" |
"testl %%esi, %%esi \n\t" |
"jz 1f \n\t" |
"movl %%ebx, (%%esi) \n\t" |
"1:" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"a"(path),"b"(buff),"c"(offset),"d"(count),"S"(writes)); |
return retval; |
}; |
static int __openFileHandle(const char *path, int mode, int *err) |
{ |
fileinfo_t info; |
/programs/develop/libraries/newlib/signal/signal.c |
---|
0,0 → 1,260 |
/* |
FUNCTION |
<<signal>>---specify handler subroutine for a signal |
INDEX |
signal |
INDEX |
_signal_r |
ANSI_SYNOPSIS |
#include <signal.h> |
void (*signal(int <[sig]>, void(*<[func]>)(int))) (int); |
void (*_signal_r(void *<[reent]>, int <[sig]>, void(*<[func]>)(int))) (int); |
TRAD_SYNOPSIS |
#include <signal.h> |
char ( * signal(<[sig]>, <[func]>) )() |
int <[sig]>; |
char ( * <[func]> )(); |
char ( * _signal_r(<[reent]>, <[sig]>, <[func]>) )() |
char *<[reent]>; |
int <[sig]>; |
char ( * <[func]> )(); |
DESCRIPTION |
<<signal>> provides a simple signal-handling implementation for embedded |
targets. |
<<signal>> allows you to request changed treatment for a particular |
signal <[sig]>. You can use one of the predefined macros <<SIG_DFL>> |
(select system default handling) or <<SIG_IGN>> (ignore this signal) |
as the value of <[func]>; otherwise, <[func]> is a function pointer |
that identifies a subroutine in your program as the handler for this signal. |
Some of the execution environment for signal handlers is |
unpredictable; notably, the only library function required to work |
correctly from within a signal handler is <<signal>> itself, and |
only when used to redefine the handler for the current signal value. |
Static storage is likewise unreliable for signal handlers, with one |
exception: if you declare a static storage location as `<<volatile |
sig_atomic_t>>', then you may use that location in a signal handler to |
store signal values. |
If your signal handler terminates using <<return>> (or implicit |
return), your program's execution continues at the point |
where it was when the signal was raised (whether by your program |
itself, or by an external event). Signal handlers can also |
use functions such as <<exit>> and <<abort>> to avoid returning. |
The alternate function <<_signal_r>> is the reentrant version. |
The extra argument <[reent]> is a pointer to a reentrancy structure. |
@c FIXME: do we have setjmp.h and assoc fns? |
RETURNS |
If your request for a signal handler cannot be honored, the result is |
<<SIG_ERR>>; a specific error number is also recorded in <<errno>>. |
Otherwise, the result is the previous handler (a function pointer or |
one of the predefined macros). |
PORTABILITY |
ANSI C requires <<signal>>. |
No supporting OS subroutines are required to link with <<signal>>, but |
it will not have any useful effects, except for software generated signals, |
without an operating system that can actually raise exceptions. |
*/ |
/* |
* signal.c |
* Original Author: G. Haley |
* |
* signal associates the function pointed to by func with the signal sig. When |
* a signal occurs, the value of func determines the action taken as follows: |
* if func is SIG_DFL, the default handling for that signal will occur; if func |
* is SIG_IGN, the signal will be ignored; otherwise, the default handling for |
* the signal is restored (SIG_DFL), and the function func is called with sig |
* as its argument. Returns the value of func for the previous call to signal |
* for the signal sig, or SIG_ERR if the request fails. |
*/ |
/* _init_signal initialises the signal handlers for each signal. This function |
is called by crt0 at program startup. */ |
#ifdef SIGNAL_PROVIDED |
int _dummy_simulated_signal; |
#else |
#include <errno.h> |
#include <signal.h> |
#include <stddef.h> |
#include <stdlib.h> |
#include <reent.h> |
#include <_syslist.h> |
int |
_DEFUN (_init_signal_r, (ptr), |
struct _reent *ptr) |
{ |
int i; |
if (ptr->_sig_func == NULL) |
{ |
ptr->_sig_func = (_sig_func_ptr *)_malloc_r (ptr, sizeof (_sig_func_ptr) * NSIG); |
if (ptr->_sig_func == NULL) |
return -1; |
for (i = 0; i < NSIG; i++) |
ptr->_sig_func[i] = SIG_DFL; |
} |
return 0; |
} |
_sig_func_ptr |
_DEFUN (_signal_r, (ptr, sig, func), |
struct _reent *ptr _AND |
int sig _AND |
_sig_func_ptr func) |
{ |
_sig_func_ptr old_func; |
if (sig < 0 || sig >= NSIG) |
{ |
ptr->_errno = EINVAL; |
return SIG_ERR; |
} |
if (ptr->_sig_func == NULL && _init_signal_r (ptr) != 0) |
return SIG_ERR; |
old_func = ptr->_sig_func[sig]; |
ptr->_sig_func[sig] = func; |
return old_func; |
} |
int |
_DEFUN (_raise_r, (ptr, sig), |
struct _reent *ptr _AND |
int sig) |
{ |
_sig_func_ptr func; |
if (sig < 0 || sig >= NSIG) |
{ |
ptr->_errno = EINVAL; |
return -1; |
} |
if (ptr->_sig_func == NULL) |
func = SIG_DFL; |
else |
func = ptr->_sig_func[sig]; |
if (func == SIG_DFL) |
return _kill_r (ptr, _getpid_r (ptr), sig); |
else if (func == SIG_IGN) |
return 0; |
else if (func == SIG_ERR) |
{ |
ptr->_errno = EINVAL; |
return 1; |
} |
else |
{ |
ptr->_sig_func[sig] = SIG_DFL; |
func (sig); |
return 0; |
} |
} |
int |
_DEFUN (__sigtramp_r, (ptr, sig), |
struct _reent *ptr _AND |
int sig) |
{ |
_sig_func_ptr func; |
if (sig < 0 || sig >= NSIG) |
{ |
return -1; |
} |
if (ptr->_sig_func == NULL && _init_signal_r (ptr) != 0) |
return -1; |
func = ptr->_sig_func[sig]; |
if (func == SIG_DFL) |
return 1; |
else if (func == SIG_ERR) |
return 2; |
else if (func == SIG_IGN) |
return 3; |
else |
{ |
ptr->_sig_func[sig] = SIG_DFL; |
func (sig); |
return 0; |
} |
} |
int _DEFUN (_kill_r, (ptr, pid, sig), |
struct _reent *ptr _AND |
int pid _AND |
int sig) |
{ |
// int ret; |
// errno = 0; |
// if ((ret = _kill (pid, sig)) == -1 && errno != 0) |
// ptr->_errno = errno; |
// return ret; |
/* sorry, guys */ |
ptr->_errno = EPERM; |
return -1; |
} |
#ifndef _REENT_ONLY |
int |
_DEFUN (raise, (sig), |
int sig) |
{ |
return _raise_r (_REENT, sig); |
} |
_sig_func_ptr |
_DEFUN (signal, (sig, func), |
int sig _AND |
_sig_func_ptr func) |
{ |
return _signal_r (_REENT, sig, func); |
} |
int |
_DEFUN_VOID (_init_signal) |
{ |
return _init_signal_r (_REENT); |
} |
int |
_DEFUN (__sigtramp, (sig), int sig) |
{ |
return __sigtramp_r (_REENT, sig); |
} |
#endif |
#endif /* !SIGNAL_PROVIDED */ |
/programs/develop/libraries/newlib/signal |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/newlib/static.lds |
---|
0,0 → 1,116 |
/*OUTPUT_FORMAT("binary")*/ |
ENTRY(__start) |
SECTIONS |
{ |
.text 0x000000: |
{ |
LONG(0x554e454D); |
LONG(0x32305445); |
LONG(1); |
LONG(__start); |
LONG(___iend); |
LONG(___memsize); |
LONG(___stacktop); |
LONG(___cmdline); |
LONG(___pgmname); /* full path */ |
LONG(0); /*FIXME tls data */ |
*(.init) |
*(.text) |
*(SORT(.text$*)) |
*(.text.*) |
*(.glue_7t) |
*(.glue_7) |
___CTOR_LIST__ = .; __CTOR_LIST__ = . ; |
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0); |
___DTOR_LIST__ = .; __DTOR_LIST__ = . ; |
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0); |
*(.fini) |
/* ??? Why is .gcc_exc here? */ |
*(.gcc_exc) |
PROVIDE (etext = .); |
*(.gcc_except_table) |
} |
.rdata ALIGN(16) : |
{ |
*(.rdata) |
*(SORT(.rdata$*)) |
___RUNTIME_PSEUDO_RELOC_LIST__ = .; |
__RUNTIME_PSEUDO_RELOC_LIST__ = .; |
*(.rdata_runtime_pseudo_reloc) |
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .; |
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .; |
} |
.CRT ALIGN(16) : |
{ |
___crt_xc_start__ = . ; |
*(SORT(.CRT$XC*)) /* C initialization */ |
___crt_xc_end__ = . ; |
___crt_xi_start__ = . ; |
*(SORT(.CRT$XI*)) /* C++ initialization */ |
___crt_xi_end__ = . ; |
___crt_xl_start__ = . ; |
*(SORT(.CRT$XL*)) /* TLS callbacks */ |
/* ___crt_xl_end__ is defined in the TLS Directory support code */ |
___crt_xp_start__ = . ; |
*(SORT(.CRT$XP*)) /* Pre-termination */ |
___crt_xp_end__ = . ; |
___crt_xt_start__ = . ; |
*(SORT(.CRT$XT*)) /* Termination */ |
___crt_xt_end__ = . ; |
} |
.data ALIGN(16) : |
{ |
__data_start__ = . ; |
*(.data) |
*(.data2) |
*(SORT(.data$*)) |
*(.jcr) |
__CRT_MT = .; |
LONG(0); |
__data_end__ = . ; |
*(.data_cygwin_nocopy) |
} |
.eh_frame ALIGN(16) : |
{ |
*(.eh_frame) |
___iend = . ; |
} |
bss ALIGN(16): |
{ |
*(.bss) |
*(COMMON) |
. = ALIGN(16); |
___cmdline = .; |
. = . + 256; |
___pgmname = .; |
___menuet__app_path_area = .; |
. = . + 1024 + 16; |
___stacktop = .; |
___memsize = . ; |
} |
/DISCARD/ : |
{ |
*(.debug$S) |
*(.debug$T) |
*(.debug$F) |
*(.drectve) |
*(.note.GNU-stack) |
*(.comment) |
*(.debug_abbrev) |
*(.debug_info) |
*(.debug_line) |
*(.debug_frame) |
*(.debug_loc) |
*(.debug_pubnames) |
*(.debug_aranges) |
*(.debug_ranges) |
} |
} |
/programs/develop/libraries/newlib/stdio/fdopen.c |
---|
0,0 → 1,144 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<fdopen>>---turn open file into a stream |
INDEX |
fdopen |
INDEX |
_fdopen_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
FILE *fdopen(int <[fd]>, const char *<[mode]>); |
FILE *_fdopen_r(struct _reent *<[reent]>, |
int <[fd]>, const char *<[mode]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
FILE *fdopen(<[fd]>, <[mode]>) |
int <[fd]>; |
char *<[mode]>; |
FILE *_fdopen_r(<[reent]>, <[fd]>, <[mode]>) |
struct _reent *<[reent]>; |
int <[fd]>; |
char *<[mode]>); |
DESCRIPTION |
<<fdopen>> produces a file descriptor of type <<FILE *>>, from a |
descriptor for an already-open file (returned, for example, by the |
system subroutine <<open>> rather than by <<fopen>>). |
The <[mode]> argument has the same meanings as in <<fopen>>. |
RETURNS |
File pointer or <<NULL>>, as for <<fopen>>. |
PORTABILITY |
<<fdopen>> is ANSI. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <sys/types.h> |
#include <sys/fcntl.h> |
#include <stdio.h> |
#include <errno.h> |
#include "local.h" |
#include <_syslist.h> |
FILE * |
_DEFUN(_fdopen_r, (ptr, fd, mode), |
struct _reent *ptr _AND |
int fd _AND |
_CONST char *mode) |
{ |
register FILE *fp; |
int flags, oflags; |
#ifdef HAVE_FCNTL |
int fdflags, fdmode; |
#endif |
if ((flags = __sflags (ptr, mode, &oflags)) == 0) |
return 0; |
/* make sure the mode the user wants is a subset of the actual mode */ |
#ifdef HAVE_FCNTL |
if ((fdflags = _fcntl_r (ptr, fd, F_GETFL, 0)) < 0) |
return 0; |
fdmode = fdflags & O_ACCMODE; |
if (fdmode != O_RDWR && (fdmode != (oflags & O_ACCMODE))) |
{ |
ptr->_errno = EBADF; |
return 0; |
} |
#endif |
if ((fp = __sfp (ptr)) == 0) |
return 0; |
_flockfile (fp); |
fp->_flags = flags; |
/* POSIX recommends setting the O_APPEND bit on fd to match append |
streams. Someone may later clear O_APPEND on fileno(fp), but the |
stream must still remain in append mode. Rely on __sflags |
setting __SAPP properly. */ |
#ifdef HAVE_FCNTL |
if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) |
_fcntl_r (ptr, fd, F_SETFL, fdflags | O_APPEND); |
#endif |
fp->_file = fd; |
fp->_cookie = (_PTR) fp; |
#undef _read |
#undef _write |
#undef _seek |
#undef _close |
fp->_read = __sread; |
fp->_write = __swrite; |
fp->_seek = __sseek; |
fp->_close = __sclose; |
#ifdef __SCLE |
/* Explicit given mode results in explicit setting mode on fd */ |
if (oflags & O_BINARY) |
setmode (fp->_file, O_BINARY); |
else if (oflags & O_TEXT) |
setmode (fp->_file, O_TEXT); |
if (__stextmode (fp->_file)) |
fp->_flags |= __SCLE; |
#endif |
_funlockfile (fp); |
return fp; |
} |
#ifndef _REENT_ONLY |
FILE * |
_DEFUN(fdopen, (fd, mode), |
int fd _AND |
_CONST char *mode) |
{ |
return _fdopen_r (_REENT, fd, mode); |
} |
#endif |
/programs/develop/libraries/newlib/stdio/fgets.c |
---|
0,0 → 1,193 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<fgets>>---get character string from a file or stream |
INDEX |
fgets |
INDEX |
_fgets_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
char *fgets(char *<[buf]>, int <[n]>, FILE *<[fp]>); |
#include <stdio.h> |
char *_fgets_r(struct _reent *<[ptr]>, char *<[buf]>, int <[n]>, FILE *<[fp]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
char *fgets(<[buf]>,<[n]>,<[fp]>) |
char *<[buf]>; |
int <[n]>; |
FILE *<[fp]>; |
#include <stdio.h> |
char *_fgets_r(<[ptr]>, <[buf]>,<[n]>,<[fp]>) |
struct _reent *<[ptr]>; |
char *<[buf]>; |
int <[n]>; |
FILE *<[fp]>; |
DESCRIPTION |
Reads at most <[n-1]> characters from <[fp]> until a newline |
is found. The characters including to the newline are stored |
in <[buf]>. The buffer is terminated with a 0. |
The <<_fgets_r>> function is simply the reentrant version of |
<<fgets>> and is passed an additional reentrancy structure |
pointer: <[ptr]>. |
RETURNS |
<<fgets>> returns the buffer passed to it, with the data |
filled in. If end of file occurs with some data already |
accumulated, the data is returned with no other indication. If |
no data are read, NULL is returned instead. |
PORTABILITY |
<<fgets>> should replace all uses of <<gets>>. Note however |
that <<fgets>> returns all of the data, while <<gets>> removes |
the trailing newline (with no indication that it has done so.) |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. |
*/ |
#include <_ansi.h> |
#include <stdio.h> |
#include <string.h> |
#include "local.h" |
/* |
* Read at most n-1 characters from the given file. |
* Stop when a newline has been read, or the count runs out. |
* Return first argument, or NULL if no characters were read. |
*/ |
char * |
_DEFUN(_fgets_r, (ptr, buf, n, fp), |
struct _reent * ptr _AND |
char *buf _AND |
int n _AND |
FILE * fp) |
{ |
size_t len; |
char *s; |
unsigned char *p, *t; |
if (n < 2) /* sanity check */ |
return 0; |
s = buf; |
CHECK_INIT(ptr, fp); |
__sfp_lock_acquire (); |
_flockfile (fp); |
#ifdef __SCLE |
if (fp->_flags & __SCLE) |
{ |
int c; |
/* Sorry, have to do it the slow way */ |
while (--n > 0 && (c = __sgetc_r (ptr, fp)) != EOF) |
{ |
*s++ = c; |
if (c == '\n') |
break; |
} |
if (c == EOF && s == buf) |
{ |
_funlockfile (fp); |
__sfp_lock_release (); |
return NULL; |
} |
*s = 0; |
_funlockfile (fp); |
__sfp_lock_release (); |
return buf; |
} |
#endif |
n--; /* leave space for NUL */ |
do |
{ |
/* |
* If the buffer is empty, refill it. |
*/ |
if ((len = fp->_r) <= 0) |
{ |
if (__srefill_r (ptr, fp)) |
{ |
/* EOF: stop with partial or no line */ |
if (s == buf) |
{ |
_funlockfile (fp); |
__sfp_lock_release (); |
return 0; |
} |
break; |
} |
len = fp->_r; |
} |
p = fp->_p; |
/* |
* Scan through at most n bytes of the current buffer, |
* looking for '\n'. If found, copy up to and including |
* newline, and stop. Otherwise, copy entire chunk |
* and loop. |
*/ |
if (len > n) |
len = n; |
t = (unsigned char *) memchr ((_PTR) p, '\n', len); |
if (t != 0) |
{ |
len = ++t - p; |
fp->_r -= len; |
fp->_p = t; |
_CAST_VOID memcpy ((_PTR) s, (_PTR) p, len); |
s[len] = 0; |
_funlockfile (fp); |
__sfp_lock_release (); |
return (buf); |
} |
fp->_r -= len; |
fp->_p += len; |
_CAST_VOID memcpy ((_PTR) s, (_PTR) p, len); |
s += len; |
} |
while ((n -= len) != 0); |
*s = 0; |
_funlockfile (fp); |
__sfp_lock_release (); |
return buf; |
} |
#ifndef _REENT_ONLY |
char * |
_DEFUN(fgets, (buf, n, fp), |
char *buf _AND |
int n _AND |
FILE * fp) |
{ |
return _fgets_r (_REENT, buf, n, fp); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/stdio/fiscanf.c |
---|
0,0 → 1,78 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#ifdef _HAVE_STDC |
#include <stdarg.h> |
#else |
#include <varargs.h> |
#endif |
#include "local.h" |
#ifndef _REENT_ONLY |
int |
#ifdef _HAVE_STDC |
fiscanf(FILE *fp, _CONST char *fmt, ...) |
#else |
fiscanf(FILE *fp, fmt, va_alist) |
FILE *fp; |
char *fmt; |
va_dcl |
#endif |
{ |
int ret; |
va_list ap; |
#ifdef _HAVE_STDC |
va_start (ap, fmt); |
#else |
va_start (ap); |
#endif |
ret = __svfiscanf_r (_REENT, fp, fmt, ap); |
va_end (ap); |
return ret; |
} |
#endif /* !_REENT_ONLY */ |
int |
#ifdef _HAVE_STDC |
_fiscanf_r(struct _reent *ptr, FILE *fp, _CONST char *fmt, ...) |
#else |
_fiscanf_r(ptr, FILE *fp, fmt, va_alist) |
struct _reent *ptr; |
FILE *fp; |
char *fmt; |
va_dcl |
#endif |
{ |
int ret; |
va_list ap; |
#ifdef _HAVE_STDC |
va_start (ap, fmt); |
#else |
va_start (ap); |
#endif |
ret = __svfiscanf_r (ptr, fp, fmt, ap); |
va_end (ap); |
return (ret); |
} |
/programs/develop/libraries/newlib/stdio/fread.c |
---|
0,0 → 1,265 |
/* |
* Copyright (c) 1990, 2007 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<fread>>---read array elements from a file |
INDEX |
fread |
INDEX |
_fread_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
size_t fread(void *<[buf]>, size_t <[size]>, size_t <[count]>, |
FILE *<[fp]>); |
#include <stdio.h> |
size_t _fread_r(struct _reent *<[ptr]>, void *<[buf]>, |
size_t <[size]>, size_t <[count]>, FILE *<[fp]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
size_t fread(<[buf]>, <[size]>, <[count]>, <[fp]>) |
char *<[buf]>; |
size_t <[size]>; |
size_t <[count]>; |
FILE *<[fp]>; |
#include <stdio.h> |
size_t _fread_r(<[ptr]>, <[buf]>, <[size]>, <[count]>, <[fp]>) |
struct _reent *<[ptr]>; |
char *<[buf]>; |
size_t <[size]>; |
size_t <[count]>; |
FILE *<[fp]>; |
DESCRIPTION |
<<fread>> attempts to copy, from the file or stream identified by |
<[fp]>, <[count]> elements (each of size <[size]>) into memory, |
starting at <[buf]>. <<fread>> may copy fewer elements than |
<[count]> if an error, or end of file, intervenes. |
<<fread>> also advances the file position indicator (if any) for |
<[fp]> by the number of @emph{characters} actually read. |
<<_fread_r>> is simply the reentrant version of <<fread>> that |
takes an additional reentrant structure pointer argument: <[ptr]>. |
RETURNS |
The result of <<fread>> is the number of elements it succeeded in |
reading. |
PORTABILITY |
ANSI C requires <<fread>>. |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. |
*/ |
#include <_ansi.h> |
#include <stdio.h> |
#include <string.h> |
#include <malloc.h> |
#include "local.h" |
#ifdef __SCLE |
static size_t |
_DEFUN(crlf_r, (ptr, fp, buf, count, eof), |
struct _reent * ptr _AND |
FILE * fp _AND |
char * buf _AND |
size_t count _AND |
int eof) |
{ |
int r; |
char *s, *d, *e; |
if (count == 0) |
return 0; |
e = buf + count; |
for (s=d=buf; s<e-1; s++) |
{ |
if (*s == '\r' && s[1] == '\n') |
s++; |
*d++ = *s; |
} |
if (s < e) |
{ |
if (*s == '\r') |
{ |
int c = __sgetc_raw_r (ptr, fp); |
if (c == '\n') |
*s = '\n'; |
else |
ungetc (c, fp); |
} |
*d++ = *s++; |
} |
while (d < e) |
{ |
r = _getc_r (ptr, fp); |
if (r == EOF) |
return count - (e-d); |
*d++ = r; |
} |
return count; |
} |
#endif |
size_t |
_DEFUN(_fread_r, (ptr, buf, size, count, fp), |
struct _reent * ptr _AND |
_PTR buf _AND |
size_t size _AND |
size_t count _AND |
FILE * fp) |
{ |
register size_t resid; |
register char *p; |
register int r; |
size_t total; |
if ((resid = count * size) == 0) |
return 0; |
CHECK_INIT(ptr, fp); |
__sfp_lock_acquire (); |
_flockfile (fp); |
ORIENT (fp, -1); |
if (fp->_r < 0) |
fp->_r = 0; |
total = resid; |
p = buf; |
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) |
/* Optimize unbuffered I/O. */ |
if (fp->_flags & __SNBF) |
{ |
/* First copy any available characters from ungetc buffer. */ |
int copy_size = resid > fp->_r ? fp->_r : resid; |
_CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) copy_size); |
fp->_p += copy_size; |
fp->_r -= copy_size; |
p += copy_size; |
resid -= copy_size; |
/* If still more data needed, free any allocated ungetc buffer. */ |
if (HASUB (fp) && resid > 0) |
FREEUB (ptr, fp); |
/* Finally read directly into user's buffer if needed. */ |
while (resid > 0) |
{ |
int rc = 0; |
/* save fp buffering state */ |
void *old_base = fp->_bf._base; |
void * old_p = fp->_p; |
int old_size = fp->_bf._size; |
/* allow __refill to use user's buffer */ |
fp->_bf._base = (unsigned char *) p; |
fp->_bf._size = resid; |
fp->_p = (unsigned char *) p; |
rc = __srefill_r (ptr, fp); |
/* restore fp buffering back to original state */ |
fp->_bf._base = old_base; |
fp->_bf._size = old_size; |
fp->_p = old_p; |
resid -= fp->_r; |
p += fp->_r; |
fp->_r = 0; |
if (rc) |
{ |
#ifdef __SCLE |
if (fp->_flags & __SCLE) |
{ |
_funlockfile (fp); |
__sfp_lock_release (); |
return crlf_r (ptr, fp, buf, total-resid, 1) / size; |
} |
#endif |
_funlockfile (fp); |
__sfp_lock_release (); |
return (total - resid) / size; |
} |
} |
} |
else |
#endif /* !PREFER_SIZE_OVER_SPEED && !__OPTIMIZE_SIZE__ */ |
{ |
while (resid > (r = fp->_r)) |
{ |
_CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) r); |
fp->_p += r; |
/* fp->_r = 0 ... done in __srefill */ |
p += r; |
resid -= r; |
if (__srefill_r (ptr, fp)) |
{ |
/* no more input: return partial result */ |
#ifdef __SCLE |
if (fp->_flags & __SCLE) |
{ |
_funlockfile (fp); |
__sfp_lock_release (); |
return crlf_r (ptr, fp, buf, total-resid, 1) / size; |
} |
#endif |
_funlockfile (fp); |
__sfp_lock_release (); |
return (total - resid) / size; |
} |
} |
_CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, resid); |
fp->_r -= resid; |
fp->_p += resid; |
} |
/* Perform any CR/LF clean-up if necessary. */ |
#ifdef __SCLE |
if (fp->_flags & __SCLE) |
{ |
_funlockfile (fp); |
__sfp_lock_release (); |
return crlf_r(ptr, fp, buf, total, 0) / size; |
} |
#endif |
_funlockfile (fp); |
__sfp_lock_release (); |
return count; |
} |
#ifndef _REENT_ONLY |
size_t |
_DEFUN(fread, (buf, size, count, fp), |
_PTR buf _AND |
size_t size _AND |
size_t count _AND |
FILE * fp) |
{ |
return _fread_r (_REENT, buf, size, count, fp); |
} |
#endif |
/programs/develop/libraries/newlib/stdio/freopen.c |
---|
0,0 → 1,250 |
/* |
* Copyright (c) 1990, 2007 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<freopen>>---open a file using an existing file descriptor |
INDEX |
freopen |
INDEX |
_freopen_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
FILE *freopen(const char *<[file]>, const char *<[mode]>, |
FILE *<[fp]>); |
FILE *_freopen_r(struct _reent *<[ptr]>, const char *<[file]>, |
const char *<[mode]>, FILE *<[fp]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
FILE *freopen(<[file]>, <[mode]>, <[fp]>) |
char *<[file]>; |
char *<[mode]>; |
FILE *<[fp]>; |
FILE *_freopen_r(<[ptr]>, <[file]>, <[mode]>, <[fp]>) |
struct _reent *<[ptr]>; |
char *<[file]>; |
char *<[mode]>; |
FILE *<[fp]>; |
DESCRIPTION |
Use this variant of <<fopen>> if you wish to specify a particular file |
descriptor <[fp]> (notably <<stdin>>, <<stdout>>, or <<stderr>>) for |
the file. |
If <[fp]> was associated with another file or stream, <<freopen>> |
closes that other file or stream (but ignores any errors while closing |
it). |
<[file]> and <[mode]> are used just as in <<fopen>>. |
If <[file]> is <<NULL>>, the underlying stream is modified rather than |
closed. The file cannot be given a more permissive access mode (for |
example, a <[mode]> of "w" will fail on a read-only file descriptor), |
but can change status such as append or binary mode. If modification |
is not possible, failure occurs. |
RETURNS |
If successful, the result is the same as the argument <[fp]>. If the |
file cannot be opened as specified, the result is <<NULL>>. |
PORTABILITY |
ANSI C requires <<freopen>>. |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
<<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <time.h> |
#include <stdio.h> |
#include <string.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <stdlib.h> |
#include <sys/lock.h> |
#include "local.h" |
/* |
* Re-direct an existing, open (probably) file to some other file. |
*/ |
FILE * |
_DEFUN(_freopen_r, (ptr, file, mode, fp), |
struct _reent *ptr _AND |
const char *file _AND |
const char *mode _AND |
register FILE *fp) |
{ |
register int f; |
int flags, oflags; |
int e = 0; |
__sfp_lock_acquire (); |
CHECK_INIT (ptr, fp); |
_flockfile (fp); |
if ((flags = __sflags (ptr, mode, &oflags)) == 0) |
{ |
_funlockfile (fp); |
_fclose_r (ptr, fp); |
__sfp_lock_release (); |
return NULL; |
} |
/* |
* Remember whether the stream was open to begin with, and |
* which file descriptor (if any) was associated with it. |
* If it was attached to a descriptor, defer closing it, |
* so that, e.g., freopen("/dev/stdin", "r", stdin) works. |
* This is unnecessary if it was not a Unix file. |
*/ |
if (fp->_flags == 0) |
fp->_flags = __SEOF; /* hold on to it */ |
else |
{ |
if (fp->_flags & __SWR) |
_fflush_r (ptr, fp); |
/* |
* If close is NULL, closing is a no-op, hence pointless. |
* If file is NULL, the file should not be closed. |
*/ |
if (fp->_close != NULL && file != NULL) |
fp->_close (ptr, fp->_cookie); |
} |
/* |
* Now get a new descriptor to refer to the new file, or reuse the |
* existing file descriptor if file is NULL. |
*/ |
if (file != NULL) |
{ |
f = _open_r (ptr, (char *) file, oflags, 0666); |
e = ptr->_errno; |
} |
else |
{ |
#ifdef HAVE_FCNTL |
int oldflags; |
/* |
* Reuse the file descriptor, but only if the new access mode is |
* equal or less permissive than the old. F_SETFL correctly |
* ignores creation flags. |
*/ |
f = fp->_file; |
if ((oldflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1 |
|| ! ((oldflags & O_ACCMODE) == O_RDWR |
|| ((oldflags ^ oflags) & O_ACCMODE) == 0) |
|| _fcntl_r (ptr, f, F_SETFL, oflags) == -1) |
f = -1; |
#else |
/* We cannot modify without fcntl support. */ |
f = -1; |
#endif |
#ifdef __SCLE |
/* |
* F_SETFL doesn't change textmode. Don't mess with modes of ttys. |
*/ |
if (0 <= f && ! _isatty_r (ptr, f) |
&& setmode (f, oflags & (O_BINARY | O_TEXT)) == -1) |
f = -1; |
#endif |
if (f < 0) |
{ |
e = EBADF; |
if (fp->_close != NULL) |
fp->_close (ptr, fp->_cookie); |
} |
} |
/* |
* Finish closing fp. Even if the open succeeded above, |
* we cannot keep fp->_base: it may be the wrong size. |
* This loses the effect of any setbuffer calls, |
* but stdio has always done this before. |
*/ |
if (fp->_flags & __SMBF) |
_free_r (ptr, (char *) fp->_bf._base); |
fp->_w = 0; |
fp->_r = 0; |
fp->_p = NULL; |
fp->_bf._base = NULL; |
fp->_bf._size = 0; |
fp->_lbfsize = 0; |
if (HASUB (fp)) |
FREEUB (ptr, fp); |
fp->_ub._size = 0; |
if (HASLB (fp)) |
FREELB (ptr, fp); |
fp->_lb._size = 0; |
fp->_flags & ~__SORD; |
fp->_flags2 = 0; |
memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); |
if (f < 0) |
{ /* did not get it after all */ |
fp->_flags = 0; /* set it free */ |
ptr->_errno = e; /* restore in case _close clobbered */ |
_funlockfile (fp); |
#ifndef __SINGLE_THREAD__ |
__lock_close_recursive (fp->_lock); |
#endif |
__sfp_lock_release (); |
return NULL; |
} |
fp->_flags = flags; |
fp->_file = f; |
fp->_cookie = (_PTR) fp; |
fp->_read = __sread; |
fp->_write = __swrite; |
fp->_seek = __sseek; |
fp->_close = __sclose; |
#ifdef __SCLE |
if (__stextmode (fp->_file)) |
fp->_flags |= __SCLE; |
#endif |
_funlockfile (fp); |
__sfp_lock_release (); |
return fp; |
} |
#ifndef _REENT_ONLY |
FILE * |
_DEFUN(freopen, (file, mode, fp), |
_CONST char *file _AND |
_CONST char *mode _AND |
register FILE *fp) |
{ |
return _freopen_r (_REENT, file, mode, fp); |
} |
#endif /*!_REENT_ONLY */ |
/programs/develop/libraries/newlib/stdio/fscanf.c |
---|
0,0 → 1,78 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#ifdef _HAVE_STDC |
#include <stdarg.h> |
#else |
#include <varargs.h> |
#endif |
#include "local.h" |
#ifndef _REENT_ONLY |
int |
#ifdef _HAVE_STDC |
fscanf(FILE *fp, _CONST char *fmt, ...) |
#else |
fscanf(FILE *fp, fmt, va_alist) |
FILE *fp; |
char *fmt; |
va_dcl |
#endif |
{ |
int ret; |
va_list ap; |
#ifdef _HAVE_STDC |
va_start (ap, fmt); |
#else |
va_start (ap); |
#endif |
ret = __svfscanf_r (_REENT, fp, fmt, ap); |
va_end (ap); |
return ret; |
} |
#endif /* !_REENT_ONLY */ |
int |
#ifdef _HAVE_STDC |
_fscanf_r(struct _reent *ptr, FILE *fp, _CONST char *fmt, ...) |
#else |
_fscanf_r(ptr, FILE *fp, fmt, va_alist) |
struct _reent *ptr; |
FILE *fp; |
char *fmt; |
va_dcl |
#endif |
{ |
int ret; |
va_list ap; |
#ifdef _HAVE_STDC |
va_start (ap, fmt); |
#else |
va_start (ap); |
#endif |
ret = __svfscanf_r (ptr, fp, fmt, ap); |
va_end (ap); |
return (ret); |
} |
/programs/develop/libraries/newlib/stdio/fseeko.c |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 2002, Red Hat Inc. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
int |
_DEFUN(_fseeko_r, (ptr, fp, offset, whence), |
struct _reent *ptr _AND |
register FILE *fp _AND |
_off_t offset _AND |
int whence) |
{ |
return _fseek_r (ptr, fp, (long)offset, whence); |
} |
#ifndef _REENT_ONLY |
int |
_DEFUN(fseeko, (fp, offset, whence), |
register FILE *fp _AND |
_off_t offset _AND |
int whence) |
{ |
/* for now we simply cast since off_t should be long */ |
return _fseek_r (_REENT, fp, (long)offset, whence); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/stdio/ftell.c |
---|
0,0 → 1,177 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<ftell>>, <<ftello>>---return position in a stream or file |
INDEX |
ftell |
INDEX |
ftello |
INDEX |
_ftell_r |
INDEX |
_ftello_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
long ftell(FILE *<[fp]>); |
off_t ftello(FILE *<[fp]>); |
long _ftell_r(struct _reent *<[ptr]>, FILE *<[fp]>); |
off_t _ftello_r(struct _reent *<[ptr]>, FILE *<[fp]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
long ftell(<[fp]>) |
FILE *<[fp]>; |
off_t ftello(<[fp]>) |
FILE *<[fp]>; |
long _ftell_r(<[ptr]>, <[fp]>) |
struct _reent *<[ptr]>; |
FILE *<[fp]>; |
off_t _ftello_r(<[ptr]>, <[fp]>) |
struct _reent *<[ptr]>; |
FILE *<[fp]>; |
DESCRIPTION |
Objects of type <<FILE>> can have a ``position'' that records how much |
of the file your program has already read. Many of the <<stdio>> functions |
depend on this position, and many change it as a side effect. |
The result of <<ftell>>/<<ftello>> is the current position for a file |
identified by <[fp]>. If you record this result, you can later |
use it with <<fseek>>/<<fseeko>> to return the file to this |
position. The difference between <<ftell>> and <<ftello>> is that |
<<ftell>> returns <<long>> and <<ftello>> returns <<off_t>>. |
In the current implementation, <<ftell>>/<<ftello>> simply uses a character |
count to represent the file position; this is the same number that |
would be recorded by <<fgetpos>>. |
RETURNS |
<<ftell>>/<<ftello>> return the file position, if possible. If they cannot do |
this, they return <<-1L>>. Failure occurs on streams that do not support |
positioning; the global <<errno>> indicates this condition with the |
value <<ESPIPE>>. |
PORTABILITY |
<<ftell>> is required by the ANSI C standard, but the meaning of its |
result (when successful) is not specified beyond requiring that it be |
acceptable as an argument to <<fseek>>. In particular, other |
conforming C implementations may return a different result from |
<<ftell>> than what <<fgetpos>> records. |
<<ftello>> is defined by the Single Unix specification. |
No supporting OS subroutines are required. |
*/ |
#if defined(LIBC_SCCS) && !defined(lint) |
static char sccsid[] = "%W% (Berkeley) %G%"; |
#endif /* LIBC_SCCS and not lint */ |
/* |
* ftell: return current offset. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#include <errno.h> |
#include "local.h" |
long |
_DEFUN(_ftell_r, (ptr, fp), |
struct _reent *ptr _AND |
register FILE * fp) |
{ |
_fpos_t pos; |
/* Ensure stdio is set up. */ |
CHECK_INIT (ptr, fp); |
_flockfile (fp); |
if (fp->_seek == NULL) |
{ |
ptr->_errno = ESPIPE; |
_funlockfile (fp); |
return -1L; |
} |
/* Find offset of underlying I/O object, then adjust for buffered |
bytes. Flush a write stream, since the offset may be altered if |
the stream is appending. Do not flush a read stream, since we |
must not lose the ungetc buffer. */ |
if (fp->_flags & __SWR) |
_fflush_r (ptr, fp); |
if (fp->_flags & __SOFF) |
pos = fp->_offset; |
else |
{ |
pos = fp->_seek (ptr, fp->_cookie, (_fpos_t) 0, SEEK_CUR); |
if (pos == -1L) |
{ |
_funlockfile (fp); |
return pos; |
} |
} |
if (fp->_flags & __SRD) |
{ |
/* |
* Reading. Any unread characters (including |
* those from ungetc) cause the position to be |
* smaller than that in the underlying object. |
*/ |
pos -= fp->_r; |
if (HASUB (fp)) |
pos -= fp->_ur; |
} |
else if ((fp->_flags & __SWR) && fp->_p != NULL) |
{ |
/* |
* Writing. Any buffered characters cause the |
* position to be greater than that in the |
* underlying object. |
*/ |
pos += fp->_p - fp->_bf._base; |
} |
_funlockfile (fp); |
if ((long)pos != pos) |
{ |
pos = -1; |
ptr->_errno = EOVERFLOW; |
} |
return pos; |
} |
#ifndef _REENT_ONLY |
long |
_DEFUN(ftell, (fp), |
register FILE * fp) |
{ |
return _ftell_r (_REENT, fp); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/stdio/ftello.c |
---|
0,0 → 1,40 |
/* |
* Copyright (c) 2002, Red Hat Inc. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
_off_t |
_DEFUN(_ftello_r, (ptr, fp), |
struct _reent * ptr _AND |
register FILE * fp) |
{ |
/* for now we simply cast since off_t should be long */ |
return (_off_t)_ftell_r (ptr, fp); |
} |
#ifndef _REENT_ONLY |
_off_t |
_DEFUN(ftello, (fp), |
register FILE * fp) |
{ |
return (_off_t)_ftell_r (_REENT, fp); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/stdio/putchar.c |
---|
0,0 → 1,97 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<putchar>>---write a character (macro) |
INDEX |
putchar |
INDEX |
_putchar_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
int putchar(int <[ch]>); |
int _putchar_r(struct _reent *<[reent]>, int <[ch]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
int putchar(<[ch]>) |
int <[ch]>; |
int _putchar_r(<[reent]>, <[ch]>) |
struct _reent *<[reent]>; |
int <[ch]>; |
DESCRIPTION |
<<putchar>> is a macro, defined in <<stdio.h>>. <<putchar>> |
writes its argument to the standard output stream, |
after converting it from an <<int>> to an <<unsigned char>>. |
The alternate function <<_putchar_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
If successful, <<putchar>> returns its argument <[ch]>. If an error |
intervenes, the result is <<EOF>>. You can use `<<ferror(stdin)>>' to |
query for errors. |
PORTABILITY |
ANSI C requires <<putchar>>; it suggests, but does not require, that |
<<putchar>> be implemented as a macro. |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. |
*/ |
#if defined(LIBC_SCCS) && !defined(lint) |
static char sccsid[] = "%W% (Berkeley) %G%"; |
#endif /* LIBC_SCCS and not lint */ |
/* |
* A subroutine version of the macro putchar. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#include "local.h" |
#undef putchar |
int |
_DEFUN(_putchar_r, (ptr, c), |
struct _reent *ptr _AND |
int c) |
{ |
_REENT_SMALL_CHECK_INIT (ptr); |
return _putc_r (ptr, c, _stdout_r (ptr)); |
} |
#ifndef _REENT_ONLY |
int |
_DEFUN(putchar, (c), |
int c) |
{ |
_REENT_SMALL_CHECK_INIT (_REENT); |
return _putc_r (_REENT, c, _stdout_r (_REENT)); |
} |
#endif |
/programs/develop/libraries/newlib/stdio/remove.c |
---|
0,0 → 1,91 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<remove>>---delete a file's name |
INDEX |
remove |
INDEX |
_remove_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
int remove(char *<[filename]>); |
int _remove_r(struct _reent *<[reent]>, char *<[filename]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
int remove(<[filename]>) |
char *<[filename]>; |
int _remove_r(<[reent]>, <[filename]>) |
struct _reent *<[reent]>; |
char *<[filename]>; |
DESCRIPTION |
Use <<remove>> to dissolve the association between a particular |
filename (the string at <[filename]>) and the file it represents. |
After calling <<remove>> with a particular filename, you will no |
longer be able to open the file by that name. |
In this implementation, you may use <<remove>> on an open file without |
error; existing file descriptors for the file will continue to access |
the file's data until the program using them closes the file. |
The alternate function <<_remove_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<remove>> returns <<0>> if it succeeds, <<-1>> if it fails. |
PORTABILITY |
ANSI C requires <<remove>>, but only specifies that the result on |
failure be nonzero. The behavior of <<remove>> when you call it on an |
open file may vary among implementations. |
Supporting OS subroutine required: <<unlink>>. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#include <sys/kos_io.h> |
int |
_DEFUN(_remove_r, (ptr, filename), |
struct _reent *ptr _AND |
_CONST char *filename) |
{ |
return delete_file(filename)==0 ? 0: -1; |
} |
#ifndef _REENT_ONLY |
int |
_DEFUN(remove, (filename), |
_CONST char *filename) |
{ |
return delete_file(filename)==0 ? 0: -1; |
} |
#endif |
/programs/develop/libraries/newlib/stdio/rename.c |
---|
0,0 → 1,80 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<rename>>---rename a file |
INDEX |
rename |
ANSI_SYNOPSIS |
#include <stdio.h> |
int rename(const char *<[old]>, const char *<[new]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
int rename(<[old]>, <[new]>) |
char *<[old]>; |
char *<[new]>; |
DESCRIPTION |
Use <<rename>> to establish a new name (the string at <[new]>) for a |
file now known by the string at <[old]>. After a successful |
<<rename>>, the file is no longer accessible by the string at <[old]>. |
If <<rename>> fails, the file named <<*<[old]>>> is unaffected. The |
conditions for failure depend on the host operating system. |
RETURNS |
The result is either <<0>> (when successful) or <<-1>> (when the file |
could not be renamed). |
PORTABILITY |
ANSI C requires <<rename>>, but only specifies that the result on |
failure be nonzero. The effects of using the name of an existing file |
as <<*<[new]>>> may vary from one implementation to another. |
Supporting OS subroutines required: <<link>>, <<unlink>>, or <<rename>>. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#include <sys/unistd.h> |
int |
_DEFUN (_rename_r, (ptr, old, new), |
struct _reent *ptr _AND |
_CONST char *old _AND |
_CONST char *new) |
{ |
return -1; |
} |
#ifndef _REENT_ONLY |
int |
_DEFUN(rename, (old, new), |
_CONST char *old _AND |
_CONST char *new) |
{ |
return -1; |
} |
#endif |
/programs/develop/libraries/newlib/stdio/rget.c |
---|
0,0 → 1,59 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* No user fns here. Pesch 15apr92. */ |
#if defined(LIBC_SCCS) && !defined(lint) |
static char sccsid[] = "%W% (Berkeley) %G%"; |
#endif /* LIBC_SCCS and not lint */ |
#include <_ansi.h> |
#include <stdio.h> |
#include <errno.h> |
#include "local.h" |
/* |
* Handle getc() when the buffer ran out: |
* Refill, then return the first character |
* in the newly-filled buffer. |
*/ |
int |
_DEFUN(__srget_r, (ptr, fp), |
struct _reent *ptr _AND |
register FILE *fp) |
{ |
/* Ensure that any fake std stream is resolved before |
we call __srefill_r so we may access the true read buffer. */ |
CHECK_INIT(ptr, fp); |
if (__srefill_r (ptr, fp) == 0) |
{ |
fp->_r--; |
return *fp->_p++; |
} |
return EOF; |
} |
/* This function isn't any longer declared in stdio.h, but it's |
required for backward compatibility with applications built against |
earlier dynamically built newlib libraries. */ |
int |
_DEFUN(__srget, (fp), |
register FILE *fp) |
{ |
return __srget_r (_REENT, fp); |
} |
/programs/develop/libraries/newlib/stdio/setvbuf.c |
---|
0,0 → 1,198 |
/* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
/* |
FUNCTION |
<<setvbuf>>---specify file or stream buffering |
INDEX |
setvbuf |
ANSI_SYNOPSIS |
#include <stdio.h> |
int setvbuf(FILE *<[fp]>, char *<[buf]>, |
int <[mode]>, size_t <[size]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
int setvbuf(<[fp]>, <[buf]>, <[mode]>, <[size]>) |
FILE *<[fp]>; |
char *<[buf]>; |
int <[mode]>; |
size_t <[size]>; |
DESCRIPTION |
Use <<setvbuf>> to specify what kind of buffering you want for the |
file or stream identified by <[fp]>, by using one of the following |
values (from <<stdio.h>>) as the <[mode]> argument: |
o+ |
o _IONBF |
Do not use a buffer: send output directly to the host system for the |
file or stream identified by <[fp]>. |
o _IOFBF |
Use full output buffering: output will be passed on to the host system |
only when the buffer is full, or when an input operation intervenes. |
o _IOLBF |
Use line buffering: pass on output to the host system at every |
newline, as well as when the buffer is full, or when an input |
operation intervenes. |
o- |
Use the <[size]> argument to specify how large a buffer you wish. You |
can supply the buffer itself, if you wish, by passing a pointer to a |
suitable area of memory as <[buf]>. Otherwise, you may pass <<NULL>> |
as the <[buf]> argument, and <<setvbuf>> will allocate the buffer. |
WARNINGS |
You may only use <<setvbuf>> before performing any file operation other |
than opening the file. |
If you supply a non-null <[buf]>, you must ensure that the associated |
storage continues to be available until you close the stream |
identified by <[fp]>. |
RETURNS |
A <<0>> result indicates success, <<EOF>> failure (invalid <[mode]> or |
<[size]> can cause failure). |
PORTABILITY |
Both ANSI C and the System V Interface Definition (Issue 2) require |
<<setvbuf>>. However, they differ on the meaning of a <<NULL>> buffer |
pointer: the SVID issue 2 specification says that a <<NULL>> buffer |
pointer requests unbuffered output. For maximum portability, avoid |
<<NULL>> buffer pointers. |
Both specifications describe the result on failure only as a |
nonzero value. |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. |
*/ |
#include <_ansi.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include "local.h" |
/* |
* Set one of the three kinds of buffering, optionally including a buffer. |
*/ |
int |
_DEFUN(setvbuf, (fp, buf, mode, size), |
register FILE * fp _AND |
char *buf _AND |
register int mode _AND |
register size_t size) |
{ |
int ret = 0; |
CHECK_INIT (_REENT, fp); |
_flockfile (fp); |
/* |
* Verify arguments. The `int' limit on `size' is due to this |
* particular implementation. |
*/ |
if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || (int)(_POINTER_INT) size < 0) |
{ |
_funlockfile (fp); |
return (EOF); |
} |
/* |
* Write current buffer, if any; drop read count, if any. |
* Make sure putc() will not think fp is line buffered. |
* Free old buffer if it was from malloc(). Clear line and |
* non buffer flags, and clear malloc flag. |
*/ |
_fflush_r (_REENT, fp); |
fp->_r = 0; |
fp->_lbfsize = 0; |
if (fp->_flags & __SMBF) |
_free_r (_REENT, (_PTR) fp->_bf._base); |
fp->_flags &= ~(__SLBF | __SNBF | __SMBF); |
if (mode == _IONBF) |
goto nbf; |
/* |
* Allocate buffer if needed. */ |
if (buf == NULL) |
{ |
/* we need this here because malloc() may return a pointer |
even if size == 0 */ |
if (!size) size = BUFSIZ; |
if ((buf = malloc (size)) == NULL) |
{ |
ret = EOF; |
/* Try another size... */ |
buf = malloc (BUFSIZ); |
size = BUFSIZ; |
} |
if (buf == NULL) |
{ |
/* Can't allocate it, let's try another approach */ |
nbf: |
fp->_flags |= __SNBF; |
fp->_w = 0; |
fp->_bf._base = fp->_p = fp->_nbuf; |
fp->_bf._size = 1; |
_funlockfile (fp); |
return (ret); |
} |
fp->_flags |= __SMBF; |
} |
/* |
* Now put back whichever flag is needed, and fix _lbfsize |
* if line buffered. Ensure output flush on exit if the |
* stream will be buffered at all. |
* If buf is NULL then make _lbfsize 0 to force the buffer |
* to be flushed and hence malloced on first use |
*/ |
switch (mode) |
{ |
case _IOLBF: |
fp->_flags |= __SLBF; |
fp->_lbfsize = buf ? -size : 0; |
/* FALLTHROUGH */ |
case _IOFBF: |
/* no flag */ |
_REENT->__cleanup = _cleanup_r; |
fp->_bf._base = fp->_p = (unsigned char *) buf; |
fp->_bf._size = size; |
break; |
} |
/* |
* Patch up write count if necessary. |
*/ |
if (fp->_flags & __SWR) |
fp->_w = fp->_flags & (__SLBF | __SNBF) ? 0 : size; |
_funlockfile (fp); |
return 0; |
} |
/programs/develop/libraries/newlib/stdio/tmpfile.c |
---|
0,0 → 1,96 |
/* |
FUNCTION |
<<tmpfile>>---create a temporary file |
INDEX |
tmpfile |
INDEX |
_tmpfile_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
FILE *tmpfile(void); |
FILE *_tmpfile_r(struct _reent *<[reent]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
FILE *tmpfile(); |
FILE *_tmpfile_r(<[reent]>) |
struct _reent *<[reent]>; |
DESCRIPTION |
Create a temporary file (a file which will be deleted automatically), |
using a name generated by <<tmpnam>>. The temporary file is opened with |
the mode <<"wb+">>, permitting you to read and write anywhere in it |
as a binary file (without any data transformations the host system may |
perform for text files). |
The alternate function <<_tmpfile_r>> is a reentrant version. The |
argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<tmpfile>> normally returns a pointer to the temporary file. If no |
temporary file could be created, the result is NULL, and <<errno>> |
records the reason for failure. |
PORTABILITY |
Both ANSI C and the System V Interface Definition (Issue 2) require |
<<tmpfile>>. |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>, |
<<isatty>>, <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>. |
<<tmpfile>> also requires the global pointer <<environ>>. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <sys/stat.h> |
#ifndef O_BINARY |
# define O_BINARY 0 |
#endif |
FILE * |
_DEFUN(_tmpfile_r, (ptr), |
struct _reent *ptr) |
{ |
FILE *fp; |
int e; |
char *f; |
char buf[L_tmpnam]; |
int fd; |
do |
{ |
if ((f = _tmpnam_r (ptr, buf)) == NULL) |
return NULL; |
fd = _open_r (ptr, f, O_RDWR | O_CREAT | O_EXCL | O_BINARY, |
S_IRUSR | S_IWUSR); |
} |
while (fd < 0 && ptr->_errno == EEXIST); |
if (fd < 0) |
return NULL; |
fp = _fdopen_r (ptr, fd, "wb+"); |
e = ptr->_errno; |
if (!fp) |
_close_r (ptr, fd); |
_CAST_VOID _remove_r (ptr, f); |
ptr->_errno = e; |
return fp; |
} |
#ifndef _REENT_ONLY |
FILE * |
_DEFUN_VOID(tmpfile) |
{ |
return _tmpfile_r (_REENT); |
} |
#endif |
/programs/develop/libraries/newlib/stdio/tmpnam.c |
---|
0,0 → 1,209 |
/* |
* tmpname.c |
* Original Author: G. Haley |
*/ |
/* |
FUNCTION |
<<tmpnam>>, <<tempnam>>---name for a temporary file |
INDEX |
tmpnam |
INDEX |
tempnam |
INDEX |
_tmpnam_r |
INDEX |
_tempnam_r |
ANSI_SYNOPSIS |
#include <stdio.h> |
char *tmpnam(char *<[s]>); |
char *tempnam(char *<[dir]>, char *<[pfx]>); |
char *_tmpnam_r(struct _reent *<[reent]>, char *<[s]>); |
char *_tempnam_r(struct _reent *<[reent]>, char *<[dir]>, char *<[pfx]>); |
TRAD_SYNOPSIS |
#include <stdio.h> |
char *tmpnam(<[s]>) |
char *<[s]>; |
char *tempnam(<[dir]>, <[pfx]>) |
char *<[dir]>; |
char *<[pfx]>; |
char *_tmpnam_r(<[reent]>, <[s]>) |
struct _reent *<[reent]>; |
char *<[s]>; |
char *_tempnam_r(<[reent]>, <[dir]>, <[pfx]>) |
struct *<[reent]>; |
char *<[dir]>; |
char *<[pfx]>; |
DESCRIPTION |
Use either of these functions to generate a name for a temporary file. |
The generated name is guaranteed to avoid collision with other files |
(for up to <<TMP_MAX>> calls of either function). |
<<tmpnam>> generates file names with the value of <<P_tmpdir>> |
(defined in `<<stdio.h>>') as the leading directory component of the path. |
You can use the <<tmpnam>> argument <[s]> to specify a suitable area |
of memory for the generated filename; otherwise, you can call |
<<tmpnam(NULL)>> to use an internal static buffer. |
<<tempnam>> allows you more control over the generated filename: you |
can use the argument <[dir]> to specify the path to a directory for |
temporary files, and you can use the argument <[pfx]> to specify a |
prefix for the base filename. |
If <[dir]> is <<NULL>>, <<tempnam>> will attempt to use the value of |
environment variable <<TMPDIR>> instead; if there is no such value, |
<<tempnam>> uses the value of <<P_tmpdir>> (defined in `<<stdio.h>>'). |
If you don't need any particular prefix to the basename of temporary |
files, you can pass <<NULL>> as the <[pfx]> argument to <<tempnam>>. |
<<_tmpnam_r>> and <<_tempnam_r>> are reentrant versions of <<tmpnam>> |
and <<tempnam>> respectively. The extra argument <[reent]> is a |
pointer to a reentrancy structure. |
WARNINGS |
The generated filenames are suitable for temporary files, but do not |
in themselves make files temporary. Files with these names must still |
be explicitly removed when you no longer want them. |
If you supply your own data area <[s]> for <<tmpnam>>, you must ensure |
that it has room for at least <<L_tmpnam>> elements of type <<char>>. |
RETURNS |
Both <<tmpnam>> and <<tempnam>> return a pointer to the newly |
generated filename. |
PORTABILITY |
ANSI C requires <<tmpnam>>, but does not specify the use of |
<<P_tmpdir>>. The System V Interface Definition (Issue 2) requires |
both <<tmpnam>> and <<tempnam>>. |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>, |
<<isatty>>, <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>. |
The global pointer <<environ>> is also required. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <fcntl.h> |
#include <reent.h> |
#include <errno.h> |
/* Try to open the file specified, if it can't be opened then try |
another one. Return nonzero if successful, otherwise zero. */ |
static int |
_DEFUN(worker, (ptr, result, part1, part2, part3, part4), |
struct _reent *ptr _AND |
char *result _AND |
_CONST char *part1 _AND |
_CONST char *part2 _AND |
int part3 _AND |
int *part4) |
{ |
/* Generate the filename and make sure that there isn't one called |
it already. */ |
while (1) |
{ |
int t; |
_sprintf_r (ptr, result, "%s/%s%x.%x", part1, part2, part3, *part4); |
(*part4)++; |
t = _open_r (ptr, result, O_RDONLY, 0); |
if (t == -1) |
{ |
if (ptr->_errno == ENOSYS) |
{ |
result[0] = '\0'; |
return 0; |
} |
break; |
} |
_close_r (ptr, t); |
} |
return 1; |
} |
char * |
_DEFUN(_tmpnam_r, (p, s), |
struct _reent *p _AND |
char *s) |
{ |
char *result; |
int pid; |
if (s == NULL) |
{ |
/* ANSI states we must use an internal static buffer if s is NULL */ |
_REENT_CHECK_EMERGENCY(p); |
result = _REENT_EMERGENCY(p); |
} |
else |
{ |
result = s; |
} |
pid = _getpid_r (p); |
if (worker (p, result, P_tmpdir, "t", pid, &p->_inc)) |
{ |
p->_inc++; |
return result; |
} |
return NULL; |
} |
char * |
_DEFUN(_tempnam_r, (p, dir, pfx), |
struct _reent *p _AND |
_CONST char *dir _AND |
_CONST char *pfx) |
{ |
char *filename; |
int length; |
_CONST char *prefix = (pfx) ? pfx : ""; |
if (dir == NULL && (dir = getenv ("TMPDIR")) == NULL) |
dir = P_tmpdir; |
/* two 8 digit numbers + . / */ |
length = strlen (dir) + strlen (prefix) + (4 * sizeof (int)) + 2 + 1; |
filename = _malloc_r (p, length); |
if (filename) |
{ |
if (! worker (p, filename, dir, prefix, |
_getpid_r (p) ^ (int) (_POINTER_INT) p, &p->_inc)) |
return NULL; |
} |
return filename; |
} |
#ifndef _REENT_ONLY |
char * |
_DEFUN(tempnam, (dir, pfx), |
_CONST char *dir _AND |
_CONST char *pfx) |
{ |
return _tempnam_r (_REENT, dir, pfx); |
} |
char * |
_DEFUN(tmpnam, (s), |
char *s) |
{ |
return _tmpnam_r (_REENT, s); |
} |
#endif |
/programs/develop/libraries/newlib/stdio/vscanf.c |
---|
0,0 → 1,52 |
/*- |
* Code created by modifying scanf.c which has following copyright. |
* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#ifdef _HAVE_STDC |
#include <stdarg.h> |
#else |
#include <varargs.h> |
#endif |
#include "local.h" |
#ifndef _REENT_ONLY |
int |
_DEFUN(vscanf, (fmt, ap), |
_CONST char *fmt _AND |
va_list ap) |
{ |
_REENT_SMALL_CHECK_INIT (_REENT); |
return __svfscanf_r (_REENT, _stdin_r (_REENT), fmt, ap); |
} |
#endif /* !_REENT_ONLY */ |
int |
_DEFUN(_vscanf_r, (ptr, fmt, ap), |
struct _reent *ptr _AND |
_CONST char *fmt _AND |
va_list ap) |
{ |
_REENT_SMALL_CHECK_INIT (ptr); |
return __svfscanf_r (ptr, _stdin_r (ptr), fmt, ap); |
} |
/programs/develop/libraries/newlib/stdio/vsscanf.c |
---|
0,0 → 1,65 |
/* |
* Code created by modifying scanf.c which has following copyright. |
* |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that the above copyright notice and this paragraph are |
* duplicated in all such forms and that any documentation, |
* advertising materials, and other materials related to such |
* distribution and use acknowledge that the software was developed |
* by the University of California, Berkeley. The name of the |
* University may not be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#include <string.h> |
#ifdef _HAVE_STDC |
#include <stdarg.h> |
#else |
#include <varargs.h> |
#endif |
#include "local.h" |
/* |
* vsscanf |
*/ |
#ifndef _REENT_ONLY |
int |
_DEFUN(vsscanf, (str, fmt, ap), |
_CONST char *str _AND |
_CONST char *fmt _AND |
va_list ap) |
{ |
return _vsscanf_r (_REENT, str, fmt, ap); |
} |
#endif /* !_REENT_ONLY */ |
int |
_DEFUN(_vsscanf_r, (ptr, str, fmt, ap), |
struct _reent *ptr _AND |
_CONST char *str _AND |
_CONST char *fmt _AND |
va_list ap) |
{ |
FILE f; |
f._flags = __SRD | __SSTR; |
f._bf._base = f._p = (unsigned char *) str; |
f._bf._size = f._r = strlen (str); |
f._read = __seofread; |
f._ub._base = NULL; |
f._lb._base = NULL; |
f._file = -1; /* No file. */ |
return __ssvfscanf_r (ptr, &f, fmt, ap); |
} |
/programs/develop/libraries/newlib/stdlib/mallocr1.c |
---|
File deleted |
/programs/develop/libraries/newlib/stdlib/__atexit.c |
---|
0,0 → 1,99 |
/* |
* Common routine to implement atexit-like functionality. |
*/ |
#include <stddef.h> |
#include <stdlib.h> |
#include <reent.h> |
#include <sys/lock.h> |
#include "atexit.h" |
/* Make this a weak reference to avoid pulling in malloc. */ |
void * malloc(size_t) _ATTRIBUTE((__weak__)); |
__LOCK_INIT_RECURSIVE(, __atexit_lock); |
/* |
* Register a function to be performed at exit or on shared library unload. |
*/ |
int |
_DEFUN (__register_exitproc, |
(type, fn, arg, d), |
int type _AND |
void (*fn) (void) _AND |
void *arg _AND |
void *d) |
{ |
struct _on_exit_args * args; |
register struct _atexit *p; |
#ifndef __SINGLE_THREAD__ |
__lock_acquire_recursive(__atexit_lock); |
#endif |
p = _GLOBAL_REENT->_atexit; |
if (p == NULL) |
_GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0; |
if (p->_ind >= _ATEXIT_SIZE) |
{ |
#ifndef _ATEXIT_DYNAMIC_ALLOC |
return -1; |
#else |
/* Don't dynamically allocate the atexit array if malloc is not |
available. */ |
if (!malloc) |
return -1; |
p = (struct _atexit *) malloc (sizeof *p); |
if (p == NULL) |
{ |
#ifndef __SINGLE_THREAD__ |
__lock_release_recursive(__atexit_lock); |
#endif |
return -1; |
} |
p->_ind = 0; |
p->_next = _GLOBAL_REENT->_atexit; |
_GLOBAL_REENT->_atexit = p; |
#ifndef _REENT_SMALL |
p->_on_exit_args._fntypes = 0; |
p->_on_exit_args._is_cxa = 0; |
#endif |
#endif |
} |
if (type != __et_atexit) |
{ |
#ifdef _REENT_SMALL |
args = p->_on_exit_args_ptr; |
if (args == NULL) |
{ |
if (malloc) |
args = malloc (sizeof * p->_on_exit_args_ptr); |
if (args == NULL) |
{ |
#ifndef __SINGLE_THREAD__ |
__lock_release(lock); |
#endif |
return -1; |
} |
args->_fntypes = 0; |
args->_is_cxa = 0; |
p->_on_exit_args_ptr = args; |
} |
#else |
args = &p->_on_exit_args; |
#endif |
args->_fnargs[p->_ind] = arg; |
args->_fntypes |= (1 << p->_ind); |
args->_dso_handle[p->_ind] = d; |
if (type == __et_cxa) |
args->_is_cxa |= (1 << p->_ind); |
} |
p->_fns[p->_ind++] = fn; |
#ifndef __SINGLE_THREAD__ |
__lock_release_recursive(__atexit_lock); |
#endif |
return 0; |
} |
/programs/develop/libraries/newlib/stdlib/__call_atexit.c |
---|
0,0 → 1,161 |
/* |
* COmmon routine to call call registered atexit-like routines. |
*/ |
#include <stdlib.h> |
#include <reent.h> |
#include <sys/lock.h> |
#include "atexit.h" |
/* Make this a weak reference to avoid pulling in free. */ |
void free(void *) _ATTRIBUTE((__weak__)); |
#ifndef __SINGLE_THREAD__ |
extern _LOCK_RECURSIVE_T __atexit_lock; |
#endif |
#ifdef _WANT_REGISTER_FINI |
/* If "__libc_fini" is defined, finalizers (either |
"__libc_fini_array", or "_fini", as appropriate) will be run after |
all user-specified atexit handlers. For example, you can define |
"__libc_fini" to "_fini" in your linker script if you want the C |
library, rather than startup code, to register finalizers. If you |
do that, then your startup code need not contain references to |
"atexit" or "exit". As a result, only applications that reference |
"exit" explicitly will pull in finalization code. |
The choice of whether to register finalizers from libc or from |
startup code is deferred to link-time, rather than being a |
configure-time option, so that the same C library binary can be |
used with multiple BSPs, some of which register finalizers from |
startup code, while others defer to the C library. */ |
extern char __libc_fini __attribute__((weak)); |
/* Register the application finalization function with atexit. These |
finalizers should run last. Therefore, we want to call atexit as |
soon as possible. */ |
static void |
register_fini(void) __attribute__((constructor (0))); |
static void |
register_fini(void) |
{ |
if (&__libc_fini) { |
#ifdef HAVE_INITFINI_ARRAY |
extern void __libc_fini_array (void); |
atexit (__libc_fini_array); |
#else |
extern void _fini (void); |
atexit (_fini); |
#endif |
} |
} |
#endif /* _WANT_REGISTER_FINI */ |
/* |
* Call registered exit handlers. If D is null then all handlers are called, |
* otherwise only the handlers from that DSO are called. |
*/ |
void |
_DEFUN (__call_exitprocs, (code, d), |
int code _AND _PTR d) |
{ |
register struct _atexit *p; |
struct _atexit **lastp; |
register struct _on_exit_args * args; |
register int n; |
int i; |
void (*fn) (void); |
#ifndef __SINGLE_THREAD__ |
__lock_acquire_recursive(__atexit_lock); |
#endif |
restart: |
p = _GLOBAL_REENT->_atexit; |
lastp = &_GLOBAL_REENT->_atexit; |
while (p) |
{ |
#ifdef _REENT_SMALL |
args = p->_on_exit_args_ptr; |
#else |
args = &p->_on_exit_args; |
#endif |
for (n = p->_ind - 1; n >= 0; n--) |
{ |
int ind; |
i = 1 << n; |
/* Skip functions not from this dso. */ |
if (d && (!args || args->_dso_handle[n] != d)) |
continue; |
/* Remove the function now to protect against the |
function calling exit recursively. */ |
fn = p->_fns[n]; |
if (n == p->_ind - 1) |
p->_ind--; |
else |
p->_fns[n] = NULL; |
/* Skip functions that have already been called. */ |
if (!fn) |
continue; |
ind = p->_ind; |
/* Call the function. */ |
if (!args || (args->_fntypes & i) == 0) |
fn (); |
else if ((args->_is_cxa & i) == 0) |
(*((void (*)(int, _PTR)) fn))(code, args->_fnargs[n]); |
else |
(*((void (*)(_PTR)) fn))(args->_fnargs[n]); |
/* The function we called call atexit and registered another |
function (or functions). Call these new functions before |
continuing with the already registered functions. */ |
if (ind != p->_ind || *lastp != p) |
goto restart; |
} |
#ifndef _ATEXIT_DYNAMIC_ALLOC |
break; |
#else |
/* Don't dynamically free the atexit array if free is not |
available. */ |
if (!free) |
break; |
/* Move to the next block. Free empty blocks except the last one, |
which is part of _GLOBAL_REENT. */ |
if (p->_ind == 0 && p->_next) |
{ |
/* Remove empty block from the list. */ |
*lastp = p->_next; |
#ifdef _REENT_SMALL |
if (args) |
free (args); |
#endif |
free (p); |
p = *lastp; |
} |
else |
{ |
lastp = &p->_next; |
p = p->_next; |
} |
#endif |
} |
#ifndef __SINGLE_THREAD__ |
__lock_release_recursive(__atexit_lock); |
#endif |
} |
/programs/develop/libraries/newlib/stdlib/atof.c |
---|
0,0 → 1,72 |
/* |
FUNCTION |
<<atof>>, <<atoff>>---string to double or float |
INDEX |
atof |
INDEX |
atoff |
ANSI_SYNOPSIS |
#include <stdlib.h> |
double atof(const char *<[s]>); |
float atoff(const char *<[s]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
double atof(<[s]>) |
char *<[s]>; |
float atoff(<[s]>) |
char *<[s]>; |
DESCRIPTION |
<<atof>> converts the initial portion of a string to a <<double>>. |
<<atoff>> converts the initial portion of a string to a <<float>>. |
The functions parse the character string <[s]>, |
locating a substring which can be converted to a floating-point |
value. The substring must match the format: |
. [+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>] |
The substring converted is the longest initial |
fragment of <[s]> that has the expected format, beginning with |
the first non-whitespace character. The substring |
is empty if <<str>> is empty, consists entirely |
of whitespace, or if the first non-whitespace character is |
something other than <<+>>, <<->>, <<.>>, or a digit. |
<<atof(<[s]>)>> is implemented as <<strtod(<[s]>, NULL)>>. |
<<atoff(<[s]>)>> is implemented as <<strtof(<[s]>, NULL)>>. |
RETURNS |
<<atof>> returns the converted substring value, if any, as a |
<<double>>; or <<0.0>>, if no conversion could be performed. |
If the correct value is out of the range of representable values, plus |
or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is stored in |
<<errno>>. |
If the correct value would cause underflow, <<0.0>> is returned |
and <<ERANGE>> is stored in <<errno>>. |
<<atoff>> obeys the same rules as <<atof>>, except that it |
returns a <<float>>. |
PORTABILITY |
<<atof>> is ANSI C. <<atof>>, <<atoi>>, and <<atol>> are subsumed by <<strod>> |
and <<strol>>, but are used extensively in existing code. These functions are |
less reliable, but may be faster if the argument is verified to be in a valid |
range. |
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. |
*/ |
#include <stdlib.h> |
#include <_ansi.h> |
double |
_DEFUN (atof, (s), |
_CONST char *s) |
{ |
return strtod (s, NULL); |
} |
/programs/develop/libraries/newlib/stdlib/div.c |
---|
0,0 → 1,132 |
/* |
FUNCTION |
<<div>>---divide two integers |
INDEX |
div |
ANSI_SYNOPSIS |
#include <stdlib.h> |
div_t div(int <[n]>, int <[d]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
div_t div(<[n]>, <[d]>) |
int <[n]>, <[d]>; |
DESCRIPTION |
Divide |
@tex |
$n/d$, |
@end tex |
@ifnottex |
<[n]>/<[d]>, |
@end ifnottex |
returning quotient and remainder as two integers in a structure <<div_t>>. |
RETURNS |
The result is represented with the structure |
. typedef struct |
. { |
. int quot; |
. int rem; |
. } div_t; |
where the <<quot>> field represents the quotient, and <<rem>> the |
remainder. For nonzero <[d]>, if `<<<[r]> = div(<[n]>,<[d]>);>>' then |
<[n]> equals `<<<[r]>.rem + <[d]>*<[r]>.quot>>'. |
To divide <<long>> rather than <<int>> values, use the similar |
function <<ldiv>>. |
PORTABILITY |
<<div>> is ANSI. |
No supporting OS subroutines are required. |
*/ |
/* |
* Copyright (c) 1990 Regents of the University of California. |
* All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <_ansi.h> |
#include <stdlib.h> /* div_t */ |
div_t |
_DEFUN (div, (num, denom), |
int num _AND |
int denom) |
{ |
div_t r; |
r.quot = num / denom; |
r.rem = num % denom; |
/* |
* The ANSI standard says that |r.quot| <= |n/d|, where |
* n/d is to be computed in infinite precision. In other |
* words, we should always truncate the quotient towards |
* 0, never -infinity or +infinity. |
* |
* Machine division and remainer may work either way when |
* one or both of n or d is negative. If only one is |
* negative and r.quot has been truncated towards -inf, |
* r.rem will have the same sign as denom and the opposite |
* sign of num; if both are negative and r.quot has been |
* truncated towards -inf, r.rem will be positive (will |
* have the opposite sign of num). These are considered |
* `wrong'. |
* |
* If both are num and denom are positive, r will always |
* be positive. |
* |
* This all boils down to: |
* if num >= 0, but r.rem < 0, we got the wrong answer. |
* In that case, to get the right answer, add 1 to r.quot and |
* subtract denom from r.rem. |
* if num < 0, but r.rem > 0, we also have the wrong answer. |
* In this case, to get the right answer, subtract 1 from r.quot and |
* add denom to r.rem. |
*/ |
if (num >= 0 && r.rem < 0) { |
++r.quot; |
r.rem -= denom; |
} |
else if (num < 0 && r.rem > 0) { |
--r.quot; |
r.rem += denom; |
} |
return (r); |
} |
/programs/develop/libraries/newlib/stdlib/exit.c |
---|
0,0 → 1,66 |
/* |
* Copyright (c) 1990 Regents of the University of California. |
* All rights reserved. |
* |
* %sccs.include.redist.c% |
*/ |
/* |
FUNCTION |
<<exit>>---end program execution |
INDEX |
exit |
ANSI_SYNOPSIS |
#include <stdlib.h> |
void exit(int <[code]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
void exit(<[code]>) |
int <[code]>; |
DESCRIPTION |
Use <<exit>> to return control from a program to the host operating |
environment. Use the argument <[code]> to pass an exit status to the |
operating environment: two particular values, <<EXIT_SUCCESS>> and |
<<EXIT_FAILURE>>, are defined in `<<stdlib.h>>' to indicate success or |
failure in a portable fashion. |
<<exit>> does two kinds of cleanup before ending execution of your |
program. First, it calls all application-defined cleanup functions |
you have enrolled with <<atexit>>. Second, files and streams are |
cleaned up: any pending output is delivered to the host system, each |
open file or stream is closed, and files created by <<tmpfile>> are |
deleted. |
RETURNS |
<<exit>> does not return to its caller. |
PORTABILITY |
ANSI C requires <<exit>>, and specifies that <<EXIT_SUCCESS>> and |
<<EXIT_FAILURE>> must be defined. |
Supporting OS subroutines required: <<_exit>>. |
*/ |
#include <stdlib.h> |
#include <unistd.h> /* for _exit() declaration */ |
#include <reent.h> |
#include "atexit.h" |
/* |
* Exit, flushing stdio buffers if necessary. |
*/ |
void |
_DEFUN (exit, (code), |
int code) |
{ |
__call_exitprocs (code, NULL); |
if (_GLOBAL_REENT->__cleanup) |
(*_GLOBAL_REENT->__cleanup) (_GLOBAL_REENT); |
_exit (code); |
} |
/programs/develop/libraries/newlib/stdlib/getenv.c |
---|
0,0 → 1,93 |
/* |
FUNCTION |
<<getenv>>---look up environment variable |
INDEX |
getenv |
INDEX |
environ |
ANSI_SYNOPSIS |
#include <stdlib.h> |
char *getenv(const char *<[name]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
char *getenv(<[name]>) |
char *<[name]>; |
DESCRIPTION |
<<getenv>> searches the list of environment variable names and values |
(using the global pointer ``<<char **environ>>'') for a variable whose |
name matches the string at <[name]>. If a variable name matches, |
<<getenv>> returns a pointer to the associated value. |
RETURNS |
A pointer to the (string) value of the environment variable, or |
<<NULL>> if there is no such environment variable. |
PORTABILITY |
<<getenv>> is ANSI, but the rules for properly forming names of environment |
variables vary from one system to another. |
<<getenv>> requires a global pointer <<environ>>. |
*/ |
/* |
* Copyright (c) 1987, 2000 Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms are permitted |
* provided that: (1) source distributions retain this entire copyright |
* notice and comment, and (2) distributions including binaries display |
* the following acknowledgement: ``This product includes software |
* developed by the University of California, Berkeley and its contributors'' |
* in the documentation or other materials provided with the distribution |
* and in all advertising materials mentioning features or use of this |
* software. Neither the name of the University nor the names of its |
* contributors may be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
*/ |
#ifndef _REENT_ONLY |
#include <stdlib.h> |
#include <stddef.h> |
#include <string.h> |
/* |
* _findenv -- |
* Returns pointer to value associated with name, if any, else NULL. |
* Sets offset to be the offset of the name/value combination in the |
* environmental array, for use by setenv(3) and unsetenv(3). |
* Explicitly removes '=' in argument name. |
* |
* This routine *should* be a static; don't use it. |
*/ |
char * |
_DEFUN (_findenv, (name, offset), |
register _CONST char *name _AND |
int *offset) |
{ |
return NULL; //_findenv_r (_REENT, name, offset); |
} |
/* |
* getenv -- |
* Returns ptr to value associated with name, if any, else NULL. |
*/ |
char * |
_DEFUN (getenv, (name), |
_CONST char *name) |
{ |
int offset; |
return NULL; //_findenv_r (_REENT, name, &offset); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/stdlib/rand.c |
---|
0,0 → 1,91 |
/* |
FUNCTION |
<<rand>>, <<srand>>---pseudo-random numbers |
INDEX |
rand |
INDEX |
srand |
INDEX |
rand_r |
ANSI_SYNOPSIS |
#include <stdlib.h> |
int rand(void); |
void srand(unsigned int <[seed]>); |
int rand_r(unsigned int *<[seed]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
int rand(); |
void srand(<[seed]>) |
unsigned int <[seed]>; |
void rand_r(<[seed]>) |
unsigned int *<[seed]>; |
DESCRIPTION |
<<rand>> returns a different integer each time it is called; each |
integer is chosen by an algorithm designed to be unpredictable, so |
that you can use <<rand>> when you require a random number. |
The algorithm depends on a static variable called the ``random seed''; |
starting with a given value of the random seed always produces the |
same sequence of numbers in successive calls to <<rand>>. |
You can set the random seed using <<srand>>; it does nothing beyond |
storing its argument in the static variable used by <<rand>>. You can |
exploit this to make the pseudo-random sequence less predictable, if |
you wish, by using some other unpredictable value (often the least |
significant parts of a time-varying value) as the random seed before |
beginning a sequence of calls to <<rand>>; or, if you wish to ensure |
(for example, while debugging) that successive runs of your program |
use the same ``random'' numbers, you can use <<srand>> to set the same |
random seed at the outset. |
RETURNS |
<<rand>> returns the next pseudo-random integer in sequence; it is a |
number between <<0>> and <<RAND_MAX>> (inclusive). |
<<srand>> does not return a result. |
NOTES |
<<rand>> and <<srand>> are unsafe for multi-threaded applications. |
<<rand_r>> is thread-safe and should be used instead. |
PORTABILITY |
<<rand>> is required by ANSI, but the algorithm for pseudo-random |
number generation is not specified; therefore, even if you use |
the same random seed, you cannot expect the same sequence of results |
on two different systems. |
<<rand>> requires no supporting OS subroutines. |
*/ |
#ifndef _REENT_ONLY |
#include <stdlib.h> |
#include <reent.h> |
void |
_DEFUN (srand, (seed), unsigned int seed) |
{ |
_REENT_CHECK_RAND48(_REENT); |
_REENT_RAND_NEXT(_REENT) = seed; |
} |
int |
_DEFUN_VOID (rand) |
{ |
/* This multiplier was obtained from Knuth, D.E., "The Art of |
Computer Programming," Vol 2, Seminumerical Algorithms, Third |
Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 */ |
_REENT_CHECK_RAND48(_REENT); |
_REENT_RAND_NEXT(_REENT) = |
_REENT_RAND_NEXT(_REENT) * __extension__ 6364136223846793005LL + 1; |
return (int)((_REENT_RAND_NEXT(_REENT) >> 32) & RAND_MAX); |
} |
#endif /* _REENT_ONLY */ |
/programs/develop/libraries/newlib/stdlib/rand48.c |
---|
0,0 → 1,179 |
/* |
* Copyright (c) 1993 Martin Birgmeier |
* All rights reserved. |
* |
* You may redistribute unmodified or modified versions of this source |
* code provided that the above copyright notice and this and the |
* following conditions are retained. |
* |
* This software is provided ``as is'', and comes with no warranties |
* of any kind. I shall in no event be liable for anything that happens |
* to anyone/anything when using this software. |
*/ |
/* |
FUNCTION |
<<rand48>>, <<drand48>>, <<erand48>>, <<lrand48>>, <<nrand48>>, <<mrand48>>, <<jrand48>>, <<srand48>>, <<seed48>>, <<lcong48>>---pseudo-random number generators and initialization routines |
INDEX |
rand48 |
INDEX |
drand48 |
INDEX |
erand48 |
INDEX |
lrand48 |
INDEX |
nrand48 |
INDEX |
mrand48 |
INDEX |
jrand48 |
INDEX |
srand48 |
INDEX |
seed48 |
INDEX |
lcong48 |
ANSI_SYNOPSIS |
#include <stdlib.h> |
double drand48(void); |
double erand48(unsigned short <[xseed]>[3]); |
long lrand48(void); |
long nrand48(unsigned short <[xseed]>[3]); |
long mrand48(void); |
long jrand48(unsigned short <[xseed]>[3]); |
void srand48(long <[seed]>); |
unsigned short *seed48(unsigned short <[xseed]>[3]); |
void lcong48(unsigned short <[p]>[7]); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
double drand48(); |
double erand48(<[xseed]>) |
unsigned short <[xseed]>[3]; |
long lrand48(); |
long nrand48(<[xseed]>) |
unsigned short <[xseed]>[3]; |
long mrand48(); |
long jrand48(<[xseed]>) |
unsigned short <[xseed]>[3]; |
void srand48(<[seed]>) |
long <[seed]>; |
unsigned short *seed48(<[xseed]>) |
unsigned short <[xseed]>[3]; |
void lcong48(<[p]>) |
unsigned short <[p]>[7]; |
DESCRIPTION |
The <<rand48>> family of functions generates pseudo-random numbers |
using a linear congruential algorithm working on integers 48 bits in size. |
The particular formula employed is |
r(n+1) = (a * r(n) + c) mod m |
where the default values are |
for the multiplicand a = 0xfdeece66d = 25214903917 and |
the addend c = 0xb = 11. The modulo is always fixed at m = 2 ** 48. |
r(n) is called the seed of the random number generator. |
For all the six generator routines described next, the first |
computational step is to perform a single iteration of the algorithm. |
<<drand48>> and <<erand48>> |
return values of type double. The full 48 bits of r(n+1) are |
loaded into the mantissa of the returned value, with the exponent set |
such that the values produced lie in the interval [0.0, 1.0]. |
<<lrand48>> and <<nrand48>> |
return values of type long in the range |
[0, 2**31-1]. The high-order (31) bits of |
r(n+1) are loaded into the lower bits of the returned value, with |
the topmost (sign) bit set to zero. |
<<mrand48>> and <<jrand48>> |
return values of type long in the range |
[-2**31, 2**31-1]. The high-order (32) bits of |
r(n+1) are loaded into the returned value. |
<<drand48>>, <<lrand48>>, and <<mrand48>> |
use an internal buffer to store r(n). For these functions |
the initial value of r(0) = 0x1234abcd330e = 20017429951246. |
On the other hand, <<erand48>>, <<nrand48>>, and <<jrand48>> |
use a user-supplied buffer to store the seed r(n), |
which consists of an array of 3 shorts, where the zeroth member |
holds the least significant bits. |
All functions share the same multiplicand and addend. |
<<srand48>> is used to initialize the internal buffer r(n) of |
<<drand48>>, <<lrand48>>, and <<mrand48>> |
such that the 32 bits of the seed value are copied into the upper 32 bits |
of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e. |
Additionally, the constant multiplicand and addend of the algorithm are |
reset to the default values given above. |
<<seed48>> also initializes the internal buffer r(n) of |
<<drand48>>, <<lrand48>>, and <<mrand48>>, |
but here all 48 bits of the seed can be specified in an array of 3 shorts, |
where the zeroth member specifies the lowest bits. Again, |
the constant multiplicand and addend of the algorithm are |
reset to the default values given above. |
<<seed48>> returns a pointer to an array of 3 shorts which contains |
the old seed. |
This array is statically allocated, thus its contents are lost after |
each new call to <<seed48>>. |
Finally, <<lcong48>> allows full control over the multiplicand and |
addend used in <<drand48>>, <<erand48>>, <<lrand48>>, <<nrand48>>, |
<<mrand48>>, and <<jrand48>>, |
and the seed used in <<drand48>>, <<lrand48>>, and <<mrand48>>. |
An array of 7 shorts is passed as parameter; the first three shorts are |
used to initialize the seed; the second three are used to initialize the |
multiplicand; and the last short is used to initialize the addend. |
It is thus not possible to use values greater than 0xffff as the addend. |
Note that all three methods of seeding the random number generator |
always also set the multiplicand and addend for any of the six |
generator calls. |
For a more powerful random number generator, see <<random>>. |
PORTABILITY |
SUS requires these functions. |
No supporting OS subroutines are required. |
*/ |
#include "rand48.h" |
void |
_DEFUN (__dorand48, (r, xseed), |
struct _reent *r _AND |
unsigned short xseed[3]) |
{ |
unsigned long accu; |
unsigned short temp[2]; |
_REENT_CHECK_RAND48(r); |
accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0] + |
(unsigned long) __rand48_add; |
temp[0] = (unsigned short) accu; /* lower 16 bits */ |
accu >>= sizeof(unsigned short) * 8; |
accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1] + |
(unsigned long) __rand48_mult[1] * (unsigned long) xseed[0]; |
temp[1] = (unsigned short) accu; /* middle 16 bits */ |
accu >>= sizeof(unsigned short) * 8; |
accu += __rand48_mult[0] * xseed[2] + __rand48_mult[1] * xseed[1] + __rand48_mult[2] * xseed[0]; |
xseed[0] = temp[0]; |
xseed[1] = temp[1]; |
xseed[2] = (unsigned short) accu; |
} |
/programs/develop/libraries/newlib/stdlib/rand_r.c |
---|
0,0 → 1,37 |
#include <stdlib.h> |
/* Pseudo-random generator based on Minimal Standard by |
Lewis, Goodman, and Miller in 1969. |
I[j+1] = a*I[j] (mod m) |
where a = 16807 |
m = 2147483647 |
Using Schrage's algorithm, a*I[j] (mod m) can be rewritten as: |
a*(I[j] mod q) - r*{I[j]/q} if >= 0 |
a*(I[j] mod q) - r*{I[j]/q} + m otherwise |
where: {} denotes integer division |
q = {m/a} = 127773 |
r = m (mod a) = 2836 |
note that the seed value of 0 cannot be used in the calculation as |
it results in 0 itself |
*/ |
int |
_DEFUN (rand_r, (seed), unsigned int *seed) |
{ |
long k; |
long s = (long)(*seed); |
if (s == 0) |
s = 0x12345987; |
k = s / 127773; |
s = 16807 * (s - k * 127773) - 2836 * k; |
if (s < 0) |
s += 2147483647; |
(*seed) = (unsigned int)s; |
return (int)(s & RAND_MAX); |
} |
/programs/develop/libraries/newlib/stdlib/seed48.c |
---|
0,0 → 1,44 |
/* |
* Copyright (c) 1993 Martin Birgmeier |
* All rights reserved. |
* |
* You may redistribute unmodified or modified versions of this source |
* code provided that the above copyright notice and this and the |
* following conditions are retained. |
* |
* This software is provided ``as is'', and comes with no warranties |
* of any kind. I shall in no event be liable for anything that happens |
* to anyone/anything when using this software. |
*/ |
#include "rand48.h" |
unsigned short * |
_DEFUN (_seed48_r, (r, xseed), |
struct _reent *r _AND |
unsigned short xseed[3]) |
{ |
static unsigned short sseed[3]; |
_REENT_CHECK_RAND48(r); |
sseed[0] = __rand48_seed[0]; |
sseed[1] = __rand48_seed[1]; |
sseed[2] = __rand48_seed[2]; |
__rand48_seed[0] = xseed[0]; |
__rand48_seed[1] = xseed[1]; |
__rand48_seed[2] = xseed[2]; |
__rand48_mult[0] = _RAND48_MULT_0; |
__rand48_mult[1] = _RAND48_MULT_1; |
__rand48_mult[2] = _RAND48_MULT_2; |
__rand48_add = _RAND48_ADD; |
return sseed; |
} |
#ifndef _REENT_ONLY |
unsigned short * |
_DEFUN (seed48, (xseed), |
unsigned short xseed[3]) |
{ |
return _seed48_r (_REENT, xseed); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/stdlib/srand48.c |
---|
0,0 → 1,38 |
/* |
* Copyright (c) 1993 Martin Birgmeier |
* All rights reserved. |
* |
* You may redistribute unmodified or modified versions of this source |
* code provided that the above copyright notice and this and the |
* following conditions are retained. |
* |
* This software is provided ``as is'', and comes with no warranties |
* of any kind. I shall in no event be liable for anything that happens |
* to anyone/anything when using this software. |
*/ |
#include "rand48.h" |
_VOID |
_DEFUN (_srand48_r, (r, seed), |
struct _reent *r _AND |
long seed) |
{ |
_REENT_CHECK_RAND48(r); |
__rand48_seed[0] = _RAND48_SEED_0; |
__rand48_seed[1] = (unsigned short) seed; |
__rand48_seed[2] = (unsigned short) ((unsigned long)seed >> 16); |
__rand48_mult[0] = _RAND48_MULT_0; |
__rand48_mult[1] = _RAND48_MULT_1; |
__rand48_mult[2] = _RAND48_MULT_2; |
__rand48_add = _RAND48_ADD; |
} |
#ifndef _REENT_ONLY |
_VOID |
_DEFUN (srand48, (seed), |
long seed) |
{ |
_srand48_r (_REENT, seed); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/stdlib/strtold.c |
---|
0,0 → 1,42 |
/* |
(C) Copyright IBM Corp. 2009 |
All rights reserved. |
Redistribution and use in source and binary forms, with or without |
modification, are permitted provided that the following conditions are met: |
* Redistributions of source code must retain the above copyright notice, |
this list of conditions and the following disclaimer. |
* Redistributions in binary form must reproduce the above copyright |
notice, this list of conditions and the following disclaimer in the |
documentation and/or other materials provided with the distribution. |
* Neither the name of IBM nor the names of its contributors may be |
used to endorse or promote products derived from this software without |
specific prior written permission. |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdlib.h> |
#include "local.h" |
/* On platforms where long double is as wide as double. */ |
#ifdef _LDBL_EQ_DBL |
long double |
strtold (const char *s00, char **se) |
{ |
return strtod(s00, se); |
} |
#endif /* _LDBL_EQ_DBL */ |
/programs/develop/libraries/newlib/stdlib/strtoll.c |
---|
0,0 → 1,138 |
/* |
FUNCTION |
<<strtoll>>---string to long long |
INDEX |
strtoll |
INDEX |
_strtoll_r |
ANSI_SYNOPSIS |
#include <stdlib.h> |
long long strtoll(const char *<[s]>, char **<[ptr]>,int <[base]>); |
long long _strtoll_r(void *<[reent]>, |
const char *<[s]>, char **<[ptr]>,int <[base]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
long long strtoll (<[s]>, <[ptr]>, <[base]>) |
const char *<[s]>; |
char **<[ptr]>; |
int <[base]>; |
long long _strtoll_r (<[reent]>, <[s]>, <[ptr]>, <[base]>) |
char *<[reent]>; |
const char *<[s]>; |
char **<[ptr]>; |
int <[base]>; |
DESCRIPTION |
The function <<strtoll>> converts the string <<*<[s]>>> to |
a <<long long>>. First, it breaks down the string into three parts: |
leading whitespace, which is ignored; a subject string consisting |
of characters resembling an integer in the radix specified by <[base]>; |
and a trailing portion consisting of zero or more unparseable characters, |
and always including the terminating null character. Then, it attempts |
to convert the subject string into a <<long long>> and returns the |
result. |
If the value of <[base]> is 0, the subject string is expected to look |
like a normal C integer constant: an optional sign, a possible `<<0x>>' |
indicating a hexadecimal base, and a number. If <[base]> is between |
2 and 36, the expected form of the subject is a sequence of letters |
and digits representing an integer in the radix specified by <[base]>, |
with an optional plus or minus sign. The letters <<a>>--<<z>> (or, |
equivalently, <<A>>--<<Z>>) are used to signify values from 10 to 35; |
only letters whose ascribed values are less than <[base]> are |
permitted. If <[base]> is 16, a leading <<0x>> is permitted. |
The subject sequence is the longest initial sequence of the input |
string that has the expected form, starting with the first |
non-whitespace character. If the string is empty or consists entirely |
of whitespace, or if the first non-whitespace character is not a |
permissible letter or digit, the subject string is empty. |
If the subject string is acceptable, and the value of <[base]> is zero, |
<<strtoll>> attempts to determine the radix from the input string. A |
string with a leading <<0x>> is treated as a hexadecimal value; a string with |
a leading 0 and no <<x>> is treated as octal; all other strings are |
treated as decimal. If <[base]> is between 2 and 36, it is used as the |
conversion radix, as described above. If the subject string begins with |
a minus sign, the value is negated. Finally, a pointer to the first |
character past the converted subject string is stored in <[ptr]>, if |
<[ptr]> is not <<NULL>>. |
If the subject string is empty (or not in acceptable form), no conversion |
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is |
not <<NULL>>). |
The alternate function <<_strtoll_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<strtoll>> returns the converted value, if any. If no conversion was |
made, 0 is returned. |
<<strtoll>> returns <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>> if the magnitude of |
the converted value is too large, and sets <<errno>> to <<ERANGE>>. |
PORTABILITY |
<<strtoll>> is ANSI. |
No supporting OS subroutines are required. |
*/ |
/*- |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <_ansi.h> |
#include <limits.h> |
#include <ctype.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <reent.h> |
#ifndef _REENT_ONLY |
long long |
_DEFUN (strtoll, (s, ptr, base), |
_CONST char *s _AND |
char **ptr _AND |
int base) |
{ |
return _strtoll_r (_REENT, s, ptr, base); |
} |
#endif |
/programs/develop/libraries/newlib/stdlib/strtoll_r.c |
---|
0,0 → 1,140 |
/* |
This code is based on strtoul.c which has the following copyright. |
It is used to convert a string into a signed long long. |
long long _strtoll_r (struct _reent *rptr, const char *s, |
char **ptr, int base); |
*/ |
/*- |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#ifdef __GNUC__ |
#define _GNU_SOURCE |
#include <_ansi.h> |
#include <limits.h> |
#include <ctype.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <reent.h> |
/* |
* Convert a string to a long long integer. |
* |
* Ignores `locale' stuff. Assumes that the upper and lower case |
* alphabets and digits are each contiguous. |
*/ |
long long |
_DEFUN (_strtoll_r, (rptr, nptr, endptr, base), |
struct _reent *rptr _AND |
_CONST char *nptr _AND |
char **endptr _AND |
int base) |
{ |
register const unsigned char *s = (const unsigned char *)nptr; |
register unsigned long long acc; |
register int c; |
register unsigned long long cutoff; |
register int neg = 0, any, cutlim; |
/* |
* Skip white space and pick up leading +/- sign if any. |
* If base is 0, allow 0x for hex and 0 for octal, else |
* assume decimal; if base is already 16, allow 0x. |
*/ |
do { |
c = *s++; |
} while (isspace(c)); |
if (c == '-') { |
neg = 1; |
c = *s++; |
} else if (c == '+') |
c = *s++; |
if ((base == 0 || base == 16) && |
c == '0' && (*s == 'x' || *s == 'X')) { |
c = s[1]; |
s += 2; |
base = 16; |
} |
if (base == 0) |
base = c == '0' ? 8 : 10; |
/* |
* Compute the cutoff value between legal numbers and illegal |
* numbers. That is the largest legal value, divided by the |
* base. An input number that is greater than this value, if |
* followed by a legal input character, is too big. One that |
* is equal to this value may be valid or not; the limit |
* between valid and invalid numbers is then based on the last |
* digit. For instance, if the range for longs is |
* [-2147483648..2147483647] and the input base is 10, |
* cutoff will be set to 214748364 and cutlim to either |
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated |
* a value > 214748364, or equal but the next digit is > 7 (or 8), |
* the number is too big, and we will return a range error. |
* |
* Set any if any `digits' consumed; make it negative to indicate |
* overflow. |
*/ |
cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX; |
cutlim = cutoff % (unsigned long long)base; |
cutoff /= (unsigned long long)base; |
for (acc = 0, any = 0;; c = *s++) { |
if (isdigit(c)) |
c -= '0'; |
else if (isalpha(c)) |
c -= isupper(c) ? 'A' - 10 : 'a' - 10; |
else |
break; |
if (c >= base) |
break; |
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) |
any = -1; |
else { |
any = 1; |
acc *= base; |
acc += c; |
} |
} |
if (any < 0) { |
acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX; |
rptr->_errno = ERANGE; |
} else if (neg) |
acc = -acc; |
if (endptr != 0) |
*endptr = (char *) (any ? (char *)s - 1 : nptr); |
return (acc); |
} |
#endif /* __GNUC__ */ |
/programs/develop/libraries/newlib/stdlib/strtoull.c |
---|
0,0 → 1,139 |
/* |
FUNCTION |
<<strtoull>>---string to unsigned long long |
INDEX |
strtoull |
INDEX |
_strtoull_r |
ANSI_SYNOPSIS |
#include <stdlib.h> |
unsigned long long strtoull(const char *<[s]>, char **<[ptr]>, |
int <[base]>); |
unsigned long long _strtoull_r(void *<[reent]>, const char *<[s]>, |
char **<[ptr]>, int <[base]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
unsigned long long strtoull(<[s]>, <[ptr]>, <[base]>) |
char *<[s]>; |
char **<[ptr]>; |
int <[base]>; |
unsigned long long _strtoull_r(<[reent]>, <[s]>, <[ptr]>, <[base]>) |
char *<[reent]>; |
char *<[s]>; |
char **<[ptr]>; |
int <[base]>; |
DESCRIPTION |
The function <<strtoull>> converts the string <<*<[s]>>> to |
an <<unsigned long long>>. First, it breaks down the string into three parts: |
leading whitespace, which is ignored; a subject string consisting |
of the digits meaningful in the radix specified by <[base]> |
(for example, <<0>> through <<7>> if the value of <[base]> is 8); |
and a trailing portion consisting of one or more unparseable characters, |
which always includes the terminating null character. Then, it attempts |
to convert the subject string into an unsigned long long integer, and returns the |
result. |
If the value of <[base]> is zero, the subject string is expected to look |
like a normal C integer constant (save that no optional sign is permitted): |
a possible <<0x>> indicating hexadecimal radix, and a number. |
If <[base]> is between 2 and 36, the expected form of the subject is a |
sequence of digits (which may include letters, depending on the |
base) representing an integer in the radix specified by <[base]>. |
The letters <<a>>--<<z>> (or <<A>>--<<Z>>) are used as digits valued from |
10 to 35. If <[base]> is 16, a leading <<0x>> is permitted. |
The subject sequence is the longest initial sequence of the input |
string that has the expected form, starting with the first |
non-whitespace character. If the string is empty or consists entirely |
of whitespace, or if the first non-whitespace character is not a |
permissible digit, the subject string is empty. |
If the subject string is acceptable, and the value of <[base]> is zero, |
<<strtoull>> attempts to determine the radix from the input string. A |
string with a leading <<0x>> is treated as a hexadecimal value; a string with |
a leading <<0>> and no <<x>> is treated as octal; all other strings are |
treated as decimal. If <[base]> is between 2 and 36, it is used as the |
conversion radix, as described above. Finally, a pointer to the first |
character past the converted subject string is stored in <[ptr]>, if |
<[ptr]> is not <<NULL>>. |
If the subject string is empty (that is, if <<*>><[s]> does not start |
with a substring in acceptable form), no conversion |
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is |
not <<NULL>>). |
The alternate function <<_strtoull_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<strtoull>> returns the converted value, if any. If no conversion was |
made, <<0>> is returned. |
<<strtoull>> returns <<ULONG_LONG_MAX>> if the magnitude of the converted |
value is too large, and sets <<errno>> to <<ERANGE>>. |
PORTABILITY |
<<strtoull>> is ANSI. |
<<strtoull>> requires no supporting OS subroutines. |
*/ |
/* |
* Copyright (c) 1990 Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <_ansi.h> |
#include <limits.h> |
#include <ctype.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <reent.h> |
#ifndef _REENT_ONLY |
unsigned long long |
_DEFUN (strtoull, (s, ptr, base), |
_CONST char *s _AND |
char **ptr _AND |
int base) |
{ |
return _strtoull_r (_REENT, s, ptr, base); |
} |
#endif |
/programs/develop/libraries/newlib/stdlib/strtoull_r.c |
---|
0,0 → 1,120 |
/* |
This code is based on strtoul.c which has the following copyright. |
It is used to convert a string into an unsigned long long. |
long long _strtoull_r (struct _reent *rptr, const char *s, |
char **ptr, int base); |
*/ |
/* |
* Copyright (c) 1990 Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#ifdef __GNUC__ |
#define _GNU_SOURCE |
#include <_ansi.h> |
#include <limits.h> |
#include <ctype.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <reent.h> |
/* |
* Convert a string to an unsigned long long integer. |
* |
* Ignores `locale' stuff. Assumes that the upper and lower case |
* alphabets and digits are each contiguous. |
*/ |
unsigned long long |
_DEFUN (_strtoull_r, (rptr, nptr, endptr, base), |
struct _reent *rptr _AND |
_CONST char *nptr _AND |
char **endptr _AND |
int base) |
{ |
register const unsigned char *s = (const unsigned char *)nptr; |
register unsigned long long acc; |
register int c; |
register unsigned long long cutoff; |
register int neg = 0, any, cutlim; |
/* |
* See strtol for comments as to the logic used. |
*/ |
do { |
c = *s++; |
} while (isspace(c)); |
if (c == '-') { |
neg = 1; |
c = *s++; |
} else if (c == '+') |
c = *s++; |
if ((base == 0 || base == 16) && |
c == '0' && (*s == 'x' || *s == 'X')) { |
c = s[1]; |
s += 2; |
base = 16; |
} |
if (base == 0) |
base = c == '0' ? 8 : 10; |
cutoff = (unsigned long long)ULONG_LONG_MAX / (unsigned long long)base; |
cutlim = (unsigned long long)ULONG_LONG_MAX % (unsigned long long)base; |
for (acc = 0, any = 0;; c = *s++) { |
if (isdigit(c)) |
c -= '0'; |
else if (isalpha(c)) |
c -= isupper(c) ? 'A' - 10 : 'a' - 10; |
else |
break; |
if (c >= base) |
break; |
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) |
any = -1; |
else { |
any = 1; |
acc *= base; |
acc += c; |
} |
} |
if (any < 0) { |
acc = ULONG_LONG_MAX; |
rptr->_errno = ERANGE; |
} else if (neg) |
acc = -acc; |
if (endptr != 0) |
*endptr = (char *) (any ? (char *)s - 1 : nptr); |
return (acc); |
} |
#endif /* __GNUC__ */ |
/programs/develop/libraries/newlib/stdlib/system.c |
---|
0,0 → 1,85 |
/* |
FUNCTION |
<<system>>---execute command string |
INDEX |
system |
INDEX |
_system_r |
ANSI_SYNOPSIS |
#include <stdlib.h> |
int system(char *<[s]>); |
int _system_r(void *<[reent]>, char *<[s]>); |
TRAD_SYNOPSIS |
#include <stdlib.h> |
int system(<[s]>) |
char *<[s]>; |
int _system_r(<[reent]>, <[s]>) |
char *<[reent]>; |
char *<[s]>; |
DESCRIPTION |
Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on |
your system, and wait for it to finish executing. |
Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>> |
available. |
The alternate function <<_system_r>> is a reentrant version. The |
extra argument <[reent]> is a pointer to a reentrancy structure. |
RETURNS |
<<system(NULL)>> returns a non-zero value if <</bin/sh>> is available, and |
<<0>> if it is not. |
With a command argument, the result of <<system>> is the exit status |
returned by <</bin/sh>>. |
PORTABILITY |
ANSI C requires <<system>>, but leaves the nature and effects of a |
command processor undefined. ANSI C does, however, specify that |
<<system(NULL)>> return zero or nonzero to report on the existence of |
a command processor. |
POSIX.2 requires <<system>>, and requires that it invoke a <<sh>>. |
Where <<sh>> is found is left unspecified. |
Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>, |
<<_wait_r>>. |
*/ |
#include <_ansi.h> |
#include <errno.h> |
#include <stddef.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <_syslist.h> |
#include <reent.h> |
int |
_DEFUN(_system_r, (ptr, s), |
struct _reent *ptr _AND |
_CONST char *s) |
{ |
if (s == NULL) |
return 0; |
errno = ENOSYS; |
return -1; |
} |
#ifndef _REENT_ONLY |
int |
_DEFUN(system, (s), |
_CONST char *s) |
{ |
return _system_r (_REENT, s); |
} |
#endif |
/programs/develop/libraries/newlib/string/strcasestr.c |
---|
0,0 → 1,147 |
/* |
FUNCTION |
<<strcasestr>>---case-insensitive character string search |
INDEX |
strcasestr |
ANSI_SYNOPSIS |
#include <string.h> |
char *strcasestr(const char *<[s]>, const char *<[find]>); |
TRAD_SYNOPSIS |
#include <string.h> |
int strcasecmp(<[s]>, <[find]>) |
char *<[s]>; |
char *<[find]>; |
DESCRIPTION |
<<strcasestr>> searchs the string <[s]> for |
the first occurrence of the sequence <[find]>. <<strcasestr>> |
is identical to <<strstr>> except the search is |
case-insensitive. |
RETURNS |
A pointer to the first case-insensitive occurrence of the sequence |
<[find]> or <<NULL>> if no match was found. |
PORTABILITY |
<<strcasestr>> is in the Berkeley Software Distribution. |
<<strcasestr>> requires no supporting OS subroutines. It uses |
tolower() from elsewhere in this library. |
QUICKREF |
strcasestr |
*/ |
/*- |
* Copyright (c) 1990, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* The quadratic code is derived from software contributed to Berkeley by |
* Chris Torek. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
/* Linear algorithm Copyright (C) 2008 Eric Blake |
* Permission to use, copy, modify, and distribute the linear portion of |
* software is freely granted, provided that this notice is preserved. |
*/ |
#include <sys/cdefs.h> |
#include <ctype.h> |
#include <string.h> |
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) |
# define RETURN_TYPE char * |
# define AVAILABLE(h, h_l, j, n_l) \ |
(!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \ |
&& ((h_l) = (j) + (n_l))) |
# define CANON_ELEMENT(c) tolower (c) |
# define CMP_FUNC strncasecmp |
# include "str-two-way.h" |
#endif |
/* |
* Find the first occurrence of find in s, ignore case. |
*/ |
char * |
strcasestr(s, find) |
const char *s, *find; |
{ |
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) |
/* Less code size, but quadratic performance in the worst case. */ |
char c, sc; |
size_t len; |
if ((c = *find++) != 0) { |
c = tolower((unsigned char)c); |
len = strlen(find); |
do { |
do { |
if ((sc = *s++) == 0) |
return (NULL); |
} while ((char)tolower((unsigned char)sc) != c); |
} while (strncasecmp(s, find, len) != 0); |
s--; |
} |
return ((char *)s); |
#else /* compilation for speed */ |
/* Larger code size, but guaranteed linear performance. */ |
const char *haystack = s; |
const char *needle = find; |
size_t needle_len; /* Length of NEEDLE. */ |
size_t haystack_len; /* Known minimum length of HAYSTACK. */ |
int ok = 1; /* True if NEEDLE is prefix of HAYSTACK. */ |
/* Determine length of NEEDLE, and in the process, make sure |
HAYSTACK is at least as long (no point processing all of a long |
NEEDLE if HAYSTACK is too short). */ |
while (*haystack && *needle) |
ok &= (tolower ((unsigned char) *haystack++) |
== tolower ((unsigned char) *needle++)); |
if (*needle) |
return NULL; |
if (ok) |
return (char *) s; |
needle_len = needle - find; |
haystack = s + 1; |
haystack_len = needle_len - 1; |
/* Perform the search. */ |
if (needle_len < LONG_NEEDLE_THRESHOLD) |
return two_way_short_needle ((const unsigned char *) haystack, |
haystack_len, |
(const unsigned char *) find, needle_len); |
return two_way_long_needle ((const unsigned char *) haystack, haystack_len, |
(const unsigned char *) find, needle_len); |
#endif /* compilation for speed */ |
} |
/programs/develop/libraries/newlib/string/strcat.c |
---|
0,0 → 1,104 |
/* |
FUNCTION |
<<strcat>>---concatenate strings |
INDEX |
strcat |
ANSI_SYNOPSIS |
#include <string.h> |
char *strcat(char *<[dst]>, const char *<[src]>); |
TRAD_SYNOPSIS |
#include <string.h> |
char *strcat(<[dst]>, <[src]>) |
char *<[dst]>; |
char *<[src]>; |
DESCRIPTION |
<<strcat>> appends a copy of the string pointed to by <[src]> |
(including the terminating null character) to the end of the |
string pointed to by <[dst]>. The initial character of |
<[src]> overwrites the null character at the end of <[dst]>. |
RETURNS |
This function returns the initial value of <[dst]> |
PORTABILITY |
<<strcat>> is ANSI C. |
<<strcat>> requires no supporting OS subroutines. |
QUICKREF |
strcat ansi pure |
*/ |
#include <string.h> |
#include <limits.h> |
/* Nonzero if X is aligned on a "long" boundary. */ |
#define ALIGNED(X) \ |
(((long)X & (sizeof (long) - 1)) == 0) |
#if LONG_MAX == 2147483647L |
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) |
#else |
#if LONG_MAX == 9223372036854775807L |
/* Nonzero if X (a long int) contains a NULL byte. */ |
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) |
#else |
#error long int is not a 32bit or 64bit type. |
#endif |
#endif |
#ifndef DETECTNULL |
#error long int is not a 32bit or 64bit byte |
#endif |
/*SUPPRESS 560*/ |
/*SUPPRESS 530*/ |
char * |
_DEFUN (strcat, (s1, s2), |
char *s1 _AND |
_CONST char *s2) |
{ |
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) |
char *s = s1; |
while (*s1) |
s1++; |
while (*s1++ = *s2++) |
; |
return s; |
#else |
char *s = s1; |
/* Skip over the data in s1 as quickly as possible. */ |
if (ALIGNED (s1)) |
{ |
unsigned long *aligned_s1 = (unsigned long *)s1; |
while (!DETECTNULL (*aligned_s1)) |
aligned_s1++; |
s1 = (char *)aligned_s1; |
} |
while (*s1) |
s1++; |
/* s1 now points to the its trailing null character, we can |
just use strcpy to do the work for us now. |
?!? We might want to just include strcpy here. |
Also, this will cause many more unaligned string copies because |
s1 is much less likely to be aligned. I don't know if its worth |
tweaking strcpy to handle this better. */ |
strcpy (s1, s2); |
return s; |
#endif /* not PREFER_SIZE_OVER_SPEED */ |
} |
/programs/develop/libraries/newlib/string/strcoll.c |
---|
0,0 → 1,48 |
/* |
FUNCTION |
<<strcoll>>---locale-specific character string compare |
INDEX |
strcoll |
ANSI_SYNOPSIS |
#include <string.h> |
int strcoll(const char *<[stra]>, const char * <[strb]>); |
TRAD_SYNOPSIS |
#include <string.h> |
int strcoll(<[stra]>, <[strb]>) |
char *<[stra]>; |
char *<[strb]>; |
DESCRIPTION |
<<strcoll>> compares the string pointed to by <[stra]> to |
the string pointed to by <[strb]>, using an interpretation |
appropriate to the current <<LC_COLLATE>> state. |
RETURNS |
If the first string is greater than the second string, |
<<strcoll>> returns a number greater than zero. If the two |
strings are equivalent, <<strcoll>> returns zero. If the first |
string is less than the second string, <<strcoll>> returns a |
number less than zero. |
PORTABILITY |
<<strcoll>> is ANSI C. |
<<strcoll>> requires no supporting OS subroutines. |
QUICKREF |
strcoll ansi pure |
*/ |
#include <string.h> |
int |
_DEFUN (strcoll, (a, b), |
_CONST char *a _AND |
_CONST char *b) |
{ |
return strcmp (a, b); |
} |
/programs/develop/libraries/newlib/string/strncat.c |
---|
0,0 → 1,114 |
/* |
FUNCTION |
<<strncat>>---concatenate strings |
INDEX |
strncat |
ANSI_SYNOPSIS |
#include <string.h> |
char *strncat(char *<[dst]>, const char *<[src]>, size_t <[length]>); |
TRAD_SYNOPSIS |
#include <string.h> |
char *strncat(<[dst]>, <[src]>, <[length]>) |
char *<[dst]>; |
char *<[src]>; |
size_t <[length]>; |
DESCRIPTION |
<<strncat>> appends not more than <[length]> characters from |
the string pointed to by <[src]> (including the terminating |
null character) to the end of the string pointed to by |
<[dst]>. The initial character of <[src]> overwrites the null |
character at the end of <[dst]>. A terminating null character |
is always appended to the result |
WARNINGS |
Note that a null is always appended, so that if the copy is |
limited by the <[length]> argument, the number of characters |
appended to <[dst]> is <<n + 1>>. |
RETURNS |
This function returns the initial value of <[dst]> |
PORTABILITY |
<<strncat>> is ANSI C. |
<<strncat>> requires no supporting OS subroutines. |
QUICKREF |
strncat ansi pure |
*/ |
#include <string.h> |
#include <limits.h> |
/* Nonzero if X is aligned on a "long" boundary. */ |
#define ALIGNED(X) \ |
(((long)X & (sizeof (long) - 1)) == 0) |
#if LONG_MAX == 2147483647L |
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) |
#else |
#if LONG_MAX == 9223372036854775807L |
/* Nonzero if X (a long int) contains a NULL byte. */ |
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) |
#else |
#error long int is not a 32bit or 64bit type. |
#endif |
#endif |
#ifndef DETECTNULL |
#error long int is not a 32bit or 64bit byte |
#endif |
char * |
_DEFUN (strncat, (s1, s2, n), |
char *s1 _AND |
_CONST char *s2 _AND |
size_t n) |
{ |
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) |
char *s = s1; |
while (*s1) |
s1++; |
while (n-- != 0 && (*s1++ = *s2++)) |
{ |
if (n == 0) |
*s1 = '\0'; |
} |
return s; |
#else |
char *s = s1; |
/* Skip over the data in s1 as quickly as possible. */ |
if (ALIGNED (s1)) |
{ |
unsigned long *aligned_s1 = (unsigned long *)s1; |
while (!DETECTNULL (*aligned_s1)) |
aligned_s1++; |
s1 = (char *)aligned_s1; |
} |
while (*s1) |
s1++; |
/* s1 now points to the its trailing null character, now copy |
up to N bytes from S2 into S1 stopping if a NULL is encountered |
in S2. |
It is not safe to use strncpy here since it copies EXACTLY N |
characters, NULL padding if necessary. */ |
while (n-- != 0 && (*s1++ = *s2++)) |
{ |
if (n == 0) |
*s1 = '\0'; |
} |
return s; |
#endif /* not PREFER_SIZE_OVER_SPEED */ |
} |
/programs/develop/libraries/newlib/string/strndup.c |
---|
0,0 → 1,16 |
#ifndef _REENT_ONLY |
#include <_ansi.h> |
#include <reent.h> |
#include <stdlib.h> |
#include <string.h> |
char * |
_DEFUN (strndup, (str, n), |
_CONST char *str _AND |
size_t n) |
{ |
return _strndup_r (_REENT, str, n); |
} |
#endif /* !_REENT_ONLY */ |
/programs/develop/libraries/newlib/string/strndup_r.c |
---|
0,0 → 1,27 |
#include <reent.h> |
#include <stdlib.h> |
#include <string.h> |
char * |
_DEFUN (_strndup_r, (reent_ptr, str, n), |
struct _reent *reent_ptr _AND |
_CONST char *str _AND |
size_t n) |
{ |
_CONST char *ptr = str; |
size_t len; |
char *copy; |
while (n-- > 0 && *ptr) |
ptr++; |
len = ptr - str; |
copy = _malloc_r (reent_ptr, len + 1); |
if (copy) |
{ |
memcpy (copy, str, len); |
copy[len] = '\0'; |
} |
return copy; |
} |
/programs/develop/libraries/newlib/string/strpbrk.c |
---|
0,0 → 1,58 |
/* |
FUNCTION |
<<strpbrk>>---find characters in string |
INDEX |
strpbrk |
ANSI_SYNOPSIS |
#include <string.h> |
char *strpbrk(const char *<[s1]>, const char *<[s2]>); |
TRAD_SYNOPSIS |
#include <string.h> |
char *strpbrk(<[s1]>, <[s2]>) |
char *<[s1]>; |
char *<[s2]>; |
DESCRIPTION |
This function locates the first occurence in the string |
pointed to by <[s1]> of any character in string pointed to by |
<[s2]> (excluding the terminating null character). |
RETURNS |
<<strpbrk>> returns a pointer to the character found in <[s1]>, or a |
null pointer if no character from <[s2]> occurs in <[s1]>. |
PORTABILITY |
<<strpbrk>> requires no supporting OS subroutines. |
*/ |
#include <string.h> |
char * |
_DEFUN (strpbrk, (s1, s2), |
_CONST char *s1 _AND |
_CONST char *s2) |
{ |
_CONST char *c = s2; |
if (!*s1) |
return (char *) NULL; |
while (*s1) |
{ |
for (c = s2; *c; c++) |
{ |
if (*s1 == *c) |
break; |
} |
if (*c) |
break; |
s1++; |
} |
if (*c == '\0') |
s1 = NULL; |
return (char *) s1; |
} |
/programs/develop/libraries/newlib/string/strsep.c |
---|
0,0 → 1,19 |
/* BSD strsep function */ |
/* Copyright 2002, Red Hat Inc. */ |
/* undef STRICT_ANSI so that strsep prototype will be defined */ |
#undef __STRICT_ANSI__ |
#include <string.h> |
#include <_ansi.h> |
#include <reent.h> |
extern char *__strtok_r (char *, const char *, char **, int); |
char * |
_DEFUN (strsep, (source_ptr, delim), |
register char **source_ptr _AND |
register const char *delim) |
{ |
return __strtok_r (*source_ptr, delim, source_ptr, 0); |
} |
/programs/develop/libraries/newlib/string/strtok.c |
---|
0,0 → 1,101 |
/* |
FUNCTION |
<<strtok>>, <<strtok_r>>, <<strsep>>---get next token from a string |
INDEX |
strtok |
INDEX |
strtok_r |
INDEX |
strsep |
ANSI_SYNOPSIS |
#include <string.h> |
char *strtok(char *<[source]>, const char *<[delimiters]>) |
char *strtok_r(char *<[source]>, const char *<[delimiters]>, |
char **<[lasts]>) |
char *strsep(char **<[source_ptr]>, const char *<[delimiters]>) |
TRAD_SYNOPSIS |
#include <string.h> |
char *strtok(<[source]>, <[delimiters]>) |
char *<[source]>; |
char *<[delimiters]>; |
char *strtok_r(<[source]>, <[delimiters]>, <[lasts]>) |
char *<[source]>; |
char *<[delimiters]>; |
char **<[lasts]>; |
char *strsep(<[source_ptr]>, <[delimiters]>) |
char **<[source_ptr]>; |
char *<[delimiters]>; |
DESCRIPTION |
The <<strtok>> function is used to isolate sequential tokens in a |
null-terminated string, <<*<[source]>>>. These tokens are delimited |
in the string by at least one of the characters in <<*<[delimiters]>>>. |
The first time that <<strtok>> is called, <<*<[source]>>> should be |
specified; subsequent calls, wishing to obtain further tokens from |
the same string, should pass a null pointer instead. The separator |
string, <<*<[delimiters]>>>, must be supplied each time and may |
change between calls. |
The <<strtok>> function returns a pointer to the beginning of each |
subsequent token in the string, after replacing the separator |
character itself with a null character. When no more tokens remain, |
a null pointer is returned. |
The <<strtok_r>> function has the same behavior as <<strtok>>, except |
a pointer to placeholder <<*<[lasts]>>> must be supplied by the caller. |
The <<strsep>> function is similar in behavior to <<strtok>>, except |
a pointer to the string pointer must be supplied <<<[source_ptr]>>> and |
the function does not skip leading delimiters. When the string starts |
with a delimiter, the delimiter is changed to the null character and |
the empty string is returned. Like <<strtok_r>> and <<strtok>>, the |
<<*<[source_ptr]>>> is updated to the next character following the |
last delimiter found or NULL if the end of string is reached with |
no more delimiters. |
RETURNS |
<<strtok>>, <<strtok_r>>, and <<strsep>> all return a pointer to the |
next token, or <<NULL>> if no more tokens can be found. For |
<<strsep>>, a token may be the empty string. |
NOTES |
<<strtok>> is unsafe for multi-threaded applications. <<strtok_r>> |
and <<strsep>> are thread-safe and should be used instead. |
PORTABILITY |
<<strtok>> is ANSI C. |
<<strtok_r>> is POSIX. |
<<strsep>> is a BSD extension. |
<<strtok>>, <<strtok_r>>, and <<strsep>> require no supporting OS subroutines. |
QUICKREF |
strtok ansi impure |
*/ |
/* undef STRICT_ANSI so that strtok_r prototype will be defined */ |
#undef __STRICT_ANSI__ |
#include <string.h> |
#include <_ansi.h> |
#include <reent.h> |
#ifndef _REENT_ONLY |
extern char *__strtok_r (char *, const char *, char **, int); |
char * |
_DEFUN (strtok, (s, delim), |
register char *s _AND |
register const char *delim) |
{ |
_REENT_CHECK_MISC(_REENT); |
return __strtok_r (s, delim, &(_REENT_STRTOK_LAST(_REENT)), 1); |
} |
#endif |
/programs/develop/libraries/newlib/string/strtok_r.c |
---|
0,0 → 1,99 |
/* |
* Copyright (c) 1988 Regents of the University of California. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
#include <string.h> |
char * |
_DEFUN (__strtok_r, (s, delim, lasts, skip_leading_delim), |
register char *s _AND |
register const char *delim _AND |
char **lasts _AND |
int skip_leading_delim) |
{ |
register char *spanp; |
register int c, sc; |
char *tok; |
if (s == NULL && (s = *lasts) == NULL) |
return (NULL); |
/* |
* Skip (span) leading delimiters (s += strspn(s, delim), sort of). |
*/ |
cont: |
c = *s++; |
for (spanp = (char *)delim; (sc = *spanp++) != 0;) { |
if (c == sc) { |
if (skip_leading_delim) { |
goto cont; |
} |
else { |
*lasts = s; |
s[-1] = 0; |
return (s - 1); |
} |
} |
} |
if (c == 0) { /* no non-delimiter characters */ |
*lasts = NULL; |
return (NULL); |
} |
tok = s - 1; |
/* |
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of). |
* Note that delim must have one NUL; we stop if we see that, too. |
*/ |
for (;;) { |
c = *s++; |
spanp = (char *)delim; |
do { |
if ((sc = *spanp++) == c) { |
if (c == 0) |
s = NULL; |
else |
s[-1] = 0; |
*lasts = s; |
return (tok); |
} |
} while (sc != 0); |
} |
/* NOTREACHED */ |
} |
char * |
_DEFUN (strtok_r, (s, delim, lasts), |
register char *s _AND |
register const char *delim _AND |
char **lasts) |
{ |
return __strtok_r (s, delim, lasts, 1); |
} |
/programs/develop/libraries/newlib/string/strupr.c |
---|
0,0 → 1,46 |
/* |
FUNCTION |
<<strupr>>---force string to uppercase |
INDEX |
strupr |
ANSI_SYNOPSIS |
#include <string.h> |
char *strupr(char *<[a]>); |
TRAD_SYNOPSIS |
#include <string.h> |
char *strupr(<[a]>) |
char *<[a]>; |
DESCRIPTION |
<<strupr>> converts each character in the string at <[a]> to |
uppercase. |
RETURNS |
<<strupr>> returns its argument, <[a]>. |
PORTABILITY |
<<strupr>> is not widely portable. |
<<strupr>> requires no supporting OS subroutines. |
QUICKREF |
strupr |
*/ |
#include <string.h> |
#include <ctype.h> |
char * |
_DEFUN (strupr, (s), |
char *s) |
{ |
unsigned char *ucs = (unsigned char *) s; |
for ( ; *ucs != '\0'; ucs++) |
{ |
*ucs = toupper(*ucs); |
} |
return s; |
} |
/programs/develop/libraries/newlib/sys/create.c |
---|
0,0 → 1,25 |
#include <sys/types.h> |
#include <sys/kos_io.h> |
int create_file(const char *path) |
{ |
int retval; |
__asm__ __volatile__ ( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %0, 1(%%esp) \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $2 \n\t" |
"movl %%esp, %%ebx \n\t" |
"movl $70, %%eax \n\t" |
"int $0x40 \n\t" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"r" (path) |
:"ebx"); |
return retval; |
}; |
/programs/develop/libraries/newlib/sys/delete.c |
---|
0,0 → 1,26 |
#include <sys/types.h> |
#include <sys/kos_io.h> |
int delete_file(const char *path) |
{ |
int retval; |
__asm__ __volatile__ ( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %0, 1(%%esp) \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $8 \n\t" |
"movl %%esp, %%ebx \n\t" |
"movl $70, %%eax \n\t" |
"int $0x40 \n\t" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"r" (path) |
:"ebx"); |
return retval; |
}; |
/programs/develop/libraries/newlib/sys/finfo.c |
---|
0,0 → 1,26 |
#include <sys/types.h> |
#include <sys/kos_io.h> |
int get_fileinfo(const char *path, fileinfo_t *info) |
{ |
int retval; |
__asm__ __volatile__ ( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %1, 1(%%esp) \n\t" |
"pushl %%ebx \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $5 \n\t" |
"movl %%esp, %%ebx \n\t" |
"movl $70, %%eax \n\t" |
"int $0x40 \n\t" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"r" (path), "b" (info)); |
return retval; |
}; |
/programs/develop/libraries/newlib/sys/fload.c |
---|
0,0 → 1,37 |
#include <sys/types.h> |
#include <stdint.h> |
#include <sys/kos_io.h> |
void *load_file(const char *path, size_t *len) |
{ |
fileinfo_t info; |
size_t bytes; |
void *file = NULL; |
if( len) *len = 0; |
if( !get_fileinfo(path, &info) ) |
{ |
file = user_alloc( info.size ); |
read_file(path, file, 0, info.size, &bytes ); |
if( bytes == info.size ) |
{ |
if ( *(uint32_t*)file == 0x4B43504B ) |
{ |
void *tmp = NULL; |
info.size = ((size_t*)file)[1]; |
tmp = user_alloc(info.size); |
unpack(file, tmp); |
user_free(file); |
file = tmp; |
} |
if(len) *len = info.size; |
}; |
}; |
return file; |
}; |
/programs/develop/libraries/newlib/sys/fsize.c |
---|
0,0 → 1,26 |
#include <sys/types.h> |
#include <sys/kos_io.h> |
int set_file_size(const char *path, unsigned size) |
{ |
int retval; |
__asm__ __volatile__( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %%eax, 1(%%esp) \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"pushl %%ebx \n\t" |
"push $4 \n\t" |
"movl %%esp, %%ebx \n\t" |
"movl $70, %%eax \n\t" |
"int $0x40 \n\t" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"a" (path), "b" (size)); |
return retval; |
}; |
/programs/develop/libraries/newlib/sys/read.c |
---|
0,0 → 1,31 |
#include <sys/types.h> |
#include <sys/kos_io.h> |
int read_file(const char *path, void *buff, |
size_t offset, size_t count, size_t *reads) |
{ |
int retval; |
int d0; |
__asm__ __volatile__( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %%eax, 1(%%esp) \n\t" |
"pushl %%ebx \n\t" |
"pushl %%edx \n\t" |
"pushl $0 \n\t" |
"pushl %%ecx \n\t" |
"pushl $0 \n\t" |
"movl %%esp, %%ebx \n\t" |
"mov $70, %%eax \n\t" |
"int $0x40 \n\t" |
"testl %%esi, %%esi \n\t" |
"jz 1f \n\t" |
"movl %%ebx, (%%esi) \n\t" |
"1:" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"a"(path),"b"(buff),"c"(offset),"d"(count),"S"(reads)); |
return retval; |
}; |
/programs/develop/libraries/newlib/sys/write.c |
---|
0,0 → 1,29 |
#include <sys/types.h> |
#include <sys/kos_io.h> |
int write_file(const char *path,const void *buff, |
size_t offset, size_t count, size_t *writes) |
{ |
int retval; |
__asm__ __volatile__( |
"pushl $0 \n\t" |
"pushl $0 \n\t" |
"movl %%eax, 1(%%esp) \n\t" |
"pushl %%ebx \n\t" |
"pushl %%edx \n\t" |
"pushl $0 \n\t" |
"pushl %%ecx \n\t" |
"pushl $3 \n\t" |
"movl %%esp, %%ebx \n\t" |
"mov $70, %%eax \n\t" |
"int $0x40 \n\t" |
"testl %%esi, %%esi \n\t" |
"jz 1f \n\t" |
"movl %%ebx, (%%esi) \n\t" |
"1:" |
"addl $28, %%esp \n\t" |
:"=a" (retval) |
:"a"(path),"b"(buff),"c"(offset),"d"(count),"S"(writes)); |
return retval; |
}; |
/programs/develop/libraries/newlib/sys |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/develop/libraries/newlib/time/asctime.c |
---|
0,0 → 1,64 |
/* |
* asctime.c |
* Original Author: G. Haley |
* |
* Converts the broken down time in the structure pointed to by tim_p into a |
* string of the form |
* |
* Wed Jun 15 11:38:07 1988\n\0 |
* |
* Returns a pointer to the string. |
*/ |
/* |
FUNCTION |
<<asctime>>---format time as string |
INDEX |
asctime |
INDEX |
_asctime_r |
ANSI_SYNOPSIS |
#include <time.h> |
char *asctime(const struct tm *<[clock]>); |
char *_asctime_r(const struct tm *<[clock]>, char *<[buf]>); |
TRAD_SYNOPSIS |
#include <time.h> |
char *asctime(<[clock]>) |
struct tm *<[clock]>; |
char *asctime_r(<[clock]>) |
struct tm *<[clock]>; |
char *<[buf]>; |
DESCRIPTION |
Format the time value at <[clock]> into a string of the form |
. Wed Jun 15 11:38:07 1988\n\0 |
The string is generated in a static buffer; each call to <<asctime>> |
overwrites the string generated by previous calls. |
RETURNS |
A pointer to the string containing a formatted timestamp. |
PORTABILITY |
ANSI C requires <<asctime>>. |
<<asctime>> requires no supporting OS subroutines. |
*/ |
#include <time.h> |
#include <_ansi.h> |
#include <reent.h> |
#ifndef _REENT_ONLY |
char * |
_DEFUN (asctime, (tim_p), |
_CONST struct tm *tim_p) |
{ |
_REENT_CHECK_ASCTIME_BUF(_REENT); |
return asctime_r (tim_p, _REENT_ASCTIME_BUF(_REENT)); |
} |
#endif |
/programs/develop/libraries/newlib/time/asctime_r.c |
---|
0,0 → 1,27 |
/* |
* asctime_r.c |
*/ |
#include <stdio.h> |
#include <time.h> |
char * |
_DEFUN (asctime_r, (tim_p, result), |
_CONST struct tm *tim_p _AND |
char *result) |
{ |
static _CONST char day_name[7][3] = { |
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" |
}; |
static _CONST char mon_name[12][3] = { |
"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
}; |
sprintf (result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", |
day_name[tim_p->tm_wday], |
mon_name[tim_p->tm_mon], |
tim_p->tm_mday, tim_p->tm_hour, tim_p->tm_min, |
tim_p->tm_sec, 1900 + tim_p->tm_year); |
return result; |
} |
/programs/develop/libraries/newlib/time/clock.c |
---|
0,0 → 1,78 |
/* NetWare can not use this implementation of clock, since it does not |
have times or any similar function. It provides its own version of |
clock in clib.nlm. If we can not use clib.nlm, then we must write |
clock in sys/netware. */ |
#ifdef CLOCK_PROVIDED |
int _dummy_clock = 1; |
#else |
/* |
* clock.c |
* Original Author: G. Haley |
* |
* Determines the processor time used by the program since invocation. The time |
* in seconds is the value returned divided by the value of the macro CLK_TCK. |
* If the processor time used is not available, (clock_t) -1 is returned. |
*/ |
/* |
FUNCTION |
<<clock>>---cumulative processor time |
INDEX |
clock |
ANSI_SYNOPSIS |
#include <time.h> |
clock_t clock(void); |
TRAD_SYNOPSIS |
#include <time.h> |
clock_t clock(); |
DESCRIPTION |
Calculates the best available approximation of the cumulative amount |
of time used by your program since it started. To convert the result |
into seconds, divide by the macro <<CLOCKS_PER_SEC>>. |
RETURNS |
The amount of processor time used so far by your program, in units |
defined by the machine-dependent macro <<CLOCKS_PER_SEC>>. If no |
measurement is available, the result is (clock_t)<<-1>>. |
PORTABILITY |
ANSI C requires <<clock>> and <<CLOCKS_PER_SEC>>. |
Supporting OS subroutine required: <<times>>. |
*/ |
#include <time.h> |
#include <sys/times.h> |
#include <reent.h> |
clock_t |
_DEFUN (_times_r, (ptr, ptms), |
struct _reent *ptr _AND |
struct tms *ptms) |
{ |
return -1; |
} |
clock_t |
clock () |
{ |
struct tms tim_s; |
clock_t res; |
if ((res = (clock_t) _times_r (_REENT, &tim_s)) != -1) |
res = (clock_t) (tim_s.tms_utime + tim_s.tms_stime + |
tim_s.tms_cutime + tim_s.tms_cstime); |
return res; |
} |
#endif /* CLOCK_PROVIDED */ |
/programs/develop/libraries/newlib/time/ctime.c |
---|
0,0 → 1,55 |
/* |
* ctime.c |
* Original Author: G. Haley |
*/ |
/* |
FUNCTION |
<<ctime>>---convert time to local and format as string |
INDEX |
ctime |
INDEX |
ctime_r |
ANSI_SYNOPSIS |
#include <time.h> |
char *ctime(const time_t *<[clock]>); |
char *ctime_r(const time_t *<[clock]>, char *<[buf]>); |
TRAD_SYNOPSIS |
#include <time.h> |
char *ctime(<[clock]>) |
time_t *<[clock]>; |
char *ctime_r(<[clock]>, <[buf]>) |
time_t *<[clock]>; |
char *<[buf]>; |
DESCRIPTION |
Convert the time value at <[clock]> to local time (like <<localtime>>) |
and format it into a string of the form |
. Wed Jun 15 11:38:07 1988\n\0 |
(like <<asctime>>). |
RETURNS |
A pointer to the string containing a formatted timestamp. |
PORTABILITY |
ANSI C requires <<ctime>>. |
<<ctime>> requires no supporting OS subroutines. |
*/ |
#include <time.h> |
#ifndef _REENT_ONLY |
char * |
_DEFUN (ctime, (tim_p), |
_CONST time_t * tim_p) |
{ |
return asctime (localtime (tim_p)); |
} |
#endif |
/programs/develop/libraries/newlib/time/ctime_r.c |
---|
0,0 → 1,15 |
/* |
* ctime_r.c |
*/ |
#include <time.h> |
char * |
_DEFUN (ctime_r, (tim_p, result), |
_CONST time_t * tim_p _AND |
char * result) |
{ |
struct tm tm; |
return asctime_r (localtime_r (tim_p, &tm), result); |
} |
/programs/develop/libraries/newlib/time/difftime.c |
---|
0,0 → 1,44 |
/* |
* difftime.c |
* Original Author: G. Haley |
*/ |
/* |
FUNCTION |
<<difftime>>---subtract two times |
INDEX |
difftime |
ANSI_SYNOPSIS |
#include <time.h> |
double difftime(time_t <[tim1]>, time_t <[tim2]>); |
TRAD_SYNOPSIS |
#include <time.h> |
double difftime(<[tim1]>, <[tim2]>) |
time_t <[tim1]>; |
time_t <[tim2]>; |
DESCRIPTION |
Subtracts the two times in the arguments: `<<<[tim1]> - <[tim2]>>>'. |
RETURNS |
The difference (in seconds) between <[tim2]> and <[tim1]>, as a <<double>>. |
PORTABILITY |
ANSI C requires <<difftime>>, and defines its result to be in seconds |
in all implementations. |
<<difftime>> requires no supporting OS subroutines. |
*/ |
#include <time.h> |
double |
_DEFUN (difftime, (tim1, tim2), |
time_t tim1 _AND |
time_t tim2) |
{ |
return (double)(tim1 - tim2); |
} |
/programs/develop/libraries/newlib/time/gettzinfo.c |
---|
0,0 → 1,15 |
#include <sys/types.h> |
#include "local.h" |
/* Shared timezone information for libc/time functions. */ |
static __tzinfo_type tzinfo = {1, 0, |
{ {'J', 0, 0, 0, 0, (time_t)0, 0L }, |
{'J', 0, 0, 0, 0, (time_t)0, 0L } |
} |
}; |
__tzinfo_type * |
__gettzinfo (void) |
{ |
return &tzinfo; |
} |
/programs/develop/libraries/newlib/time/gmtime.c |
---|
0,0 → 1,68 |
/* |
* gmtime.c |
* Original Author: G. Haley |
* |
* Converts the calendar time pointed to by tim_p into a broken-down time |
* expressed as Greenwich Mean Time (GMT). Returns a pointer to a structure |
* containing the broken-down time, or a null pointer if GMT is not |
* available. |
*/ |
/* |
FUNCTION |
<<gmtime>>---convert time to UTC traditional form |
INDEX |
gmtime |
INDEX |
gmtime_r |
ANSI_SYNOPSIS |
#include <time.h> |
struct tm *gmtime(const time_t *<[clock]>); |
struct tm *gmtime_r(const time_t *<[clock]>, struct tm *<[res]>); |
TRAD_SYNOPSIS |
#include <time.h> |
struct tm *gmtime(<[clock]>) |
const time_t *<[clock]>; |
struct tm *gmtime_r(<[clock]>, <[res]>) |
const time_t *<[clock]>; |
struct tm *<[res]>; |
DESCRIPTION |
<<gmtime>> takes the time at <[clock]> representing the number |
of elapsed seconds since 00:00:00 on January 1, 1970, Universal |
Coordinated Time (UTC, also known in some countries as GMT, |
Greenwich Mean time) and converts it to a <<struct tm>> |
representation. |
<<gmtime>> constructs the traditional time representation in static |
storage; each call to <<gmtime>> or <<localtime>> will overwrite the |
information generated by previous calls to either function. |
RETURNS |
A pointer to the traditional time representation (<<struct tm>>). |
PORTABILITY |
ANSI C requires <<gmtime>>. |
<<gmtime>> requires no supporting OS subroutines. |
*/ |
#include <stdlib.h> |
#include <time.h> |
#define _GMT_OFFSET 0 |
#ifndef _REENT_ONLY |
struct tm * |
_DEFUN (gmtime, (tim_p), |
_CONST time_t * tim_p) |
{ |
_REENT_CHECK_TM(_REENT); |
return gmtime_r (tim_p, (struct tm *)_REENT_TM(_REENT)); |
} |
#endif |
/programs/develop/libraries/newlib/time/gmtime_r.c |
---|
0,0 → 1,14 |
/* |
* gmtime_r.c |
*/ |
#include <time.h> |
#include "local.h" |
struct tm * |
_DEFUN (gmtime_r, (tim_p, res), |
_CONST time_t * tim_p _AND |
struct tm *res) |
{ |
return (_mktm_r (tim_p, res, 1)); |
} |
/programs/develop/libraries/newlib/time/lcltime.c |
---|
0,0 → 1,60 |
/* |
* localtime.c |
*/ |
/* |
FUNCTION |
<<localtime>>---convert time to local representation |
INDEX |
localtime |
INDEX |
localtime_r |
ANSI_SYNOPSIS |
#include <time.h> |
struct tm *localtime(time_t *<[clock]>); |
struct tm *localtime_r(time_t *<[clock]>, struct tm *<[res]>); |
TRAD_SYNOPSIS |
#include <time.h> |
struct tm *localtime(<[clock]>) |
time_t *<[clock]>; |
struct tm *localtime(<[clock]>, <[res]>) |
time_t *<[clock]>; |
struct tm *<[res]>; |
DESCRIPTION |
<<localtime>> converts the time at <[clock]> into local time, then |
converts its representation from the arithmetic representation to the |
traditional representation defined by <<struct tm>>. |
<<localtime>> constructs the traditional time representation in static |
storage; each call to <<gmtime>> or <<localtime>> will overwrite the |
information generated by previous calls to either function. |
<<mktime>> is the inverse of <<localtime>>. |
RETURNS |
A pointer to the traditional time representation (<<struct tm>>). |
PORTABILITY |
ANSI C requires <<localtime>>. |
<<localtime>> requires no supporting OS subroutines. |
*/ |
#include <time.h> |
#include <reent.h> |
#ifndef _REENT_ONLY |
struct tm * |
_DEFUN (localtime, (tim_p), |
_CONST time_t * tim_p) |
{ |
_REENT_CHECK_TM(_REENT); |
return localtime_r (tim_p, (struct tm *)_REENT_TM(_REENT)); |
} |
#endif |
/programs/develop/libraries/newlib/time/lcltime_r.c |
---|
0,0 → 1,18 |
/* |
* localtime_r.c |
* |
* Converts the calendar time pointed to by tim_p into a broken-down time |
* expressed as local time. Returns a pointer to a structure containing the |
* broken-down time. |
*/ |
#include <time.h> |
#include "local.h" |
struct tm * |
_DEFUN (localtime_r, (tim_p, res), |
_CONST time_t * tim_p _AND |
struct tm *res) |
{ |
return _mktm_r (tim_p, res, 0); |
} |
/programs/develop/libraries/newlib/time/local.h |
---|
0,0 → 1,36 |
/* local header used by libc/time routines */ |
#include <_ansi.h> |
#include <time.h> |
#define SECSPERMIN 60L |
#define MINSPERHOUR 60L |
#define HOURSPERDAY 24L |
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) |
#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY) |
#define DAYSPERWEEK 7 |
#define MONSPERYEAR 12 |
#define YEAR_BASE 1900 |
#define EPOCH_YEAR 1970 |
#define EPOCH_WDAY 4 |
#define EPOCH_YEARS_SINCE_LEAP 2 |
#define EPOCH_YEARS_SINCE_CENTURY 70 |
#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370 |
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) |
struct tm * _EXFUN (_mktm_r, (_CONST time_t *, struct tm *, int __is_gmtime)); |
int _EXFUN (__tzcalc_limits, (int __year)); |
/* locks for multi-threading */ |
#ifdef __SINGLE_THREAD__ |
#define TZ_LOCK |
#define TZ_UNLOCK |
#else |
#define TZ_LOCK __tz_lock() |
#define TZ_UNLOCK __tz_unlock() |
#endif |
void _EXFUN(__tz_lock,(_VOID)); |
void _EXFUN(__tz_unlock,(_VOID)); |
/programs/develop/libraries/newlib/time/mktime.c |
---|
0,0 → 1,264 |
/* |
* mktime.c |
* Original Author: G. Haley |
* |
* Converts the broken-down time, expressed as local time, in the structure |
* pointed to by tim_p into a calendar time value. The original values of the |
* tm_wday and tm_yday fields of the structure are ignored, and the original |
* values of the other fields have no restrictions. On successful completion |
* the fields of the structure are set to represent the specified calendar |
* time. Returns the specified calendar time. If the calendar time can not be |
* represented, returns the value (time_t) -1. |
* |
* Modifications: Fixed tm_isdst usage - 27 August 2008 Craig Howland. |
*/ |
/* |
FUNCTION |
<<mktime>>---convert time to arithmetic representation |
INDEX |
mktime |
ANSI_SYNOPSIS |
#include <time.h> |
time_t mktime(struct tm *<[timp]>); |
TRAD_SYNOPSIS |
#include <time.h> |
time_t mktime(<[timp]>) |
struct tm *<[timp]>; |
DESCRIPTION |
<<mktime>> assumes the time at <[timp]> is a local time, and converts |
its representation from the traditional representation defined by |
<<struct tm>> into a representation suitable for arithmetic. |
<<localtime>> is the inverse of <<mktime>>. |
RETURNS |
If the contents of the structure at <[timp]> do not form a valid |
calendar time representation, the result is <<-1>>. Otherwise, the |
result is the time, converted to a <<time_t>> value. |
PORTABILITY |
ANSI C requires <<mktime>>. |
<<mktime>> requires no supporting OS subroutines. |
*/ |
#include <stdlib.h> |
#include <time.h> |
#include "local.h" |
#define _SEC_IN_MINUTE 60L |
#define _SEC_IN_HOUR 3600L |
#define _SEC_IN_DAY 86400L |
static _CONST int DAYS_IN_MONTH[12] = |
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x]) |
static _CONST int _DAYS_BEFORE_MONTH[12] = |
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; |
#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0)) |
#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365) |
static void |
_DEFUN(validate_structure, (tim_p), |
struct tm *tim_p) |
{ |
div_t res; |
int days_in_feb = 28; |
/* calculate time & date to account for out of range values */ |
if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59) |
{ |
res = div (tim_p->tm_sec, 60); |
tim_p->tm_min += res.quot; |
if ((tim_p->tm_sec = res.rem) < 0) |
{ |
tim_p->tm_sec += 60; |
--tim_p->tm_min; |
} |
} |
if (tim_p->tm_min < 0 || tim_p->tm_min > 59) |
{ |
res = div (tim_p->tm_min, 60); |
tim_p->tm_hour += res.quot; |
if ((tim_p->tm_min = res.rem) < 0) |
{ |
tim_p->tm_min += 60; |
--tim_p->tm_hour; |
} |
} |
if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23) |
{ |
res = div (tim_p->tm_hour, 24); |
tim_p->tm_mday += res.quot; |
if ((tim_p->tm_hour = res.rem) < 0) |
{ |
tim_p->tm_hour += 24; |
--tim_p->tm_mday; |
} |
} |
if (tim_p->tm_mon > 11) |
{ |
res = div (tim_p->tm_mon, 12); |
tim_p->tm_year += res.quot; |
if ((tim_p->tm_mon = res.rem) < 0) |
{ |
tim_p->tm_mon += 12; |
--tim_p->tm_year; |
} |
} |
if (_DAYS_IN_YEAR (tim_p->tm_year) == 366) |
days_in_feb = 29; |
if (tim_p->tm_mday <= 0) |
{ |
while (tim_p->tm_mday <= 0) |
{ |
if (--tim_p->tm_mon == -1) |
{ |
tim_p->tm_year--; |
tim_p->tm_mon = 11; |
days_in_feb = |
((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? |
29 : 28); |
} |
tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon); |
} |
} |
else |
{ |
while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon)) |
{ |
tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon); |
if (++tim_p->tm_mon == 12) |
{ |
tim_p->tm_year++; |
tim_p->tm_mon = 0; |
days_in_feb = |
((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? |
29 : 28); |
} |
} |
} |
} |
time_t |
_DEFUN(mktime, (tim_p), |
struct tm *tim_p) |
{ |
time_t tim = 0; |
long days = 0; |
int year, isdst, tm_isdst; |
__tzinfo_type *tz = __gettzinfo (); |
/* validate structure */ |
validate_structure (tim_p); |
/* compute hours, minutes, seconds */ |
tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) + |
(tim_p->tm_hour * _SEC_IN_HOUR); |
/* compute days in year */ |
days += tim_p->tm_mday - 1; |
days += _DAYS_BEFORE_MONTH[tim_p->tm_mon]; |
if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366) |
days++; |
/* compute day of the year */ |
tim_p->tm_yday = days; |
if (tim_p->tm_year > 10000 |
|| tim_p->tm_year < -10000) |
{ |
return (time_t) -1; |
} |
/* compute days in other years */ |
if (tim_p->tm_year > 70) |
{ |
for (year = 70; year < tim_p->tm_year; year++) |
days += _DAYS_IN_YEAR (year); |
} |
else if (tim_p->tm_year < 70) |
{ |
for (year = 69; year > tim_p->tm_year; year--) |
days -= _DAYS_IN_YEAR (year); |
days -= _DAYS_IN_YEAR (year); |
} |
/* compute day of the week */ |
if ((tim_p->tm_wday = (days + 4) % 7) < 0) |
tim_p->tm_wday += 7; |
/* compute total seconds */ |
tim += (days * _SEC_IN_DAY); |
/* Convert user positive into 1 */ |
tm_isdst = tim_p->tm_isdst > 0 ? 1 : tim_p->tm_isdst; |
isdst = tm_isdst; |
if (_daylight) |
{ |
int y = tim_p->tm_year + YEAR_BASE; |
if (y == tz->__tzyear || __tzcalc_limits (y)) |
{ |
/* calculate start of dst in dst local time and |
start of std in both std local time and dst local time */ |
time_t startdst_dst = tz->__tzrule[0].change |
- (time_t) tz->__tzrule[1].offset; |
time_t startstd_dst = tz->__tzrule[1].change |
- (time_t) tz->__tzrule[1].offset; |
time_t startstd_std = tz->__tzrule[1].change |
- (time_t) tz->__tzrule[0].offset; |
/* if the time is in the overlap between dst and std local times */ |
if (tim >= startstd_std && tim < startstd_dst) |
; /* we let user decide or leave as -1 */ |
else |
{ |
isdst = (tz->__tznorth |
? (tim >= startdst_dst && tim < startstd_std) |
: (tim >= startdst_dst || tim < startstd_std)); |
/* if user committed and was wrong, perform correction, but not |
* if the user has given a negative value (which |
* asks mktime() to determine if DST is in effect or not) */ |
if (tm_isdst >= 0 && (isdst ^ tm_isdst) == 1) |
{ |
/* we either subtract or add the difference between |
time zone offsets, depending on which way the user got it |
wrong. The diff is typically one hour, or 3600 seconds, |
and should fit in a 16-bit int, even though offset |
is a long to accomodate 12 hours. */ |
int diff = (int) (tz->__tzrule[0].offset |
- tz->__tzrule[1].offset); |
if (!isdst) |
diff = -diff; |
tim_p->tm_sec += diff; |
validate_structure (tim_p); |
tim += diff; /* we also need to correct our current time calculation */ |
} |
} |
} |
} |
/* add appropriate offset to put time in gmt format */ |
if (isdst == 1) |
tim += (time_t) tz->__tzrule[1].offset; |
else /* otherwise assume std time */ |
tim += (time_t) tz->__tzrule[0].offset; |
/* reset isdst flag to what we have calculated */ |
tim_p->tm_isdst = isdst; |
return tim; |
} |
/programs/develop/libraries/newlib/time/mktm_r.c |
---|
0,0 → 1,257 |
/* |
* mktm_r.c |
* Original Author: Adapted from tzcode maintained by Arthur David Olson. |
* Modifications: Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston |
* Fixed bug in mday computations - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru> |
* Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru> |
* |
* Converts the calendar time pointed to by tim_p into a broken-down time |
* expressed as local time. Returns a pointer to a structure containing the |
* broken-down time. |
*/ |
#include <stdlib.h> |
#include <time.h> |
#include "local.h" |
static _CONST int mon_lengths[2][MONSPERYEAR] = { |
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, |
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} |
} ; |
static _CONST int year_lengths[2] = { |
365, |
366 |
} ; |
struct tm * |
_DEFUN (_mktm_r, (tim_p, res, is_gmtime), |
_CONST time_t * tim_p _AND |
struct tm *res _AND |
int is_gmtime) |
{ |
long days, rem; |
time_t lcltime; |
int y; |
int yleap; |
_CONST int *ip; |
__tzinfo_type *tz = __gettzinfo (); |
/* base decision about std/dst time on current time */ |
lcltime = *tim_p; |
days = ((long)lcltime) / SECSPERDAY; |
rem = ((long)lcltime) % SECSPERDAY; |
while (rem < 0) |
{ |
rem += SECSPERDAY; |
--days; |
} |
while (rem >= SECSPERDAY) |
{ |
rem -= SECSPERDAY; |
++days; |
} |
/* compute hour, min, and sec */ |
res->tm_hour = (int) (rem / SECSPERHOUR); |
rem %= SECSPERHOUR; |
res->tm_min = (int) (rem / SECSPERMIN); |
res->tm_sec = (int) (rem % SECSPERMIN); |
/* compute day of week */ |
if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0) |
res->tm_wday += DAYSPERWEEK; |
/* compute year & day of year */ |
y = EPOCH_YEAR; |
if (days >= 0) |
{ |
for (;;) |
{ |
yleap = isleap(y); |
if (days < year_lengths[yleap]) |
break; |
y++; |
days -= year_lengths[yleap]; |
} |
} |
else |
{ |
do |
{ |
--y; |
yleap = isleap(y); |
days += year_lengths[yleap]; |
} while (days < 0); |
} |
res->tm_year = y - YEAR_BASE; |
res->tm_yday = days; |
ip = mon_lengths[yleap]; |
for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon) |
days -= ip[res->tm_mon]; |
res->tm_mday = days + 1; |
if (!is_gmtime) |
{ |
long offset; |
int hours, mins, secs; |
TZ_LOCK; |
if (_daylight) |
{ |
if (y == tz->__tzyear || __tzcalc_limits (y)) |
res->tm_isdst = (tz->__tznorth |
? (*tim_p >= tz->__tzrule[0].change |
&& *tim_p < tz->__tzrule[1].change) |
: (*tim_p >= tz->__tzrule[0].change |
|| *tim_p < tz->__tzrule[1].change)); |
else |
res->tm_isdst = -1; |
} |
else |
res->tm_isdst = 0; |
offset = (res->tm_isdst == 1 |
? tz->__tzrule[1].offset |
: tz->__tzrule[0].offset); |
hours = (int) (offset / SECSPERHOUR); |
offset = offset % SECSPERHOUR; |
mins = (int) (offset / SECSPERMIN); |
secs = (int) (offset % SECSPERMIN); |
res->tm_sec -= secs; |
res->tm_min -= mins; |
res->tm_hour -= hours; |
if (res->tm_sec >= SECSPERMIN) |
{ |
res->tm_min += 1; |
res->tm_sec -= SECSPERMIN; |
} |
else if (res->tm_sec < 0) |
{ |
res->tm_min -= 1; |
res->tm_sec += SECSPERMIN; |
} |
if (res->tm_min >= MINSPERHOUR) |
{ |
res->tm_hour += 1; |
res->tm_min -= MINSPERHOUR; |
} |
else if (res->tm_min < 0) |
{ |
res->tm_hour -= 1; |
res->tm_min += MINSPERHOUR; |
} |
if (res->tm_hour >= HOURSPERDAY) |
{ |
++res->tm_yday; |
++res->tm_wday; |
if (res->tm_wday > 6) |
res->tm_wday = 0; |
++res->tm_mday; |
res->tm_hour -= HOURSPERDAY; |
if (res->tm_mday > ip[res->tm_mon]) |
{ |
res->tm_mday -= ip[res->tm_mon]; |
res->tm_mon += 1; |
if (res->tm_mon == 12) |
{ |
res->tm_mon = 0; |
res->tm_year += 1; |
res->tm_yday = 0; |
} |
} |
} |
else if (res->tm_hour < 0) |
{ |
res->tm_yday -= 1; |
res->tm_wday -= 1; |
if (res->tm_wday < 0) |
res->tm_wday = 6; |
res->tm_mday -= 1; |
res->tm_hour += 24; |
if (res->tm_mday == 0) |
{ |
res->tm_mon -= 1; |
if (res->tm_mon < 0) |
{ |
res->tm_mon = 11; |
res->tm_year -= 1; |
res->tm_yday = 365 + isleap(res->tm_year); |
} |
res->tm_mday = ip[res->tm_mon]; |
} |
} |
TZ_UNLOCK; |
} |
else |
res->tm_isdst = 0; |
return (res); |
} |
int |
_DEFUN (__tzcalc_limits, (year), |
int year) |
{ |
int days, year_days, years; |
int i, j; |
__tzinfo_type *tz = __gettzinfo (); |
if (year < EPOCH_YEAR) |
return 0; |
tz->__tzyear = year; |
years = (year - EPOCH_YEAR); |
year_days = years * 365 + |
(years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + |
(years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400; |
for (i = 0; i < 2; ++i) |
{ |
if (tz->__tzrule[i].ch == 'J') |
days = year_days + tz->__tzrule[i].d + |
(isleap(year) && tz->__tzrule[i].d >= 60); |
else if (tz->__tzrule[i].ch == 'D') |
days = year_days + tz->__tzrule[i].d; |
else |
{ |
int yleap = isleap(year); |
int m_day, m_wday, wday_diff; |
_CONST int *ip = mon_lengths[yleap]; |
days = year_days; |
for (j = 1; j < tz->__tzrule[i].m; ++j) |
days += ip[j-1]; |
m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK; |
wday_diff = tz->__tzrule[i].d - m_wday; |
if (wday_diff < 0) |
wday_diff += DAYSPERWEEK; |
m_day = (tz->__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff; |
while (m_day >= ip[j-1]) |
m_day -= DAYSPERWEEK; |
days += m_day; |
} |
/* store the change-over time in GMT form by adding offset */ |
tz->__tzrule[i].change = days * SECSPERDAY + |
tz->__tzrule[i].s + tz->__tzrule[i].offset; |
} |
tz->__tznorth = (tz->__tzrule[0].change < tz->__tzrule[1].change); |
return 1; |
} |
/programs/develop/libraries/newlib/time/strftime.c |
---|
0,0 → 1,333 |
/* NOTE: This file defines both strftime() and wcsftime(). Take care when |
* making changes. See also wcsftime.c, and note the (small) overlap in the |
* manual description, taking care to edit both as needed. */ |
/* |
* strftime.c |
* Original Author: G. Haley |
* Additions from: Eric Blake |
* Changes to allow dual use as wcstime, also: Craig Howland |
* |
* Places characters into the array pointed to by s as controlled by the string |
* pointed to by format. If the total number of resulting characters including |
* the terminating null character is not more than maxsize, returns the number |
* of characters placed into the array pointed to by s (not including the |
* terminating null character); otherwise zero is returned and the contents of |
* the array indeterminate. |
*/ |
/* |
FUNCTION |
<<strftime>>---convert date and time to a formatted string |
INDEX |
strftime |
ANSI_SYNOPSIS |
#include <time.h> |
size_t strftime(char *<[s]>, size_t <[maxsize]>, |
const char *<[format]>, const struct tm *<[timp]>); |
TRAD_SYNOPSIS |
#include <time.h> |
size_t strftime(<[s]>, <[maxsize]>, <[format]>, <[timp]>) |
char *<[s]>; |
size_t <[maxsize]>; |
char *<[format]>; |
struct tm *<[timp]>; |
DESCRIPTION |
<<strftime>> converts a <<struct tm>> representation of the time (at |
<[timp]>) into a null-terminated string, starting at <[s]> and occupying |
no more than <[maxsize]> characters. |
You control the format of the output using the string at <[format]>. |
<<*<[format]>>> can contain two kinds of specifications: text to be |
copied literally into the formatted string, and time conversion |
specifications. Time conversion specifications are two- and |
three-character sequences beginning with `<<%>>' (use `<<%%>>' to |
include a percent sign in the output). Each defined conversion |
specification selects only the specified field(s) of calendar time |
data from <<*<[timp]>>>, and converts it to a string in one of the |
following ways: |
o+ |
o %a |
The abbreviated weekday name according to the current locale. [tm_wday] |
o %A |
The full weekday name according to the current locale. |
In the default "C" locale, one of `<<Sunday>>', `<<Monday>>', `<<Tuesday>>', |
`<<Wednesday>>', `<<Thursday>>', `<<Friday>>', `<<Saturday>>'. [tm_wday] |
o %b |
The abbreviated month name according to the current locale. [tm_mon] |
o %B |
The full month name according to the current locale. |
In the default "C" locale, one of `<<January>>', `<<February>>', |
`<<March>>', `<<April>>', `<<May>>', `<<June>>', `<<July>>', |
`<<August>>', `<<September>>', `<<October>>', `<<November>>', |
`<<December>>'. [tm_mon] |
o %c |
The preferred date and time representation for the current locale. |
[tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday] |
o %C |
The century, that is, the year divided by 100 then truncated. For |
4-digit years, the result is zero-padded and exactly two characters; |
but for other years, there may a negative sign or more digits. In |
this way, `<<%C%y>>' is equivalent to `<<%Y>>'. [tm_year] |
o %d |
The day of the month, formatted with two digits (from `<<01>>' to |
`<<31>>'). [tm_mday] |
o %D |
A string representing the date, in the form `<<"%m/%d/%y">>'. |
[tm_mday, tm_mon, tm_year] |
o %e |
The day of the month, formatted with leading space if single digit |
(from `<<1>>' to `<<31>>'). [tm_mday] |
o %E<<x>> |
In some locales, the E modifier selects alternative representations of |
certain modifiers <<x>>. In newlib, it is ignored, and treated as %<<x>>. |
o %F |
A string representing the ISO 8601:2000 date format, in the form |
`<<"%Y-%m-%d">>'. [tm_mday, tm_mon, tm_year] |
o %g |
The last two digits of the week-based year, see specifier %G (from |
`<<00>>' to `<<99>>'). [tm_year, tm_wday, tm_yday] |
o %G |
The week-based year. In the ISO 8601:2000 calendar, week 1 of the year |
includes January 4th, and begin on Mondays. Therefore, if January 1st, |
2nd, or 3rd falls on a Sunday, that day and earlier belong to the last |
week of the previous year; and if December 29th, 30th, or 31st falls |
on Monday, that day and later belong to week 1 of the next year. For |
consistency with %Y, it always has at least four characters. |
Example: "%G" for Saturday 2nd January 1999 gives "1998", and for |
Tuesday 30th December 1997 gives "1998". [tm_year, tm_wday, tm_yday] |
o %h |
Synonym for "%b". [tm_mon] |
o %H |
The hour (on a 24-hour clock), formatted with two digits (from |
`<<00>>' to `<<23>>'). [tm_hour] |
o %I |
The hour (on a 12-hour clock), formatted with two digits (from |
`<<01>>' to `<<12>>'). [tm_hour] |
o %j |
The count of days in the year, formatted with three digits |
(from `<<001>>' to `<<366>>'). [tm_yday] |
o %k |
The hour (on a 24-hour clock), formatted with leading space if single |
digit (from `<<0>>' to `<<23>>'). Non-POSIX extension (c.p. %I). [tm_hour] |
o %l |
The hour (on a 12-hour clock), formatted with leading space if single |
digit (from `<<1>>' to `<<12>>'). Non-POSIX extension (c.p. %H). [tm_hour] |
o %m |
The month number, formatted with two digits (from `<<01>>' to `<<12>>'). |
[tm_mon] |
o %M |
The minute, formatted with two digits (from `<<00>>' to `<<59>>'). [tm_min] |
o %n |
A newline character (`<<\n>>'). |
o %O<<x>> |
In some locales, the O modifier selects alternative digit characters |
for certain modifiers <<x>>. In newlib, it is ignored, and treated as %<<x>>. |
o %p |
Either `<<AM>>' or `<<PM>>' as appropriate, or the corresponding strings for |
the current locale. [tm_hour] |
o %P |
Same as '<<%p>>', but in lowercase. This is a GNU extension. [tm_hour] |
o %r |
Replaced by the time in a.m. and p.m. notation. In the "C" locale this |
is equivalent to "%I:%M:%S %p". In locales which don't define a.m./p.m. |
notations, the result is an empty string. [tm_sec, tm_min, tm_hour] |
o %R |
The 24-hour time, to the minute. Equivalent to "%H:%M". [tm_min, tm_hour] |
o %S |
The second, formatted with two digits (from `<<00>>' to `<<60>>'). The |
value 60 accounts for the occasional leap second. [tm_sec] |
o %t |
A tab character (`<<\t>>'). |
o %T |
The 24-hour time, to the second. Equivalent to "%H:%M:%S". [tm_sec, |
tm_min, tm_hour] |
o %u |
The weekday as a number, 1-based from Monday (from `<<1>>' to |
`<<7>>'). [tm_wday] |
o %U |
The week number, where weeks start on Sunday, week 1 contains the first |
Sunday in a year, and earlier days are in week 0. Formatted with two |
digits (from `<<00>>' to `<<53>>'). See also <<%W>>. [tm_wday, tm_yday] |
o %V |
The week number, where weeks start on Monday, week 1 contains January 4th, |
and earlier days are in the previous year. Formatted with two digits |
(from `<<01>>' to `<<53>>'). See also <<%G>>. [tm_year, tm_wday, tm_yday] |
o %w |
The weekday as a number, 0-based from Sunday (from `<<0>>' to `<<6>>'). |
[tm_wday] |
o %W |
The week number, where weeks start on Monday, week 1 contains the first |
Monday in a year, and earlier days are in week 0. Formatted with two |
digits (from `<<00>>' to `<<53>>'). [tm_wday, tm_yday] |
o %x |
Replaced by the preferred date representation in the current locale. |
In the "C" locale this is equivalent to "%m/%d/%y". |
[tm_mon, tm_mday, tm_year] |
o %X |
Replaced by the preferred time representation in the current locale. |
In the "C" locale this is equivalent to "%H:%M:%S". [tm_sec, tm_min, tm_hour] |
o %y |
The last two digits of the year (from `<<00>>' to `<<99>>'). [tm_year] |
(Implementation interpretation: always positive, even for negative years.) |
o %Y |
The full year, equivalent to <<%C%y>>. It will always have at least four |
characters, but may have more. The year is accurate even when tm_year |
added to the offset of 1900 overflows an int. [tm_year] |
o %z |
The offset from UTC. The format consists of a sign (negative is west of |
Greewich), two characters for hour, then two characters for minutes |
(-hhmm or +hhmm). If tm_isdst is negative, the offset is unknown and no |
output is generated; if it is zero, the offset is the standard offset for |
the current time zone; and if it is positive, the offset is the daylight |
savings offset for the current timezone. The offset is determined from |
the TZ environment variable, as if by calling tzset(). [tm_isdst] |
o %Z |
The time zone name. If tm_isdst is negative, no output is generated. |
Otherwise, the time zone name is based on the TZ environment variable, |
as if by calling tzset(). [tm_isdst] |
o %% |
A single character, `<<%>>'. |
o- |
RETURNS |
When the formatted time takes up no more than <[maxsize]> characters, |
the result is the length of the formatted string. Otherwise, if the |
formatting operation was abandoned due to lack of room, the result is |
<<0>>, and the string starting at <[s]> corresponds to just those |
parts of <<*<[format]>>> that could be completely filled in within the |
<[maxsize]> limit. |
PORTABILITY |
ANSI C requires <<strftime>>, but does not specify the contents of |
<<*<[s]>>> when the formatted string would require more than |
<[maxsize]> characters. Unrecognized specifiers and fields of |
<<timp>> that are out of range cause undefined results. Since some |
formats expand to 0 bytes, it is wise to set <<*<[s]>>> to a nonzero |
value beforehand to distinguish between failure and an empty string. |
This implementation does not support <<s>> being NULL, nor overlapping |
<<s>> and <<format>>. |
<<strftime>> requires no supporting OS subroutines. |
BUGS |
<<strftime>> ignores the LC_TIME category of the current locale, hard-coding |
the "C" locale settings. |
*/ |
#include <newlib.h> |
#include <sys/config.h> |
#include <stddef.h> |
#include <stdio.h> |
#include <time.h> |
#include <string.h> |
#include <stdlib.h> |
#include <limits.h> |
#include <ctype.h> |
#include <wctype.h> |
/* Defines to make the file dual use for either strftime() or wcsftime(). |
* To get wcsftime, define MAKE_WCSFTIME. |
* To get strftime, do not define MAKE_WCSFTIME. |
* Names are kept friendly to strftime() usage. The biggest ugliness is the |
* use of the CQ() macro to make either regular character constants and |
* string literals or wide-character constants and wide-character-string |
* literals, as appropriate. */ |
#if !defined(MAKE_WCSFTIME) |
# define CHAR char /* string type basis */ |
# define CQ(a) a /* character constant qualifier */ |
# define SFLG /* %s flag (null for normal char) */ |
# define _ctloc(x) (ctloclen = strlen (ctloc = _CurrentTimeLocale->x), ctloc) |
# define TOLOWER(c) tolower((int)(unsigned char)(c)) |
# define STRTOUL(c,p,b) strtoul((c),(p),(b)) |
# define STRCPY(a,b) strcpy((a),(b)) |
# define STRCHR(a,b) strchr((a),(b)) |
# define STRLEN(a) strlen(a) |
# else |
# define strftime wcsftime /* Alternate function name */ |
# define CHAR wchar_t /* string type basis */ |
# define CQ(a) L##a /* character constant qualifier */ |
# define snprintf swprintf /* wide-char equivalent function name */ |
# define strncmp wcsncmp /* wide-char equivalent function name */ |
# define TOLOWER(c) towlower((wint_t)(c)) |
# define STRTOUL(c,p,b) wcstoul((c),(p),(b)) |
# define STRCPY(a,b) wcscpy((a),(b)) |
# define STRCHR(a,b) wcschr((a),(b)) |
# define STRLEN(a) wcslen(a) |
# define SFLG "l" /* %s flag (l for wide char) */ |
# ifdef __HAVE_LOCALE_INFO_EXTENDED__ |
# define _ctloc(x) (ctloclen = wcslen (ctloc = _CurrentTimeLocale->w##x), \ |
ctloc) |
# else |
# define CTLOCBUFLEN 256 /* Arbitrary big buffer size */ |
const wchar_t * |
__ctloc (wchar_t *buf, const char *elem, size_t *len_ret) |
{ |
buf[CTLOCBUFLEN - 1] = L'\0'; |
*len_ret = mbstowcs (buf, elem, CTLOCBUFLEN - 1); |
if (*len_ret == (size_t) -1 ) |
*len_ret = 0; |
return buf; |
} |
# define _ctloc(x) (ctloc = __ctloc (ctlocbuf, _CurrentTimeLocale->x, \ |
&ctloclen)) |
# endif |
#endif /* MAKE_WCSFTIME */ |
size_t _DEFUN (strftime, (s, maxsize, format, tim_p), |
CHAR *s _AND |
size_t maxsize _AND |
_CONST CHAR *format _AND |
_CONST struct tm *tim_p) |
{ |
return 0; |
} |
/programs/develop/libraries/newlib/time/time.c |
---|
0,0 → 1,53 |
/* |
FUNCTION |
<<time>>---get current calendar time (as single number) |
INDEX |
time |
ANSI_SYNOPSIS |
#include <time.h> |
time_t time(time_t *<[t]>); |
TRAD_SYNOPSIS |
#include <time.h> |
time_t time(<[t]>) |
time_t *<[t]>; |
DESCRIPTION |
<<time>> looks up the best available representation of the current |
time and returns it, encoded as a <<time_t>>. It stores the same |
value at <[t]> unless the argument is <<NULL>>. |
RETURNS |
A <<-1>> result means the current time is not available; otherwise the |
result represents the current time. |
PORTABILITY |
ANSI C requires <<time>>. |
Supporting OS subroutine required: Some implementations require |
<<gettimeofday>>. |
*/ |
/* Most times we have a system call in newlib/libc/sys/.. to do this job */ |
#include <_ansi.h> |
#include <reent.h> |
#include <sys/types.h> |
#include <sys/time.h> |
time_t |
_DEFUN (time, (t), |
time_t * t) |
{ |
struct timeval now; |
if (_gettimeofday_r (_REENT, &now, NULL) >= 0) |
{ |
if (t) |
*t = now.tv_sec; |
return now.tv_sec; |
} |
return -1; |
} |
/programs/develop/libraries/newlib/time/tzlock.c |
---|
0,0 → 1,56 |
/* |
FUNCTION |
<<__tz_lock>>, <<__tz_unlock>>---lock time zone global variables |
INDEX |
__tz_lock |
INDEX |
__tz_unlock |
ANSI_SYNOPSIS |
#include "local.h" |
void __tz_lock (void); |
void __tz_unlock (void); |
TRAD_SYNOPSIS |
void __tz_lock(); |
void __tz_unlock(); |
DESCRIPTION |
The <<tzset>> facility functions call these functions when they need to |
ensure the values of global variables. The version of these routines |
supplied in the library use the lock API defined in sys/lock.h. If multiple |
threads of execution can call the time functions and give up scheduling in |
the middle, then you you need to define your own versions of these functions |
in order to safely lock the time zone variables during a call. If you do |
not, the results of <<localtime>>, <<mktime>>, <<ctime>>, and <<strftime>> |
are undefined. |
The lock <<__tz_lock>> may not be called recursively; that is, |
a call <<__tz_lock>> will always lock all subsequent <<__tz_lock>> calls |
until the corresponding <<__tz_unlock>> call on the same thread is made. |
*/ |
#include <_ansi.h> |
#include "local.h" |
#include <sys/lock.h> |
#ifndef __SINGLE_THREAD__ |
__LOCK_INIT(static, __tz_lock_object); |
#endif |
_VOID |
_DEFUN_VOID (__tz_lock) |
{ |
#ifndef __SINGLE_THREAD__ |
__lock_acquire(__tz_lock_object); |
#endif |
} |
_VOID |
_DEFUN_VOID (__tz_unlock) |
{ |
#ifndef __SINGLE_THREAD__ |
__lock_release(__tz_lock_object); |
#endif |
} |
/programs/develop/libraries/newlib/time/tzvars.c |
---|
0,0 → 1,10 |
#include <time.h> |
/* Global timezone variables. */ |
/* Default timezone to GMT */ |
char *_tzname[2] = {"GMT", "GMT"}; |
int _daylight = 0; |
long _timezone = 0; |
/programs/develop/libraries/newlib/time |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |