From 2336060a0c2e50e09ba371eec9bc00c8ae9f54ff Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Fri, 11 Mar 2011 18:52:24 +0000 Subject: [PATCH] newlib: update git-svn-id: svn://kolibrios.org@1906 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/develop/libraries/newlib/Makefile | 386 ++++ .../libraries/newlib/argz/buf_findstr.c | 44 + .../libraries/newlib/argz/buf_findstr.h | 12 + .../develop/libraries/newlib/argz/envz_get.c | 43 + .../develop/libraries/newlib/crt/assert.c | 74 + .../develop/libraries/newlib/crt/chkstk.S | 2 +- programs/develop/libraries/newlib/crt/crt1.c | 29 +- .../develop/libraries/newlib/crt/crt_amz.S | 15 + .../develop/libraries/newlib/crt/crtdll.c | 144 ++ .../develop/libraries/newlib/crt/emutls.c | 218 ++ programs/develop/libraries/newlib/crt/exit.S | 20 + .../develop/libraries/newlib/crt/i386mach.h | 76 + .../libraries/newlib/crt/pseudo-reloc.S | 26 + .../develop/libraries/newlib/crt/setjmp.S | 89 + programs/develop/libraries/newlib/crt/start.S | 37 +- programs/develop/libraries/newlib/crt/tls.S | 48 + .../develop/libraries/newlib/ctype/isascii.c | 43 + .../develop/libraries/newlib/ctype/isblank.c | 41 + .../develop/libraries/newlib/ctype/toascii.c | 41 + .../libraries/newlib/ctype/towctrans.c | 97 + .../develop/libraries/newlib/ctype/wctrans.c | 94 + .../develop/libraries/newlib/ctype/wctype.c | 137 ++ programs/develop/libraries/newlib/dll.lds | 126 ++ .../develop/libraries/newlib/include/gthr.h | 103 + .../develop/libraries/newlib/include/newlib.h | 12 +- .../libraries/newlib/include/sys/lock.h | 4 + .../libraries/newlib/include/sys/reent.h | 20 +- programs/develop/libraries/newlib/libcdll.lds | 82 + .../develop/libraries/newlib/locale/lctype.c | 111 + .../develop/libraries/newlib/math/acosf.c | 40 + .../develop/libraries/newlib/math/acosh.c | 26 + .../develop/libraries/newlib/math/acoshf.c | 25 + .../develop/libraries/newlib/math/acoshl.c | 27 + .../develop/libraries/newlib/math/acosl.c | 25 + .../develop/libraries/newlib/math/asinf.c | 34 + .../develop/libraries/newlib/math/asinh.c | 28 + .../develop/libraries/newlib/math/asinhf.c | 28 + .../develop/libraries/newlib/math/asinhl.c | 28 + .../develop/libraries/newlib/math/asinl.c | 21 + .../develop/libraries/newlib/math/atan2f.c | 15 + .../develop/libraries/newlib/math/atan2l.c | 16 + .../develop/libraries/newlib/math/atanf.c | 28 + .../develop/libraries/newlib/math/atanh.c | 31 + .../develop/libraries/newlib/math/atanhf.c | 30 + .../develop/libraries/newlib/math/atanhl.c | 29 + .../develop/libraries/newlib/math/atanl.c | 19 + programs/develop/libraries/newlib/math/cbrt.c | 162 ++ .../develop/libraries/newlib/math/cbrtf.c | 147 ++ .../develop/libraries/newlib/math/cbrtl.c | 161 ++ programs/develop/libraries/newlib/math/ceil.S | 31 + .../develop/libraries/newlib/math/ceilf.S | 31 + .../develop/libraries/newlib/math/ceill.S | 33 + .../libraries/newlib/math/cephes_mconf.h | 395 ++++ .../develop/libraries/newlib/math/copysign.S | 19 + .../develop/libraries/newlib/math/copysignf.S | 19 + .../develop/libraries/newlib/math/copysignl.S | 20 + programs/develop/libraries/newlib/math/cos.S | 29 + programs/develop/libraries/newlib/math/cosf.S | 29 + .../develop/libraries/newlib/math/coshf.c | 3 + .../develop/libraries/newlib/math/coshl.c | 110 + programs/develop/libraries/newlib/math/cosl.S | 30 + .../develop/libraries/newlib/math/double.h | 265 +++ .../develop/libraries/newlib/math/e_atan2.c | 131 ++ .../develop/libraries/newlib/math/e_cosh.c | 90 + .../develop/libraries/newlib/math/e_hypot.c | 128 ++ .../develop/libraries/newlib/math/e_sinh.c | 83 + .../develop/libraries/newlib/math/e_sqrt.c | 452 ++++ programs/develop/libraries/newlib/math/erfl.c | 299 +++ programs/develop/libraries/newlib/math/exp.S | 49 + programs/develop/libraries/newlib/math/exp2.S | 39 + .../develop/libraries/newlib/math/exp2f.S | 39 + .../develop/libraries/newlib/math/exp2l.S | 39 + programs/develop/libraries/newlib/math/expf.c | 3 + programs/develop/libraries/newlib/math/expl.c | 71 + .../develop/libraries/newlib/math/expm1.c | 28 + .../develop/libraries/newlib/math/expm1f.c | 29 + .../develop/libraries/newlib/math/expm1l.c | 29 + programs/develop/libraries/newlib/math/fabs.c | 10 + .../develop/libraries/newlib/math/fabsf.c | 9 + .../develop/libraries/newlib/math/fabsl.c | 9 + .../develop/libraries/newlib/math/fastmath.h | 115 + programs/develop/libraries/newlib/math/fdim.c | 7 + .../develop/libraries/newlib/math/fdimf.c | 7 + .../develop/libraries/newlib/math/fdiml.c | 7 + .../develop/libraries/newlib/math/fdlibm.h | 365 ++++ .../develop/libraries/newlib/math/floor.S | 33 + .../develop/libraries/newlib/math/floorf.S | 35 + .../develop/libraries/newlib/math/floorl.S | 33 + programs/develop/libraries/newlib/math/fma.S | 12 + programs/develop/libraries/newlib/math/fmaf.S | 12 + programs/develop/libraries/newlib/math/fmal.c | 5 + programs/develop/libraries/newlib/math/fmax.c | 7 + .../develop/libraries/newlib/math/fmaxf.c | 7 + .../develop/libraries/newlib/math/fmaxl.c | 7 + programs/develop/libraries/newlib/math/fmin.c | 7 + .../develop/libraries/newlib/math/fminf.c | 7 + .../develop/libraries/newlib/math/fminl.c | 7 + .../develop/libraries/newlib/math/fmodf.c | 37 + .../develop/libraries/newlib/math/fmodl.c | 22 + .../develop/libraries/newlib/math/fp_consts.c | 14 + .../develop/libraries/newlib/math/fp_consts.h | 48 + .../libraries/newlib/math/fp_constsf.c | 12 + .../libraries/newlib/math/fp_constsl.c | 12 + .../libraries/newlib/math/fpclassify.c | 20 + .../libraries/newlib/math/fpclassifyf.c | 10 + .../libraries/newlib/math/fpclassifyl.c | 10 + .../develop/libraries/newlib/math/frexp.S | 74 + .../develop/libraries/newlib/math/frexpf.c | 3 + .../develop/libraries/newlib/math/frexpl.S | 71 + .../develop/libraries/newlib/math/fucom.c | 11 + .../develop/libraries/newlib/math/hypotf.c | 75 + .../develop/libraries/newlib/math/hypotl.c | 73 + .../develop/libraries/newlib/math/ilogb.S | 37 + .../develop/libraries/newlib/math/ilogbf.S | 35 + .../develop/libraries/newlib/math/ilogbl.S | 36 + .../develop/libraries/newlib/math/isnan.c | 14 + .../develop/libraries/newlib/math/isnanf.c | 12 + .../develop/libraries/newlib/math/isnanl.c | 13 + .../develop/libraries/newlib/math/ldexp.c | 19 + .../develop/libraries/newlib/math/ldexpf.c | 3 + .../develop/libraries/newlib/math/ldexpl.c | 19 + .../develop/libraries/newlib/math/lgamma.c | 369 ++++ .../develop/libraries/newlib/math/lgammaf.c | 253 +++ .../develop/libraries/newlib/math/lgammal.c | 416 ++++ .../develop/libraries/newlib/math/llrint.c | 10 + .../develop/libraries/newlib/math/llrintf.c | 9 + .../develop/libraries/newlib/math/llrintl.c | 10 + programs/develop/libraries/newlib/math/log.S | 38 + .../develop/libraries/newlib/math/log10.S | 48 + .../develop/libraries/newlib/math/log10f.S | 48 + .../develop/libraries/newlib/math/log10l.S | 52 + .../develop/libraries/newlib/math/log1p.S | 47 + .../develop/libraries/newlib/math/log1pf.S | 47 + .../develop/libraries/newlib/math/log1pl.S | 54 + programs/develop/libraries/newlib/math/log2.S | 51 + .../develop/libraries/newlib/math/log2f.S | 51 + .../develop/libraries/newlib/math/log2l.S | 48 + programs/develop/libraries/newlib/math/logb.c | 16 + .../develop/libraries/newlib/math/logbf.c | 16 + .../develop/libraries/newlib/math/logbl.c | 17 + programs/develop/libraries/newlib/math/logf.S | 39 + programs/develop/libraries/newlib/math/logl.S | 40 + .../develop/libraries/newlib/math/lrint.c | 9 + .../develop/libraries/newlib/math/lrintf.c | 9 + .../develop/libraries/newlib/math/lrintl.c | 10 + .../libraries/newlib/math/lround_generic.c | 64 + .../develop/libraries/newlib/math/modff.c | 22 + .../develop/libraries/newlib/math/modfl.c | 22 + .../develop/libraries/newlib/math/nearbyint.S | 30 + .../libraries/newlib/math/nearbyintf.S | 29 + .../libraries/newlib/math/nearbyintl.S | 30 + .../libraries/newlib/math/nextafterf.c | 27 + .../libraries/newlib/math/nextafterl.c | 65 + .../libraries/newlib/math/nexttoward.c | 42 + .../libraries/newlib/math/nexttowardf.c | 38 + programs/develop/libraries/newlib/math/op-1.h | 302 +++ programs/develop/libraries/newlib/math/op-2.h | 617 ++++++ programs/develop/libraries/newlib/math/op-4.h | 688 ++++++ programs/develop/libraries/newlib/math/op-8.h | 111 + .../develop/libraries/newlib/math/op-common.h | 1359 ++++++++++++ programs/develop/libraries/newlib/math/pow.c | 781 +++++++ programs/develop/libraries/newlib/math/powf.c | 3 + programs/develop/libraries/newlib/math/powi.c | 200 ++ .../develop/libraries/newlib/math/powif.c | 198 ++ .../develop/libraries/newlib/math/powil.c | 179 ++ programs/develop/libraries/newlib/math/powl.c | 804 +++++++ programs/develop/libraries/newlib/math/quad.h | 271 +++ .../develop/libraries/newlib/math/remainder.S | 19 + .../libraries/newlib/math/remainderf.S | 19 + .../libraries/newlib/math/remainderl.S | 22 + .../develop/libraries/newlib/math/remquo.S | 38 + .../develop/libraries/newlib/math/remquof.S | 38 + .../develop/libraries/newlib/math/remquol.S | 36 + programs/develop/libraries/newlib/math/rint.c | 6 + .../develop/libraries/newlib/math/rintf.c | 7 + .../develop/libraries/newlib/math/rintl.c | 7 + .../libraries/newlib/math/round_generic.c | 51 + .../libraries/newlib/math/round_internal.h | 155 ++ .../develop/libraries/newlib/math/s_erf.c | 345 +++ .../develop/libraries/newlib/math/s_expm1.S | 70 + .../libraries/newlib/math/s_fpclassify.c | 31 + .../develop/libraries/newlib/math/s_isnand.c | 31 + .../develop/libraries/newlib/math/s_modf.c | 131 ++ .../develop/libraries/newlib/math/s_roundf.c | 70 + .../develop/libraries/newlib/math/s_signbit.c | 30 + .../develop/libraries/newlib/math/s_tanh.c | 80 + .../develop/libraries/newlib/math/scalbn.S | 19 + .../develop/libraries/newlib/math/scalbnf.S | 19 + .../develop/libraries/newlib/math/scalbnl.S | 20 + .../develop/libraries/newlib/math/sf_erf.c | 267 +++ .../develop/libraries/newlib/math/signbit.c | 21 + .../develop/libraries/newlib/math/signbitf.c | 10 + .../develop/libraries/newlib/math/signbitl.c | 11 + programs/develop/libraries/newlib/math/sin.S | 30 + programs/develop/libraries/newlib/math/sinf.S | 32 + .../develop/libraries/newlib/math/single.h | 151 ++ .../develop/libraries/newlib/math/sinhf.c | 3 + .../develop/libraries/newlib/math/sinhl.c | 172 ++ programs/develop/libraries/newlib/math/sinl.S | 32 + .../develop/libraries/newlib/math/soft-fp.h | 199 ++ .../develop/libraries/newlib/math/sqrtf.c | 37 + .../develop/libraries/newlib/math/sqrtl.c | 20 + programs/develop/libraries/newlib/math/tan.S | 31 + programs/develop/libraries/newlib/math/tanf.S | 31 + .../develop/libraries/newlib/math/tanhf.c | 3 + .../develop/libraries/newlib/math/tanhl.c | 151 ++ programs/develop/libraries/newlib/math/tanl.S | 33 + .../develop/libraries/newlib/math/tgamma.c | 388 ++++ .../develop/libraries/newlib/math/tgammaf.c | 265 +++ .../develop/libraries/newlib/math/tgammal.c | 501 +++++ .../develop/libraries/newlib/math/trunc.c | 16 + .../develop/libraries/newlib/math/truncf.c | 17 + .../develop/libraries/newlib/math/truncl.c | 16 + .../develop/libraries/newlib/math/w_atan2.c | 90 + .../develop/libraries/newlib/math/w_hypot.c | 111 + programs/develop/libraries/newlib/pe/list.h | 707 +++++++ programs/develop/libraries/newlib/pe/loader.c | 652 ++++++ programs/develop/libraries/newlib/pe/pe.h | 188 ++ programs/develop/libraries/newlib/pe_app.lds | 122 ++ .../develop/libraries/newlib/reent/getreent.c | 15 +- .../libraries/newlib/reent/gettimeofdayr.c | 113 + .../develop/libraries/newlib/reent/openr.c | 177 +- .../develop/libraries/newlib/signal/signal.c | 260 +++ programs/develop/libraries/newlib/static.lds | 116 ++ .../develop/libraries/newlib/stdio/fdopen.c | 144 ++ .../develop/libraries/newlib/stdio/fgets.c | 193 ++ .../develop/libraries/newlib/stdio/fiscanf.c | 78 + .../develop/libraries/newlib/stdio/fread.c | 265 +++ .../develop/libraries/newlib/stdio/freopen.c | 250 +++ .../develop/libraries/newlib/stdio/fscanf.c | 78 + .../develop/libraries/newlib/stdio/fseeko.c | 44 + .../develop/libraries/newlib/stdio/ftell.c | 177 ++ .../develop/libraries/newlib/stdio/ftello.c | 40 + .../develop/libraries/newlib/stdio/putchar.c | 97 + .../develop/libraries/newlib/stdio/remove.c | 91 + .../develop/libraries/newlib/stdio/rename.c | 80 + .../develop/libraries/newlib/stdio/rget.c | 59 + .../develop/libraries/newlib/stdio/setvbuf.c | 198 ++ .../develop/libraries/newlib/stdio/tmpfile.c | 96 + .../develop/libraries/newlib/stdio/tmpnam.c | 209 ++ .../develop/libraries/newlib/stdio/vscanf.c | 52 + .../develop/libraries/newlib/stdio/vsscanf.c | 65 + .../libraries/newlib/stdlib/__atexit.c | 99 + .../libraries/newlib/stdlib/__call_atexit.c | 161 ++ .../develop/libraries/newlib/stdlib/atof.c | 72 + .../develop/libraries/newlib/stdlib/div.c | 132 ++ .../develop/libraries/newlib/stdlib/exit.c | 66 + .../develop/libraries/newlib/stdlib/getenv.c | 93 + .../libraries/newlib/stdlib/mallocr1.c | 1853 ----------------- .../develop/libraries/newlib/stdlib/rand.c | 91 + .../develop/libraries/newlib/stdlib/rand48.c | 179 ++ .../develop/libraries/newlib/stdlib/rand_r.c | 37 + .../develop/libraries/newlib/stdlib/seed48.c | 44 + .../develop/libraries/newlib/stdlib/srand48.c | 38 + .../develop/libraries/newlib/stdlib/strtod.c | 14 +- .../develop/libraries/newlib/stdlib/strtold.c | 42 + .../develop/libraries/newlib/stdlib/strtoll.c | 138 ++ .../libraries/newlib/stdlib/strtoll_r.c | 140 ++ .../libraries/newlib/stdlib/strtoull.c | 139 ++ .../libraries/newlib/stdlib/strtoull_r.c | 120 ++ .../develop/libraries/newlib/stdlib/system.c | 85 + .../libraries/newlib/string/strcasestr.c | 147 ++ .../develop/libraries/newlib/string/strcat.c | 104 + .../develop/libraries/newlib/string/strcoll.c | 48 + .../develop/libraries/newlib/string/strncat.c | 114 + .../develop/libraries/newlib/string/strndup.c | 16 + .../libraries/newlib/string/strndup_r.c | 27 + .../develop/libraries/newlib/string/strpbrk.c | 58 + .../develop/libraries/newlib/string/strsep.c | 19 + .../develop/libraries/newlib/string/strtok.c | 101 + .../libraries/newlib/string/strtok_r.c | 99 + .../develop/libraries/newlib/string/strupr.c | 46 + .../develop/libraries/newlib/sys/create.c | 25 + .../develop/libraries/newlib/sys/delete.c | 26 + programs/develop/libraries/newlib/sys/finfo.c | 26 + programs/develop/libraries/newlib/sys/fload.c | 37 + programs/develop/libraries/newlib/sys/fsize.c | 26 + programs/develop/libraries/newlib/sys/read.c | 31 + programs/develop/libraries/newlib/sys/write.c | 29 + .../develop/libraries/newlib/time/asctime.c | 64 + .../develop/libraries/newlib/time/asctime_r.c | 27 + .../develop/libraries/newlib/time/clock.c | 78 + .../develop/libraries/newlib/time/ctime.c | 55 + .../develop/libraries/newlib/time/ctime_r.c | 15 + .../develop/libraries/newlib/time/difftime.c | 44 + .../develop/libraries/newlib/time/gettzinfo.c | 15 + .../develop/libraries/newlib/time/gmtime.c | 68 + .../develop/libraries/newlib/time/gmtime_r.c | 14 + .../develop/libraries/newlib/time/lcltime.c | 60 + .../develop/libraries/newlib/time/lcltime_r.c | 18 + .../develop/libraries/newlib/time/local.h | 36 + .../develop/libraries/newlib/time/mktime.c | 264 +++ .../develop/libraries/newlib/time/mktm_r.c | 257 +++ .../develop/libraries/newlib/time/strftime.c | 333 +++ programs/develop/libraries/newlib/time/time.c | 53 + .../develop/libraries/newlib/time/tzlock.c | 56 + .../develop/libraries/newlib/time/tzvars.c | 10 + 297 files changed, 26930 insertions(+), 2094 deletions(-) create mode 100644 programs/develop/libraries/newlib/Makefile create mode 100644 programs/develop/libraries/newlib/argz/buf_findstr.c create mode 100644 programs/develop/libraries/newlib/argz/buf_findstr.h create mode 100644 programs/develop/libraries/newlib/argz/envz_get.c create mode 100644 programs/develop/libraries/newlib/crt/assert.c create mode 100644 programs/develop/libraries/newlib/crt/crt_amz.S create mode 100644 programs/develop/libraries/newlib/crt/crtdll.c create mode 100644 programs/develop/libraries/newlib/crt/emutls.c create mode 100644 programs/develop/libraries/newlib/crt/exit.S create mode 100644 programs/develop/libraries/newlib/crt/i386mach.h create mode 100644 programs/develop/libraries/newlib/crt/pseudo-reloc.S create mode 100644 programs/develop/libraries/newlib/crt/setjmp.S create mode 100644 programs/develop/libraries/newlib/crt/tls.S create mode 100644 programs/develop/libraries/newlib/ctype/isascii.c create mode 100644 programs/develop/libraries/newlib/ctype/isblank.c create mode 100644 programs/develop/libraries/newlib/ctype/toascii.c create mode 100644 programs/develop/libraries/newlib/ctype/towctrans.c create mode 100644 programs/develop/libraries/newlib/ctype/wctrans.c create mode 100644 programs/develop/libraries/newlib/ctype/wctype.c create mode 100644 programs/develop/libraries/newlib/dll.lds create mode 100644 programs/develop/libraries/newlib/include/gthr.h create mode 100644 programs/develop/libraries/newlib/libcdll.lds create mode 100644 programs/develop/libraries/newlib/locale/lctype.c create mode 100644 programs/develop/libraries/newlib/math/acosf.c create mode 100644 programs/develop/libraries/newlib/math/acosh.c create mode 100644 programs/develop/libraries/newlib/math/acoshf.c create mode 100644 programs/develop/libraries/newlib/math/acoshl.c create mode 100644 programs/develop/libraries/newlib/math/acosl.c create mode 100644 programs/develop/libraries/newlib/math/asinf.c create mode 100644 programs/develop/libraries/newlib/math/asinh.c create mode 100644 programs/develop/libraries/newlib/math/asinhf.c create mode 100644 programs/develop/libraries/newlib/math/asinhl.c create mode 100644 programs/develop/libraries/newlib/math/asinl.c create mode 100644 programs/develop/libraries/newlib/math/atan2f.c create mode 100644 programs/develop/libraries/newlib/math/atan2l.c create mode 100644 programs/develop/libraries/newlib/math/atanf.c create mode 100644 programs/develop/libraries/newlib/math/atanh.c create mode 100644 programs/develop/libraries/newlib/math/atanhf.c create mode 100644 programs/develop/libraries/newlib/math/atanhl.c create mode 100644 programs/develop/libraries/newlib/math/atanl.c create mode 100644 programs/develop/libraries/newlib/math/cbrt.c create mode 100644 programs/develop/libraries/newlib/math/cbrtf.c create mode 100644 programs/develop/libraries/newlib/math/cbrtl.c create mode 100644 programs/develop/libraries/newlib/math/ceil.S create mode 100644 programs/develop/libraries/newlib/math/ceilf.S create mode 100644 programs/develop/libraries/newlib/math/ceill.S create mode 100644 programs/develop/libraries/newlib/math/cephes_mconf.h create mode 100644 programs/develop/libraries/newlib/math/copysign.S create mode 100644 programs/develop/libraries/newlib/math/copysignf.S create mode 100644 programs/develop/libraries/newlib/math/copysignl.S create mode 100644 programs/develop/libraries/newlib/math/cos.S create mode 100644 programs/develop/libraries/newlib/math/cosf.S create mode 100644 programs/develop/libraries/newlib/math/coshf.c create mode 100644 programs/develop/libraries/newlib/math/coshl.c create mode 100644 programs/develop/libraries/newlib/math/cosl.S create mode 100644 programs/develop/libraries/newlib/math/double.h create mode 100644 programs/develop/libraries/newlib/math/e_atan2.c create mode 100644 programs/develop/libraries/newlib/math/e_cosh.c create mode 100644 programs/develop/libraries/newlib/math/e_hypot.c create mode 100644 programs/develop/libraries/newlib/math/e_sinh.c create mode 100644 programs/develop/libraries/newlib/math/e_sqrt.c create mode 100644 programs/develop/libraries/newlib/math/erfl.c create mode 100644 programs/develop/libraries/newlib/math/exp.S create mode 100644 programs/develop/libraries/newlib/math/exp2.S create mode 100644 programs/develop/libraries/newlib/math/exp2f.S create mode 100644 programs/develop/libraries/newlib/math/exp2l.S create mode 100644 programs/develop/libraries/newlib/math/expf.c create mode 100644 programs/develop/libraries/newlib/math/expl.c create mode 100644 programs/develop/libraries/newlib/math/expm1.c create mode 100644 programs/develop/libraries/newlib/math/expm1f.c create mode 100644 programs/develop/libraries/newlib/math/expm1l.c create mode 100644 programs/develop/libraries/newlib/math/fabs.c create mode 100644 programs/develop/libraries/newlib/math/fabsf.c create mode 100644 programs/develop/libraries/newlib/math/fabsl.c create mode 100644 programs/develop/libraries/newlib/math/fastmath.h create mode 100644 programs/develop/libraries/newlib/math/fdim.c create mode 100644 programs/develop/libraries/newlib/math/fdimf.c create mode 100644 programs/develop/libraries/newlib/math/fdiml.c create mode 100644 programs/develop/libraries/newlib/math/fdlibm.h create mode 100644 programs/develop/libraries/newlib/math/floor.S create mode 100644 programs/develop/libraries/newlib/math/floorf.S create mode 100644 programs/develop/libraries/newlib/math/floorl.S create mode 100644 programs/develop/libraries/newlib/math/fma.S create mode 100644 programs/develop/libraries/newlib/math/fmaf.S create mode 100644 programs/develop/libraries/newlib/math/fmal.c create mode 100644 programs/develop/libraries/newlib/math/fmax.c create mode 100644 programs/develop/libraries/newlib/math/fmaxf.c create mode 100644 programs/develop/libraries/newlib/math/fmaxl.c create mode 100644 programs/develop/libraries/newlib/math/fmin.c create mode 100644 programs/develop/libraries/newlib/math/fminf.c create mode 100644 programs/develop/libraries/newlib/math/fminl.c create mode 100644 programs/develop/libraries/newlib/math/fmodf.c create mode 100644 programs/develop/libraries/newlib/math/fmodl.c create mode 100644 programs/develop/libraries/newlib/math/fp_consts.c create mode 100644 programs/develop/libraries/newlib/math/fp_consts.h create mode 100644 programs/develop/libraries/newlib/math/fp_constsf.c create mode 100644 programs/develop/libraries/newlib/math/fp_constsl.c create mode 100644 programs/develop/libraries/newlib/math/fpclassify.c create mode 100644 programs/develop/libraries/newlib/math/fpclassifyf.c create mode 100644 programs/develop/libraries/newlib/math/fpclassifyl.c create mode 100644 programs/develop/libraries/newlib/math/frexp.S create mode 100644 programs/develop/libraries/newlib/math/frexpf.c create mode 100644 programs/develop/libraries/newlib/math/frexpl.S create mode 100644 programs/develop/libraries/newlib/math/fucom.c create mode 100644 programs/develop/libraries/newlib/math/hypotf.c create mode 100644 programs/develop/libraries/newlib/math/hypotl.c create mode 100644 programs/develop/libraries/newlib/math/ilogb.S create mode 100644 programs/develop/libraries/newlib/math/ilogbf.S create mode 100644 programs/develop/libraries/newlib/math/ilogbl.S create mode 100644 programs/develop/libraries/newlib/math/isnan.c create mode 100644 programs/develop/libraries/newlib/math/isnanf.c create mode 100644 programs/develop/libraries/newlib/math/isnanl.c create mode 100644 programs/develop/libraries/newlib/math/ldexp.c create mode 100644 programs/develop/libraries/newlib/math/ldexpf.c create mode 100644 programs/develop/libraries/newlib/math/ldexpl.c create mode 100644 programs/develop/libraries/newlib/math/lgamma.c create mode 100644 programs/develop/libraries/newlib/math/lgammaf.c create mode 100644 programs/develop/libraries/newlib/math/lgammal.c create mode 100644 programs/develop/libraries/newlib/math/llrint.c create mode 100644 programs/develop/libraries/newlib/math/llrintf.c create mode 100644 programs/develop/libraries/newlib/math/llrintl.c create mode 100644 programs/develop/libraries/newlib/math/log.S create mode 100644 programs/develop/libraries/newlib/math/log10.S create mode 100644 programs/develop/libraries/newlib/math/log10f.S create mode 100644 programs/develop/libraries/newlib/math/log10l.S create mode 100644 programs/develop/libraries/newlib/math/log1p.S create mode 100644 programs/develop/libraries/newlib/math/log1pf.S create mode 100644 programs/develop/libraries/newlib/math/log1pl.S create mode 100644 programs/develop/libraries/newlib/math/log2.S create mode 100644 programs/develop/libraries/newlib/math/log2f.S create mode 100644 programs/develop/libraries/newlib/math/log2l.S create mode 100644 programs/develop/libraries/newlib/math/logb.c create mode 100644 programs/develop/libraries/newlib/math/logbf.c create mode 100644 programs/develop/libraries/newlib/math/logbl.c create mode 100644 programs/develop/libraries/newlib/math/logf.S create mode 100644 programs/develop/libraries/newlib/math/logl.S create mode 100644 programs/develop/libraries/newlib/math/lrint.c create mode 100644 programs/develop/libraries/newlib/math/lrintf.c create mode 100644 programs/develop/libraries/newlib/math/lrintl.c create mode 100644 programs/develop/libraries/newlib/math/lround_generic.c create mode 100644 programs/develop/libraries/newlib/math/modff.c create mode 100644 programs/develop/libraries/newlib/math/modfl.c create mode 100644 programs/develop/libraries/newlib/math/nearbyint.S create mode 100644 programs/develop/libraries/newlib/math/nearbyintf.S create mode 100644 programs/develop/libraries/newlib/math/nearbyintl.S create mode 100644 programs/develop/libraries/newlib/math/nextafterf.c create mode 100644 programs/develop/libraries/newlib/math/nextafterl.c create mode 100644 programs/develop/libraries/newlib/math/nexttoward.c create mode 100644 programs/develop/libraries/newlib/math/nexttowardf.c create mode 100644 programs/develop/libraries/newlib/math/op-1.h create mode 100644 programs/develop/libraries/newlib/math/op-2.h create mode 100644 programs/develop/libraries/newlib/math/op-4.h create mode 100644 programs/develop/libraries/newlib/math/op-8.h create mode 100644 programs/develop/libraries/newlib/math/op-common.h create mode 100644 programs/develop/libraries/newlib/math/pow.c create mode 100644 programs/develop/libraries/newlib/math/powf.c create mode 100644 programs/develop/libraries/newlib/math/powi.c create mode 100644 programs/develop/libraries/newlib/math/powif.c create mode 100644 programs/develop/libraries/newlib/math/powil.c create mode 100644 programs/develop/libraries/newlib/math/powl.c create mode 100644 programs/develop/libraries/newlib/math/quad.h create mode 100644 programs/develop/libraries/newlib/math/remainder.S create mode 100644 programs/develop/libraries/newlib/math/remainderf.S create mode 100644 programs/develop/libraries/newlib/math/remainderl.S create mode 100644 programs/develop/libraries/newlib/math/remquo.S create mode 100644 programs/develop/libraries/newlib/math/remquof.S create mode 100644 programs/develop/libraries/newlib/math/remquol.S create mode 100644 programs/develop/libraries/newlib/math/rint.c create mode 100644 programs/develop/libraries/newlib/math/rintf.c create mode 100644 programs/develop/libraries/newlib/math/rintl.c create mode 100644 programs/develop/libraries/newlib/math/round_generic.c create mode 100644 programs/develop/libraries/newlib/math/round_internal.h create mode 100644 programs/develop/libraries/newlib/math/s_erf.c create mode 100644 programs/develop/libraries/newlib/math/s_expm1.S create mode 100644 programs/develop/libraries/newlib/math/s_fpclassify.c create mode 100644 programs/develop/libraries/newlib/math/s_isnand.c create mode 100644 programs/develop/libraries/newlib/math/s_modf.c create mode 100644 programs/develop/libraries/newlib/math/s_roundf.c create mode 100644 programs/develop/libraries/newlib/math/s_signbit.c create mode 100644 programs/develop/libraries/newlib/math/s_tanh.c create mode 100644 programs/develop/libraries/newlib/math/scalbn.S create mode 100644 programs/develop/libraries/newlib/math/scalbnf.S create mode 100644 programs/develop/libraries/newlib/math/scalbnl.S create mode 100644 programs/develop/libraries/newlib/math/sf_erf.c create mode 100644 programs/develop/libraries/newlib/math/signbit.c create mode 100644 programs/develop/libraries/newlib/math/signbitf.c create mode 100644 programs/develop/libraries/newlib/math/signbitl.c create mode 100644 programs/develop/libraries/newlib/math/sin.S create mode 100644 programs/develop/libraries/newlib/math/sinf.S create mode 100644 programs/develop/libraries/newlib/math/single.h create mode 100644 programs/develop/libraries/newlib/math/sinhf.c create mode 100644 programs/develop/libraries/newlib/math/sinhl.c create mode 100644 programs/develop/libraries/newlib/math/sinl.S create mode 100644 programs/develop/libraries/newlib/math/soft-fp.h create mode 100644 programs/develop/libraries/newlib/math/sqrtf.c create mode 100644 programs/develop/libraries/newlib/math/sqrtl.c create mode 100644 programs/develop/libraries/newlib/math/tan.S create mode 100644 programs/develop/libraries/newlib/math/tanf.S create mode 100644 programs/develop/libraries/newlib/math/tanhf.c create mode 100644 programs/develop/libraries/newlib/math/tanhl.c create mode 100644 programs/develop/libraries/newlib/math/tanl.S create mode 100644 programs/develop/libraries/newlib/math/tgamma.c create mode 100644 programs/develop/libraries/newlib/math/tgammaf.c create mode 100644 programs/develop/libraries/newlib/math/tgammal.c create mode 100644 programs/develop/libraries/newlib/math/trunc.c create mode 100644 programs/develop/libraries/newlib/math/truncf.c create mode 100644 programs/develop/libraries/newlib/math/truncl.c create mode 100644 programs/develop/libraries/newlib/math/w_atan2.c create mode 100644 programs/develop/libraries/newlib/math/w_hypot.c create mode 100644 programs/develop/libraries/newlib/pe/list.h create mode 100644 programs/develop/libraries/newlib/pe/loader.c create mode 100644 programs/develop/libraries/newlib/pe/pe.h create mode 100644 programs/develop/libraries/newlib/pe_app.lds create mode 100644 programs/develop/libraries/newlib/reent/gettimeofdayr.c create mode 100644 programs/develop/libraries/newlib/signal/signal.c create mode 100644 programs/develop/libraries/newlib/static.lds create mode 100644 programs/develop/libraries/newlib/stdio/fdopen.c create mode 100644 programs/develop/libraries/newlib/stdio/fgets.c create mode 100644 programs/develop/libraries/newlib/stdio/fiscanf.c create mode 100644 programs/develop/libraries/newlib/stdio/fread.c create mode 100644 programs/develop/libraries/newlib/stdio/freopen.c create mode 100644 programs/develop/libraries/newlib/stdio/fscanf.c create mode 100644 programs/develop/libraries/newlib/stdio/fseeko.c create mode 100644 programs/develop/libraries/newlib/stdio/ftell.c create mode 100644 programs/develop/libraries/newlib/stdio/ftello.c create mode 100644 programs/develop/libraries/newlib/stdio/putchar.c create mode 100644 programs/develop/libraries/newlib/stdio/remove.c create mode 100644 programs/develop/libraries/newlib/stdio/rename.c create mode 100644 programs/develop/libraries/newlib/stdio/rget.c create mode 100644 programs/develop/libraries/newlib/stdio/setvbuf.c create mode 100644 programs/develop/libraries/newlib/stdio/tmpfile.c create mode 100644 programs/develop/libraries/newlib/stdio/tmpnam.c create mode 100644 programs/develop/libraries/newlib/stdio/vscanf.c create mode 100644 programs/develop/libraries/newlib/stdio/vsscanf.c create mode 100644 programs/develop/libraries/newlib/stdlib/__atexit.c create mode 100644 programs/develop/libraries/newlib/stdlib/__call_atexit.c create mode 100644 programs/develop/libraries/newlib/stdlib/atof.c create mode 100644 programs/develop/libraries/newlib/stdlib/div.c create mode 100644 programs/develop/libraries/newlib/stdlib/exit.c create mode 100644 programs/develop/libraries/newlib/stdlib/getenv.c delete mode 100644 programs/develop/libraries/newlib/stdlib/mallocr1.c create mode 100644 programs/develop/libraries/newlib/stdlib/rand.c create mode 100644 programs/develop/libraries/newlib/stdlib/rand48.c create mode 100644 programs/develop/libraries/newlib/stdlib/rand_r.c create mode 100644 programs/develop/libraries/newlib/stdlib/seed48.c create mode 100644 programs/develop/libraries/newlib/stdlib/srand48.c create mode 100644 programs/develop/libraries/newlib/stdlib/strtold.c create mode 100644 programs/develop/libraries/newlib/stdlib/strtoll.c create mode 100644 programs/develop/libraries/newlib/stdlib/strtoll_r.c create mode 100644 programs/develop/libraries/newlib/stdlib/strtoull.c create mode 100644 programs/develop/libraries/newlib/stdlib/strtoull_r.c create mode 100644 programs/develop/libraries/newlib/stdlib/system.c create mode 100644 programs/develop/libraries/newlib/string/strcasestr.c create mode 100644 programs/develop/libraries/newlib/string/strcat.c create mode 100644 programs/develop/libraries/newlib/string/strcoll.c create mode 100644 programs/develop/libraries/newlib/string/strncat.c create mode 100644 programs/develop/libraries/newlib/string/strndup.c create mode 100644 programs/develop/libraries/newlib/string/strndup_r.c create mode 100644 programs/develop/libraries/newlib/string/strpbrk.c create mode 100644 programs/develop/libraries/newlib/string/strsep.c create mode 100644 programs/develop/libraries/newlib/string/strtok.c create mode 100644 programs/develop/libraries/newlib/string/strtok_r.c create mode 100644 programs/develop/libraries/newlib/string/strupr.c create mode 100644 programs/develop/libraries/newlib/sys/create.c create mode 100644 programs/develop/libraries/newlib/sys/delete.c create mode 100644 programs/develop/libraries/newlib/sys/finfo.c create mode 100644 programs/develop/libraries/newlib/sys/fload.c create mode 100644 programs/develop/libraries/newlib/sys/fsize.c create mode 100644 programs/develop/libraries/newlib/sys/read.c create mode 100644 programs/develop/libraries/newlib/sys/write.c create mode 100644 programs/develop/libraries/newlib/time/asctime.c create mode 100644 programs/develop/libraries/newlib/time/asctime_r.c create mode 100644 programs/develop/libraries/newlib/time/clock.c create mode 100644 programs/develop/libraries/newlib/time/ctime.c create mode 100644 programs/develop/libraries/newlib/time/ctime_r.c create mode 100644 programs/develop/libraries/newlib/time/difftime.c create mode 100644 programs/develop/libraries/newlib/time/gettzinfo.c create mode 100644 programs/develop/libraries/newlib/time/gmtime.c create mode 100644 programs/develop/libraries/newlib/time/gmtime_r.c create mode 100644 programs/develop/libraries/newlib/time/lcltime.c create mode 100644 programs/develop/libraries/newlib/time/lcltime_r.c create mode 100644 programs/develop/libraries/newlib/time/local.h create mode 100644 programs/develop/libraries/newlib/time/mktime.c create mode 100644 programs/develop/libraries/newlib/time/mktm_r.c create mode 100644 programs/develop/libraries/newlib/time/strftime.c create mode 100644 programs/develop/libraries/newlib/time/time.c create mode 100644 programs/develop/libraries/newlib/time/tzlock.c create mode 100644 programs/develop/libraries/newlib/time/tzvars.c diff --git a/programs/develop/libraries/newlib/Makefile b/programs/develop/libraries/newlib/Makefile new file mode 100644 index 0000000000..7bcdfb1a2c --- /dev/null +++ b/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 + + diff --git a/programs/develop/libraries/newlib/argz/buf_findstr.c b/programs/develop/libraries/newlib/argz/buf_findstr.c new file mode 100644 index 0000000000..4a4d8cee5e --- /dev/null +++ b/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 +#include +#include +#include + +#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; +} diff --git a/programs/develop/libraries/newlib/argz/buf_findstr.h b/programs/develop/libraries/newlib/argz/buf_findstr.h new file mode 100644 index 0000000000..a8a18292fb --- /dev/null +++ b/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 + +/* 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); diff --git a/programs/develop/libraries/newlib/argz/envz_get.c b/programs/develop/libraries/newlib/argz/envz_get.c new file mode 100644 index 0000000000..253cc85d8e --- /dev/null +++ b/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 +#include +#include +#include +#include + +#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; +} diff --git a/programs/develop/libraries/newlib/crt/assert.c b/programs/develop/libraries/newlib/crt/assert.c new file mode 100644 index 0000000000..962b28819f --- /dev/null +++ b/programs/develop/libraries/newlib/crt/assert.c @@ -0,0 +1,74 @@ +/* +FUNCTION +<>---macro for debugging diagnostics + +INDEX + assert + +ANSI_SYNOPSIS + #include + 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), <> + calls <>, 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 + <> at compile time by defining <> as a + preprocessor variable. If you do this, the <> macro + expands to + +. (void(0)) + +RETURNS + <> does not return a value. + +PORTABILITY + The <> macro is required by ANSI, as is the behavior + when <> is defined. + +Supporting OS subroutines required (only if enabled): <>, <>, +<>, <>, <>, <>, <>, <>, <>. +*/ + +#include +#include +#include + +/* 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 */ +} diff --git a/programs/develop/libraries/newlib/crt/chkstk.S b/programs/develop/libraries/newlib/crt/chkstk.S index cbc1e5264f..a1c6a4f68e 100644 --- a/programs/develop/libraries/newlib/crt/chkstk.S +++ b/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 @@ __alloca: int3 #trap to debugger .ascii "Stack overflow" + diff --git a/programs/develop/libraries/newlib/crt/crt1.c b/programs/develop/libraries/newlib/crt/crt1.c index 1db80911fd..6486989899 100644 --- a/programs/develop/libraries/newlib/crt/crt1.c +++ b/programs/develop/libraries/newlib/crt/crt1.c @@ -16,6 +16,9 @@ #include #include #include +#include +#include + #include "cpu_features.h" @@ -51,8 +54,6 @@ char * __libc_getenv(const char *name) } void __main (){}; - - void init_reent(); void __attribute__((noreturn)) @@ -73,10 +74,25 @@ __thread_startup (int (*entry)(void*), void *param, _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 @@ __crt_startup (void) __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,13 +129,14 @@ __crt_startup (void) */ // _mingw32_init_fmode (); + nRet = main (_argc, _argv, NULL); /* * Perform exit processing for the C library. This means * flushing output and calling 'atexit' registered functions. */ - _exit (nRet); + exit (nRet); } diff --git a/programs/develop/libraries/newlib/crt/crt_amz.S b/programs/develop/libraries/newlib/crt/crt_amz.S new file mode 100644 index 0000000000..4a8865687d --- /dev/null +++ b/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 + + diff --git a/programs/develop/libraries/newlib/crt/crtdll.c b/programs/develop/libraries/newlib/crt/crtdll.c new file mode 100644 index 0000000000..3358f03a5b --- /dev/null +++ b/programs/develop/libraries/newlib/crt/crtdll.c @@ -0,0 +1,144 @@ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} + + diff --git a/programs/develop/libraries/newlib/crt/emutls.c b/programs/develop/libraries/newlib/crt/emutls.c new file mode 100644 index 0000000000..c9a6907309 --- /dev/null +++ b/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 . + +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 +. */ + + +#include +#include +#include +#include +#include + +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; +} diff --git a/programs/develop/libraries/newlib/crt/exit.S b/programs/develop/libraries/newlib/crt/exit.S new file mode 100644 index 0000000000..927132c9ca --- /dev/null +++ b/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 + diff --git a/programs/develop/libraries/newlib/crt/i386mach.h b/programs/develop/libraries/newlib/crt/i386mach.h new file mode 100644 index 0000000000..914f426829 --- /dev/null +++ b/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 + diff --git a/programs/develop/libraries/newlib/crt/pseudo-reloc.S b/programs/develop/libraries/newlib/crt/pseudo-reloc.S new file mode 100644 index 0000000000..cf7387d182 --- /dev/null +++ b/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 + diff --git a/programs/develop/libraries/newlib/crt/setjmp.S b/programs/develop/libraries/newlib/crt/setjmp.S new file mode 100644 index 0000000000..cdcd7f566f --- /dev/null +++ b/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 diff --git a/programs/develop/libraries/newlib/crt/start.S b/programs/develop/libraries/newlib/crt/start.S index 4f562e6c87..3b96063fd7 100644 --- a/programs/develop/libraries/newlib/crt/start.S +++ b/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 @@ __start: 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 diff --git a/programs/develop/libraries/newlib/crt/tls.S b/programs/develop/libraries/newlib/crt/tls.S new file mode 100644 index 0000000000..e8647bf375 --- /dev/null +++ b/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 diff --git a/programs/develop/libraries/newlib/ctype/isascii.c b/programs/develop/libraries/newlib/ctype/isascii.c new file mode 100644 index 0000000000..ff0766f1b4 --- /dev/null +++ b/programs/develop/libraries/newlib/ctype/isascii.c @@ -0,0 +1,43 @@ +/* +FUNCTION + <>---ASCII character predicate + +INDEX + isascii + +ANSI_SYNOPSIS + #include + int isascii(int <[c]>); + +TRAD_SYNOPSIS + #include + int isascii(<[c]>); + +DESCRIPTION +<> 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 +<> returns non-zero if the low order byte of <[c]> is in the range +0 to 127 (<<0x00>>--<<0x7F>>). + +PORTABILITY +<> is ANSI C. + +No supporting OS subroutines are required. +*/ +#include <_ansi.h> +#include + + + +#undef isascii + +int +_DEFUN(isascii,(c),int c) +{ + return c >= 0 && c< 128; +} diff --git a/programs/develop/libraries/newlib/ctype/isblank.c b/programs/develop/libraries/newlib/ctype/isblank.c new file mode 100644 index 0000000000..c6ab2e11e3 --- /dev/null +++ b/programs/develop/libraries/newlib/ctype/isblank.c @@ -0,0 +1,41 @@ + +/* +FUNCTION + <>---blank character predicate + +INDEX + isblank + +ANSI_SYNOPSIS + #include + int isblank(int <[c]>); + +TRAD_SYNOPSIS + #include + int isblank(<[c]>); + +DESCRIPTION +<> 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 +<> returns non-zero if <[c]> is a blank character. + +PORTABILITY +<> is C99. + +No supporting OS subroutines are required. +*/ + +#include <_ansi.h> +#include + + + +#undef isblank +int +_DEFUN(isblank,(c),int c) +{ + return ((__ctype_ptr__[c+1] & _B) || (c == '\t')); +} diff --git a/programs/develop/libraries/newlib/ctype/toascii.c b/programs/develop/libraries/newlib/ctype/toascii.c new file mode 100644 index 0000000000..50a1752c3e --- /dev/null +++ b/programs/develop/libraries/newlib/ctype/toascii.c @@ -0,0 +1,41 @@ +/* +FUNCTION + <>---force integers to ASCII range + +INDEX + toascii + +ANSI_SYNOPSIS + #include + int toascii(int <[c]>); + +TRAD_SYNOPSIS + #include + int toascii(<[c]>); + int (<[c]>); + +DESCRIPTION +<> 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 +<> returns integers between 0 and 127. + +PORTABILITY +<> is not ANSI C. + +No supporting OS subroutines are required. +*/ + +#include <_ansi.h> +#include +#undef toascii + +int +_DEFUN(toascii,(c),int c) +{ + return (c)&0177; +} + diff --git a/programs/develop/libraries/newlib/ctype/towctrans.c b/programs/develop/libraries/newlib/ctype/towctrans.c new file mode 100644 index 0000000000..dbad853b76 --- /dev/null +++ b/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 + <>---extensible wide-character translation + +INDEX + towctrans + +ANSI_SYNOPSIS + #include + wint_t towctrans(wint_t <[c]>, wctrans_t <[w]>); + +TRAD_SYNOPSIS + #include + wint_t towctrans(<[c]>, <[w]>) + wint_t <[c]>; + wctrans_t <[w]>; + + +DESCRIPTION +<> 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 +<> 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, <> is set <>. + +PORTABILITY +<> is C99. + +No supporting OS subroutines are required. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#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 */ diff --git a/programs/develop/libraries/newlib/ctype/wctrans.c b/programs/develop/libraries/newlib/ctype/wctrans.c new file mode 100644 index 0000000000..4a51ce895d --- /dev/null +++ b/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 + <>---get wide-character translation type + +INDEX + wctrans + +ANSI_SYNOPSIS + #include + wctrans_t wctrans(const char *<[c]>); + +TRAD_SYNOPSIS + #include + wctrans_t wctrans(<[c]>) + const char * <[c]>; + + +DESCRIPTION +<> 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 +<> returns 0 and sets <> to <> if the +given name is invalid. Otherwise, it returns a valid non-zero wctrans_t +value. + +PORTABILITY +<> is C99. + +No supporting OS subroutines are required. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#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 */ diff --git a/programs/develop/libraries/newlib/ctype/wctype.c b/programs/develop/libraries/newlib/ctype/wctype.c new file mode 100644 index 0000000000..6ac839e8d6 --- /dev/null +++ b/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 + <>---get wide-character classification type + +INDEX + wctype + +ANSI_SYNOPSIS + #include + wctype_t wctype(const char *<[c]>); + +TRAD_SYNOPSIS + #include + wctype_t wctype(<[c]>) + const char * <[c]>; + + +DESCRIPTION +<> 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 +<> returns 0 and sets <> to <> if the +given name is invalid. Otherwise, it returns a valid non-zero wctype_t +value. + +PORTABILITY +<> is C99. + +No supporting OS subroutines are required. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#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 */ diff --git a/programs/develop/libraries/newlib/dll.lds b/programs/develop/libraries/newlib/dll.lds new file mode 100644 index 0000000000..1c44270fca --- /dev/null +++ b/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) + } + +} + diff --git a/programs/develop/libraries/newlib/include/gthr.h b/programs/develop/libraries/newlib/include/gthr.h new file mode 100644 index 0000000000..7243835866 --- /dev/null +++ b/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 +. */ + +#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 diff --git a/programs/develop/libraries/newlib/include/newlib.h b/programs/develop/libraries/newlib/include/newlib.h index a404a25aa2..2152f8b0de 100644 --- a/programs/develop/libraries/newlib/include/newlib.h +++ b/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_ */ diff --git a/programs/develop/libraries/newlib/include/sys/lock.h b/programs/develop/libraries/newlib/include/sys/lock.h index 07ad90f0c3..725b73aec8 100644 --- a/programs/develop/libraries/newlib/include/sys/lock.h +++ b/programs/develop/libraries/newlib/include/sys/lock.h @@ -27,9 +27,13 @@ typedef __libc_lock_recursive_t _LOCK_RECURSIVE_T; #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; diff --git a/programs/develop/libraries/newlib/include/sys/reent.h b/programs/develop/libraries/newlib/include/sys/reent.h index a9f55777e8..4c33bf880a 100644 --- a/programs/develop/libraries/newlib/include/sys/reent.h +++ b/programs/develop/libraries/newlib/include/sys/reent.h @@ -822,19 +822,17 @@ void _reclaim_reent _PARAMS ((struct _reent *)); /* #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 diff --git a/programs/develop/libraries/newlib/libcdll.lds b/programs/develop/libraries/newlib/libcdll.lds new file mode 100644 index 0000000000..93f120f472 --- /dev/null +++ b/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) + } + +} + diff --git a/programs/develop/libraries/newlib/locale/lctype.c b/programs/develop/libraries/newlib/locale/lctype.c new file mode 100644 index 0000000000..d043fe00e9 --- /dev/null +++ b/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 +#include +#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); +} diff --git a/programs/develop/libraries/newlib/math/acosf.c b/programs/develop/libraries/newlib/math/acosf.c new file mode 100644 index 0000000000..e756168a7f --- /dev/null +++ b/programs/develop/libraries/newlib/math/acosf.c @@ -0,0 +1,40 @@ +/* + * Written by J.T. Conklin . + * Public domain. + */ + +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/acosh.c b/programs/develop/libraries/newlib/math/acosh.c new file mode 100644 index 0000000000..cf61712610 --- /dev/null +++ b/programs/develop/libraries/newlib/math/acosh.c @@ -0,0 +1,26 @@ +#include +#include +#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))); +} diff --git a/programs/develop/libraries/newlib/math/acoshf.c b/programs/develop/libraries/newlib/math/acoshf.c new file mode 100644 index 0000000000..d2c0f22aad --- /dev/null +++ b/programs/develop/libraries/newlib/math/acoshf.c @@ -0,0 +1,25 @@ +#include +#include +#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))); +} diff --git a/programs/develop/libraries/newlib/math/acoshl.c b/programs/develop/libraries/newlib/math/acoshl.c new file mode 100644 index 0000000000..9a005be287 --- /dev/null +++ b/programs/develop/libraries/newlib/math/acoshl.c @@ -0,0 +1,27 @@ +#include +#include +#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))); +} diff --git a/programs/develop/libraries/newlib/math/acosl.c b/programs/develop/libraries/newlib/math/acosl.c new file mode 100644 index 0000000000..0eaea62787 --- /dev/null +++ b/programs/develop/libraries/newlib/math/acosl.c @@ -0,0 +1,25 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/asinf.c b/programs/develop/libraries/newlib/math/asinf.c new file mode 100644 index 0000000000..14e43f4ec0 --- /dev/null +++ b/programs/develop/libraries/newlib/math/asinf.c @@ -0,0 +1,34 @@ +/* + * Written by J.T. Conklin . + * 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; +} diff --git a/programs/develop/libraries/newlib/math/asinh.c b/programs/develop/libraries/newlib/math/asinh.c new file mode 100644 index 0000000000..fba07eb4f8 --- /dev/null +++ b/programs/develop/libraries/newlib/math/asinh.c @@ -0,0 +1,28 @@ +#include +#include +#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); +} + diff --git a/programs/develop/libraries/newlib/math/asinhf.c b/programs/develop/libraries/newlib/math/asinhf.c new file mode 100644 index 0000000000..5f65679182 --- /dev/null +++ b/programs/develop/libraries/newlib/math/asinhf.c @@ -0,0 +1,28 @@ +#include +#include +#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); +} diff --git a/programs/develop/libraries/newlib/math/asinhl.c b/programs/develop/libraries/newlib/math/asinhl.c new file mode 100644 index 0000000000..aff076a909 --- /dev/null +++ b/programs/develop/libraries/newlib/math/asinhl.c @@ -0,0 +1,28 @@ +#include +#include +#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); +} diff --git a/programs/develop/libraries/newlib/math/asinl.c b/programs/develop/libraries/newlib/math/asinl.c new file mode 100644 index 0000000000..916efe448d --- /dev/null +++ b/programs/develop/libraries/newlib/math/asinl.c @@ -0,0 +1,21 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Adapted for long double type by Danny Smith . + */ + +/* 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; +} diff --git a/programs/develop/libraries/newlib/math/atan2f.c b/programs/develop/libraries/newlib/math/atan2f.c new file mode 100644 index 0000000000..c31f43b91e --- /dev/null +++ b/programs/develop/libraries/newlib/math/atan2f.c @@ -0,0 +1,15 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + */ + +#include + +float +atan2f (float y, float x) +{ + float res; + asm ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)"); + return res; +} diff --git a/programs/develop/libraries/newlib/math/atan2l.c b/programs/develop/libraries/newlib/math/atan2l.c new file mode 100644 index 0000000000..b2ea7e9ff6 --- /dev/null +++ b/programs/develop/libraries/newlib/math/atan2l.c @@ -0,0 +1,16 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +#include + +long double +atan2l (long double y, long double x) +{ + long double res; + asm ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)"); + return res; +} diff --git a/programs/develop/libraries/newlib/math/atanf.c b/programs/develop/libraries/newlib/math/atanf.c new file mode 100644 index 0000000000..52bc48c1fc --- /dev/null +++ b/programs/develop/libraries/newlib/math/atanf.c @@ -0,0 +1,28 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + */ + +#include + +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; +} + diff --git a/programs/develop/libraries/newlib/math/atanh.c b/programs/develop/libraries/newlib/math/atanh.c new file mode 100644 index 0000000000..806bda1f73 --- /dev/null +++ b/programs/develop/libraries/newlib/math/atanh.c @@ -0,0 +1,31 @@ +#include +#include +#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; +} diff --git a/programs/develop/libraries/newlib/math/atanhf.c b/programs/develop/libraries/newlib/math/atanhf.c new file mode 100644 index 0000000000..656ec71f98 --- /dev/null +++ b/programs/develop/libraries/newlib/math/atanhf.c @@ -0,0 +1,30 @@ +#include +#include +#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; +} diff --git a/programs/develop/libraries/newlib/math/atanhl.c b/programs/develop/libraries/newlib/math/atanhl.c new file mode 100644 index 0000000000..040a46c33a --- /dev/null +++ b/programs/develop/libraries/newlib/math/atanhl.c @@ -0,0 +1,29 @@ +#include +#include +#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; +} diff --git a/programs/develop/libraries/newlib/math/atanl.c b/programs/develop/libraries/newlib/math/atanl.c new file mode 100644 index 0000000000..800194f032 --- /dev/null +++ b/programs/develop/libraries/newlib/math/atanl.c @@ -0,0 +1,19 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +#include + +long double +atanl (long double x) +{ + long double res; + + asm ("fld1\n\t" + "fpatan" + : "=t" (res) : "0" (x)); + return res; +} diff --git a/programs/develop/libraries/newlib/math/cbrt.c b/programs/develop/libraries/newlib/math/cbrt.c new file mode 100644 index 0000000000..7644090cc4 --- /dev/null +++ b/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 + */ +#ifdef __MINGW32__ +#include +#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); +} diff --git a/programs/develop/libraries/newlib/math/cbrtf.c b/programs/develop/libraries/newlib/math/cbrtf.c new file mode 100644 index 0000000000..03af6a61e5 --- /dev/null +++ b/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 + */ +#ifdef __MINGW32__ +#include +#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); +} diff --git a/programs/develop/libraries/newlib/math/cbrtl.c b/programs/develop/libraries/newlib/math/cbrtl.c new file mode 100644 index 0000000000..486531d01a --- /dev/null +++ b/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 + */ +#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); +} diff --git a/programs/develop/libraries/newlib/math/ceil.S b/programs/develop/libraries/newlib/math/ceil.S new file mode 100644 index 0000000000..54c3211251 --- /dev/null +++ b/programs/develop/libraries/newlib/math/ceil.S @@ -0,0 +1,31 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/ceilf.S b/programs/develop/libraries/newlib/math/ceilf.S new file mode 100644 index 0000000000..a973a7d73e --- /dev/null +++ b/programs/develop/libraries/newlib/math/ceilf.S @@ -0,0 +1,31 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/ceill.S b/programs/develop/libraries/newlib/math/ceill.S new file mode 100644 index 0000000000..09625c2771 --- /dev/null +++ b/programs/develop/libraries/newlib/math/ceill.S @@ -0,0 +1,33 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Changes for long double by Ulrich Drepper + */ + + + .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 diff --git a/programs/develop/libraries/newlib/math/cephes_mconf.h b/programs/develop/libraries/newlib/math/cephes_mconf.h new file mode 100644 index 0000000000..e328bb23b7 --- /dev/null +++ b/programs/develop/libraries/newlib/math/cephes_mconf.h @@ -0,0 +1,395 @@ +#include +#include + + +#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. + * 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 diff --git a/programs/develop/libraries/newlib/math/copysignf.S b/programs/develop/libraries/newlib/math/copysignf.S new file mode 100644 index 0000000000..0e54e54de5 --- /dev/null +++ b/programs/develop/libraries/newlib/math/copysignf.S @@ -0,0 +1,19 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/copysignl.S b/programs/develop/libraries/newlib/math/copysignl.S new file mode 100644 index 0000000000..7c82274716 --- /dev/null +++ b/programs/develop/libraries/newlib/math/copysignl.S @@ -0,0 +1,20 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * 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 diff --git a/programs/develop/libraries/newlib/math/cos.S b/programs/develop/libraries/newlib/math/cos.S new file mode 100644 index 0000000000..9a049fafe0 --- /dev/null +++ b/programs/develop/libraries/newlib/math/cos.S @@ -0,0 +1,29 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Removed glibc header dependancy by Danny Smith + * + */ + .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 diff --git a/programs/develop/libraries/newlib/math/cosf.S b/programs/develop/libraries/newlib/math/cosf.S new file mode 100644 index 0000000000..21616a14bf --- /dev/null +++ b/programs/develop/libraries/newlib/math/cosf.S @@ -0,0 +1,29 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Removed glibc header dependancy by Danny Smith + * + */ + .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 diff --git a/programs/develop/libraries/newlib/math/coshf.c b/programs/develop/libraries/newlib/math/coshf.c new file mode 100644 index 0000000000..dbd1345ab4 --- /dev/null +++ b/programs/develop/libraries/newlib/math/coshf.c @@ -0,0 +1,3 @@ +#include +float coshf (float x) + {return (float) cosh (x);} diff --git a/programs/develop/libraries/newlib/math/coshl.c b/programs/develop/libraries/newlib/math/coshl.c new file mode 100644 index 0000000000..e09f0f01de --- /dev/null +++ b/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 +*/ + +#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 ); +} diff --git a/programs/develop/libraries/newlib/math/cosl.S b/programs/develop/libraries/newlib/math/cosl.S new file mode 100644 index 0000000000..b7b2d970de --- /dev/null +++ b/programs/develop/libraries/newlib/math/cosl.S @@ -0,0 +1,30 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Removed glibc header dependancy by Danny Smith + * + */ + .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 diff --git a/programs/develop/libraries/newlib/math/double.h b/programs/develop/libraries/newlib/math/double.h new file mode 100644 index 0000000000..eaf253a25a --- /dev/null +++ b/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 */ diff --git a/programs/develop/libraries/newlib/math/e_atan2.c b/programs/develop/libraries/newlib/math/e_atan2.c new file mode 100644 index 0000000000..87d4f7c2be --- /dev/null +++ b/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) */ diff --git a/programs/develop/libraries/newlib/math/e_cosh.c b/programs/develop/libraries/newlib/math/e_cosh.c new file mode 100644 index 0000000000..9c3d7b8a46 --- /dev/null +++ b/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; +} + diff --git a/programs/develop/libraries/newlib/math/e_hypot.c b/programs/develop/libraries/newlib/math/e_hypot.c new file mode 100644 index 0000000000..801e74c102 --- /dev/null +++ b/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) */ diff --git a/programs/develop/libraries/newlib/math/e_sinh.c b/programs/develop/libraries/newlib/math/e_sinh.c new file mode 100644 index 0000000000..c4b1df8cd4 --- /dev/null +++ b/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; +} + diff --git a/programs/develop/libraries/newlib/math/e_sqrt.c b/programs/develop/libraries/newlib/math/e_sqrt.c new file mode 100644 index 0000000000..9a41d8b1d5 --- /dev/null +++ b/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>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+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). + + */ diff --git a/programs/develop/libraries/newlib/math/erfl.c b/programs/develop/libraries/newlib/math/erfl.c new file mode 100644 index 0000000000..dcaa11ffbd --- /dev/null +++ b/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 +#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 ); +} diff --git a/programs/develop/libraries/newlib/math/exp.S b/programs/develop/libraries/newlib/math/exp.S new file mode 100644 index 0000000000..634569266b --- /dev/null +++ b/programs/develop/libraries/newlib/math/exp.S @@ -0,0 +1,49 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/exp2.S b/programs/develop/libraries/newlib/math/exp2.S new file mode 100644 index 0000000000..d5d81a9d0b --- /dev/null +++ b/programs/develop/libraries/newlib/math/exp2.S @@ -0,0 +1,39 @@ +/* + * Written by J.T. Conklin . + * Adapted for exp2 by Ulrich Drepper . + * 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 diff --git a/programs/develop/libraries/newlib/math/exp2f.S b/programs/develop/libraries/newlib/math/exp2f.S new file mode 100644 index 0000000000..18e1bf9038 --- /dev/null +++ b/programs/develop/libraries/newlib/math/exp2f.S @@ -0,0 +1,39 @@ +/* + * Written by J.T. Conklin . + * Adapted for exp2 by Ulrich Drepper . + * 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 diff --git a/programs/develop/libraries/newlib/math/exp2l.S b/programs/develop/libraries/newlib/math/exp2l.S new file mode 100644 index 0000000000..932cee4e95 --- /dev/null +++ b/programs/develop/libraries/newlib/math/exp2l.S @@ -0,0 +1,39 @@ +/* + * Written by J.T. Conklin . + * Adapted for exp2 by Ulrich Drepper . + * 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 diff --git a/programs/develop/libraries/newlib/math/expf.c b/programs/develop/libraries/newlib/math/expf.c new file mode 100644 index 0000000000..99684a077d --- /dev/null +++ b/programs/develop/libraries/newlib/math/expf.c @@ -0,0 +1,3 @@ +#include +float expf (float x) + {return (float) exp (x);} diff --git a/programs/develop/libraries/newlib/math/expl.c b/programs/develop/libraries/newlib/math/expl.c new file mode 100644 index 0000000000..a9a404d30f --- /dev/null +++ b/programs/develop/libraries/newlib/math/expl.c @@ -0,0 +1,71 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +/* + * 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 +#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); +} diff --git a/programs/develop/libraries/newlib/math/expm1.c b/programs/develop/libraries/newlib/math/expm1.c new file mode 100644 index 0000000000..005fc16c17 --- /dev/null +++ b/programs/develop/libraries/newlib/math/expm1.c @@ -0,0 +1,28 @@ +/* + * Written 2005 by Gregory W. Chicares . + * Adapted to double by Danny Smith . + * 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 /* 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; +} diff --git a/programs/develop/libraries/newlib/math/expm1f.c b/programs/develop/libraries/newlib/math/expm1f.c new file mode 100644 index 0000000000..e8459ca6cc --- /dev/null +++ b/programs/develop/libraries/newlib/math/expm1f.c @@ -0,0 +1,29 @@ +/* + * Written 2005 by Gregory W. Chicares . + * Adapted to float by Danny Smith . + * 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 /* 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; +} diff --git a/programs/develop/libraries/newlib/math/expm1l.c b/programs/develop/libraries/newlib/math/expm1l.c new file mode 100644 index 0000000000..5e3da19b76 --- /dev/null +++ b/programs/develop/libraries/newlib/math/expm1l.c @@ -0,0 +1,29 @@ +/* + * Written 2005 by Gregory W. Chicares 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 /* 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; +} diff --git a/programs/develop/libraries/newlib/math/fabs.c b/programs/develop/libraries/newlib/math/fabs.c new file mode 100644 index 0000000000..a05cc4a1f5 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fabs.c @@ -0,0 +1,10 @@ +#include + +double +fabs (double x) +{ + double res; + + asm ("fabs;" : "=t" (res) : "0" (x)); + return res; +} diff --git a/programs/develop/libraries/newlib/math/fabsf.c b/programs/develop/libraries/newlib/math/fabsf.c new file mode 100644 index 0000000000..8a503d859e --- /dev/null +++ b/programs/develop/libraries/newlib/math/fabsf.c @@ -0,0 +1,9 @@ +#include + +float +fabsf (float x) +{ + float res; + asm ("fabs;" : "=t" (res) : "0" (x)); + return res; +} diff --git a/programs/develop/libraries/newlib/math/fabsl.c b/programs/develop/libraries/newlib/math/fabsl.c new file mode 100644 index 0000000000..2fb7a210b6 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fabsl.c @@ -0,0 +1,9 @@ +#include + +long double +fabsl (long double x) +{ + long double res; + asm ("fabs;" : "=t" (res) : "0" (x)); + return res; +} diff --git a/programs/develop/libraries/newlib/math/fastmath.h b/programs/develop/libraries/newlib/math/fastmath.h new file mode 100644 index 0000000000..35b73a6a5b --- /dev/null +++ b/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 diff --git a/programs/develop/libraries/newlib/math/fdim.c b/programs/develop/libraries/newlib/math/fdim.c new file mode 100644 index 0000000000..e1d5cb9f11 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fdim.c @@ -0,0 +1,7 @@ +#include + +double +fdim (double x, double y) +{ + return (isgreater(x, y) ? (x - y) : 0.0); +} diff --git a/programs/develop/libraries/newlib/math/fdimf.c b/programs/develop/libraries/newlib/math/fdimf.c new file mode 100644 index 0000000000..66cf18b51e --- /dev/null +++ b/programs/develop/libraries/newlib/math/fdimf.c @@ -0,0 +1,7 @@ +#include + +float +fdimf (float x, float y) +{ + return (isgreater(x, y) ? (x - y) : 0.0F); +} diff --git a/programs/develop/libraries/newlib/math/fdiml.c b/programs/develop/libraries/newlib/math/fdiml.c new file mode 100644 index 0000000000..2697ac0a69 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fdiml.c @@ -0,0 +1,7 @@ +#include + +long double +fdiml (long double x, long double y) +{ + return (isgreater(x, y) ? (x - y) : 0.0L); +} diff --git a/programs/develop/libraries/newlib/math/fdlibm.h b/programs/develop/libraries/newlib/math/fdlibm.h new file mode 100644 index 0000000000..9a30d2004d --- /dev/null +++ b/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 +#include +#include + +/* 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 + * (one may replace the following line by "#include ") + */ + +#define X_TLOSS 1.41484755040568800000e+16 + +/* Functions that are not documented, and are not in . */ + +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) diff --git a/programs/develop/libraries/newlib/math/floor.S b/programs/develop/libraries/newlib/math/floor.S new file mode 100644 index 0000000000..89893a4cda --- /dev/null +++ b/programs/develop/libraries/newlib/math/floor.S @@ -0,0 +1,33 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Changes for long double by Ulrich Drepper + * + */ + .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 diff --git a/programs/develop/libraries/newlib/math/floorf.S b/programs/develop/libraries/newlib/math/floorf.S new file mode 100644 index 0000000000..089bf05981 --- /dev/null +++ b/programs/develop/libraries/newlib/math/floorf.S @@ -0,0 +1,35 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Changes for long double by Ulrich Drepper + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + .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 diff --git a/programs/develop/libraries/newlib/math/floorl.S b/programs/develop/libraries/newlib/math/floorl.S new file mode 100644 index 0000000000..1bdfc5b5e9 --- /dev/null +++ b/programs/develop/libraries/newlib/math/floorl.S @@ -0,0 +1,33 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Changes for long double by Ulrich Drepper + * + */ + .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 diff --git a/programs/develop/libraries/newlib/math/fma.S b/programs/develop/libraries/newlib/math/fma.S new file mode 100644 index 0000000000..216166f38d --- /dev/null +++ b/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 diff --git a/programs/develop/libraries/newlib/math/fmaf.S b/programs/develop/libraries/newlib/math/fmaf.S new file mode 100644 index 0000000000..e2302bc330 --- /dev/null +++ b/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 diff --git a/programs/develop/libraries/newlib/math/fmal.c b/programs/develop/libraries/newlib/math/fmal.c new file mode 100644 index 0000000000..2de17cc6e9 --- /dev/null +++ b/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); +} diff --git a/programs/develop/libraries/newlib/math/fmax.c b/programs/develop/libraries/newlib/math/fmax.c new file mode 100644 index 0000000000..2c69a51870 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fmax.c @@ -0,0 +1,7 @@ +#include + +double +fmax (double _x, double _y) +{ + return ( isgreaterequal (_x, _y)|| __isnan (_y) ? _x : _y ); +} diff --git a/programs/develop/libraries/newlib/math/fmaxf.c b/programs/develop/libraries/newlib/math/fmaxf.c new file mode 100644 index 0000000000..c51e16d86a --- /dev/null +++ b/programs/develop/libraries/newlib/math/fmaxf.c @@ -0,0 +1,7 @@ +#include + +float +fmaxf (float _x, float _y) +{ + return (( isgreaterequal(_x, _y) || __isnanf (_y)) ? _x : _y ); +} diff --git a/programs/develop/libraries/newlib/math/fmaxl.c b/programs/develop/libraries/newlib/math/fmaxl.c new file mode 100644 index 0000000000..683f487eea --- /dev/null +++ b/programs/develop/libraries/newlib/math/fmaxl.c @@ -0,0 +1,7 @@ +#include + +long double +fmaxl (long double _x, long double _y) +{ + return (( isgreaterequal(_x, _y) || __isnanl (_y)) ? _x : _y ); +} diff --git a/programs/develop/libraries/newlib/math/fmin.c b/programs/develop/libraries/newlib/math/fmin.c new file mode 100644 index 0000000000..e135c6eaa0 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fmin.c @@ -0,0 +1,7 @@ +#include + +double +fmin (double _x, double _y) +{ + return ((islessequal(_x, _y) || __isnan (_y)) ? _x : _y ); +} diff --git a/programs/develop/libraries/newlib/math/fminf.c b/programs/develop/libraries/newlib/math/fminf.c new file mode 100644 index 0000000000..a2c0d64686 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fminf.c @@ -0,0 +1,7 @@ +#include + +float +fminf (float _x, float _y) +{ + return ((islessequal(_x, _y) || isnan (_y)) ? _x : _y ); +} diff --git a/programs/develop/libraries/newlib/math/fminl.c b/programs/develop/libraries/newlib/math/fminl.c new file mode 100644 index 0000000000..632a43e245 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fminl.c @@ -0,0 +1,7 @@ +#include + +long double +fminl (long double _x, long double _y) +{ + return ((islessequal(_x, _y) || __isnanl (_y)) ? _x : _y ); +} diff --git a/programs/develop/libraries/newlib/math/fmodf.c b/programs/develop/libraries/newlib/math/fmodf.c new file mode 100644 index 0000000000..620dfa0ae0 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fmodf.c @@ -0,0 +1,37 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for float type by Danny Smith + * . + */ + +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/fmodl.c b/programs/develop/libraries/newlib/math/fmodl.c new file mode 100644 index 0000000000..b1379ad26a --- /dev/null +++ b/programs/develop/libraries/newlib/math/fmodl.c @@ -0,0 +1,22 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/fp_consts.c b/programs/develop/libraries/newlib/math/fp_consts.c new file mode 100644 index 0000000000..21251387c3 --- /dev/null +++ b/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; } + + diff --git a/programs/develop/libraries/newlib/math/fp_consts.h b/programs/develop/libraries/newlib/math/fp_consts.h new file mode 100644 index 0000000000..763d0ff166 --- /dev/null +++ b/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 diff --git a/programs/develop/libraries/newlib/math/fp_constsf.c b/programs/develop/libraries/newlib/math/fp_constsf.c new file mode 100644 index 0000000000..a85dde78a4 --- /dev/null +++ b/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;} diff --git a/programs/develop/libraries/newlib/math/fp_constsl.c b/programs/develop/libraries/newlib/math/fp_constsl.c new file mode 100644 index 0000000000..f240bef924 --- /dev/null +++ b/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; } diff --git a/programs/develop/libraries/newlib/math/fpclassify.c b/programs/develop/libraries/newlib/math/fpclassify.c new file mode 100644 index 0000000000..a0343c8b59 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fpclassify.c @@ -0,0 +1,20 @@ +#include + +/* '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 ); +} diff --git a/programs/develop/libraries/newlib/math/fpclassifyf.c b/programs/develop/libraries/newlib/math/fpclassifyf.c new file mode 100644 index 0000000000..9403f84e18 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fpclassifyf.c @@ -0,0 +1,10 @@ +#include +int __fpclassifyf (float _x){ + unsigned short sw; + __asm__ ( + "fxam; fstsw %%ax;" + : "=a" (sw) + : "t" (_x) + ); + return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); +} diff --git a/programs/develop/libraries/newlib/math/fpclassifyl.c b/programs/develop/libraries/newlib/math/fpclassifyl.c new file mode 100644 index 0000000000..fb2de85022 --- /dev/null +++ b/programs/develop/libraries/newlib/math/fpclassifyl.c @@ -0,0 +1,10 @@ +#include +int __fpclassifyl (long double _x){ + unsigned short sw; + __asm__ ( + "fxam; fstsw %%ax;" + : "=a" (sw) + : "t" (_x) + ); + return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); +} diff --git a/programs/develop/libraries/newlib/math/frexp.S b/programs/develop/libraries/newlib/math/frexp.S new file mode 100644 index 0000000000..002b1faa37 --- /dev/null +++ b/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 , 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 diff --git a/programs/develop/libraries/newlib/math/frexpf.c b/programs/develop/libraries/newlib/math/frexpf.c new file mode 100644 index 0000000000..3ada659f74 --- /dev/null +++ b/programs/develop/libraries/newlib/math/frexpf.c @@ -0,0 +1,3 @@ +#include +float frexpf (float x, int* expn) + {return (float)frexp(x, expn);} diff --git a/programs/develop/libraries/newlib/math/frexpl.S b/programs/develop/libraries/newlib/math/frexpl.S new file mode 100644 index 0000000000..348864ee25 --- /dev/null +++ b/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 + 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 diff --git a/programs/develop/libraries/newlib/math/fucom.c b/programs/develop/libraries/newlib/math/fucom.c new file mode 100644 index 0000000000..774c1cb561 --- /dev/null +++ b/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; +} diff --git a/programs/develop/libraries/newlib/math/hypotf.c b/programs/develop/libraries/newlib/math/hypotf.c new file mode 100644 index 0000000000..d98b8d3f87 --- /dev/null +++ b/programs/develop/libraries/newlib/math/hypotf.c @@ -0,0 +1,75 @@ +#include +#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; +} diff --git a/programs/develop/libraries/newlib/math/hypotl.c b/programs/develop/libraries/newlib/math/hypotl.c new file mode 100644 index 0000000000..61738241ae --- /dev/null +++ b/programs/develop/libraries/newlib/math/hypotl.c @@ -0,0 +1,73 @@ +#include +#include +#include + +/* +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 + 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)); +} diff --git a/programs/develop/libraries/newlib/math/ilogb.S b/programs/develop/libraries/newlib/math/ilogb.S new file mode 100644 index 0000000000..00cdb78e10 --- /dev/null +++ b/programs/develop/libraries/newlib/math/ilogb.S @@ -0,0 +1,37 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/ilogbf.S b/programs/develop/libraries/newlib/math/ilogbf.S new file mode 100644 index 0000000000..f10f91c4c9 --- /dev/null +++ b/programs/develop/libraries/newlib/math/ilogbf.S @@ -0,0 +1,35 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/ilogbl.S b/programs/develop/libraries/newlib/math/ilogbl.S new file mode 100644 index 0000000000..185a57c6f4 --- /dev/null +++ b/programs/develop/libraries/newlib/math/ilogbl.S @@ -0,0 +1,36 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * 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 diff --git a/programs/develop/libraries/newlib/math/isnan.c b/programs/develop/libraries/newlib/math/isnan.c new file mode 100644 index 0000000000..43f3a36795 --- /dev/null +++ b/programs/develop/libraries/newlib/math/isnan.c @@ -0,0 +1,14 @@ +#include + +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); diff --git a/programs/develop/libraries/newlib/math/isnanf.c b/programs/develop/libraries/newlib/math/isnanf.c new file mode 100644 index 0000000000..f3d61173d6 --- /dev/null +++ b/programs/develop/libraries/newlib/math/isnanf.c @@ -0,0 +1,12 @@ +#include +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); diff --git a/programs/develop/libraries/newlib/math/isnanl.c b/programs/develop/libraries/newlib/math/isnanl.c new file mode 100644 index 0000000000..4aadfc57b9 --- /dev/null +++ b/programs/develop/libraries/newlib/math/isnanl.c @@ -0,0 +1,13 @@ +#include + +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); diff --git a/programs/develop/libraries/newlib/math/ldexp.c b/programs/develop/libraries/newlib/math/ldexp.c new file mode 100644 index 0000000000..6958bb8a7d --- /dev/null +++ b/programs/develop/libraries/newlib/math/ldexp.c @@ -0,0 +1,19 @@ +#include +#include + +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; +} + diff --git a/programs/develop/libraries/newlib/math/ldexpf.c b/programs/develop/libraries/newlib/math/ldexpf.c new file mode 100644 index 0000000000..6e8c407fc9 --- /dev/null +++ b/programs/develop/libraries/newlib/math/ldexpf.c @@ -0,0 +1,3 @@ +#include +float ldexpf (float x, int expn) + {return (float) ldexp (x, expn);} diff --git a/programs/develop/libraries/newlib/math/ldexpl.c b/programs/develop/libraries/newlib/math/ldexpl.c new file mode 100644 index 0000000000..2987a849d9 --- /dev/null +++ b/programs/develop/libraries/newlib/math/ldexpl.c @@ -0,0 +1,19 @@ +#include +#include + +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; +} + diff --git a/programs/develop/libraries/newlib/math/lgamma.c b/programs/develop/libraries/newlib/math/lgamma.c new file mode 100644 index 0000000000..b155d1d1e8 --- /dev/null +++ b/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 + */ + + +#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)); +} diff --git a/programs/develop/libraries/newlib/math/lgammaf.c b/programs/develop/libraries/newlib/math/lgammaf.c new file mode 100644 index 0000000000..37d29612a4 --- /dev/null +++ b/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 +*/ + + +/* 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)); +} diff --git a/programs/develop/libraries/newlib/math/lgammal.c b/programs/develop/libraries/newlib/math/lgammal.c new file mode 100644 index 0000000000..07aadc883d --- /dev/null +++ b/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 + */ + +#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)); +} diff --git a/programs/develop/libraries/newlib/math/llrint.c b/programs/develop/libraries/newlib/math/llrint.c new file mode 100644 index 0000000000..6488648b79 --- /dev/null +++ b/programs/develop/libraries/newlib/math/llrint.c @@ -0,0 +1,10 @@ +#include + +long long llrint (double x) +{ + long long retval; + __asm__ __volatile__ \ + ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ + return retval; +} + diff --git a/programs/develop/libraries/newlib/math/llrintf.c b/programs/develop/libraries/newlib/math/llrintf.c new file mode 100644 index 0000000000..e4a97590c5 --- /dev/null +++ b/programs/develop/libraries/newlib/math/llrintf.c @@ -0,0 +1,9 @@ +#include + +long long llrintf (float x) +{ + long long retval; + __asm__ __volatile__ \ + ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ + return retval; +} diff --git a/programs/develop/libraries/newlib/math/llrintl.c b/programs/develop/libraries/newlib/math/llrintl.c new file mode 100644 index 0000000000..85401850fa --- /dev/null +++ b/programs/develop/libraries/newlib/math/llrintl.c @@ -0,0 +1,10 @@ +#include + +long long llrintl (long double x) +{ + long long retval; + __asm__ __volatile__ \ + ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ + return retval; +} + diff --git a/programs/develop/libraries/newlib/math/log.S b/programs/develop/libraries/newlib/math/log.S new file mode 100644 index 0000000000..3961e766e4 --- /dev/null +++ b/programs/develop/libraries/newlib/math/log.S @@ -0,0 +1,38 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Changed to use fyl2xp1 for values near 1, . + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log10.S b/programs/develop/libraries/newlib/math/log10.S new file mode 100644 index 0000000000..2666eb05a7 --- /dev/null +++ b/programs/develop/libraries/newlib/math/log10.S @@ -0,0 +1,48 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Adapted for float type by Ulrich Drepper . + * + * Changed to use fyl2xp1 for values near 1, . + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log10f.S b/programs/develop/libraries/newlib/math/log10f.S new file mode 100644 index 0000000000..87f21889cd --- /dev/null +++ b/programs/develop/libraries/newlib/math/log10f.S @@ -0,0 +1,48 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Adapted for float type by Ulrich Drepper . + * + * Changed to use fyl2xp1 for values near 1, . + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log10l.S b/programs/develop/libraries/newlib/math/log10l.S new file mode 100644 index 0000000000..bb14034325 --- /dev/null +++ b/programs/develop/libraries/newlib/math/log10l.S @@ -0,0 +1,52 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * + * Changed to use fyl2xp1 for values near 1, . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log1p.S b/programs/develop/libraries/newlib/math/log1p.S new file mode 100644 index 0000000000..daa20980b2 --- /dev/null +++ b/programs/develop/libraries/newlib/math/log1p.S @@ -0,0 +1,47 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log1pf.S b/programs/develop/libraries/newlib/math/log1pf.S new file mode 100644 index 0000000000..23e89a24bf --- /dev/null +++ b/programs/develop/libraries/newlib/math/log1pf.S @@ -0,0 +1,47 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log1pl.S b/programs/develop/libraries/newlib/math/log1pl.S new file mode 100644 index 0000000000..e4d81b87a9 --- /dev/null +++ b/programs/develop/libraries/newlib/math/log1pl.S @@ -0,0 +1,54 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . +* Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log2.S b/programs/develop/libraries/newlib/math/log2.S new file mode 100644 index 0000000000..ba7adba38e --- /dev/null +++ b/programs/develop/libraries/newlib/math/log2.S @@ -0,0 +1,51 @@ +/* + * Written by J.T. Conklin . + * Adapted for use as log2 by Ulrich Drepper . + * Public domain. + * + * Changed to use fyl2xp1 for values near 1, . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log2f.S b/programs/develop/libraries/newlib/math/log2f.S new file mode 100644 index 0000000000..1779b11212 --- /dev/null +++ b/programs/develop/libraries/newlib/math/log2f.S @@ -0,0 +1,51 @@ +/* + * Written by J.T. Conklin . + * Adapted for use as log2 by Ulrich Drepper . + * Public domain. + * + * Changed to use fyl2xp1 for values near 1, . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/log2l.S b/programs/develop/libraries/newlib/math/log2l.S new file mode 100644 index 0000000000..4deb1c35b3 --- /dev/null +++ b/programs/develop/libraries/newlib/math/log2l.S @@ -0,0 +1,48 @@ +/* + * Written by J.T. Conklin . + * Adapted for use as log2 by Ulrich Drepper . + * Public domain. + * + * Changed to use fyl2xp1 for values near 1, . + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/logb.c b/programs/develop/libraries/newlib/math/logb.c new file mode 100644 index 0000000000..26914f1a39 --- /dev/null +++ b/programs/develop/libraries/newlib/math/logb.c @@ -0,0 +1,16 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include + +double +logb (double x) +{ + double res; + asm ("fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; +} diff --git a/programs/develop/libraries/newlib/math/logbf.c b/programs/develop/libraries/newlib/math/logbf.c new file mode 100644 index 0000000000..b75f9e5882 --- /dev/null +++ b/programs/develop/libraries/newlib/math/logbf.c @@ -0,0 +1,16 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include + +float +logbf (float x) +{ + float res; + asm ("fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; +} diff --git a/programs/develop/libraries/newlib/math/logbl.c b/programs/develop/libraries/newlib/math/logbl.c new file mode 100644 index 0000000000..6e17794820 --- /dev/null +++ b/programs/develop/libraries/newlib/math/logbl.c @@ -0,0 +1,17 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include + +long double +logbl (long double x) +{ + long double res; + + asm ("fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; +} diff --git a/programs/develop/libraries/newlib/math/logf.S b/programs/develop/libraries/newlib/math/logf.S new file mode 100644 index 0000000000..9d5b9c1193 --- /dev/null +++ b/programs/develop/libraries/newlib/math/logf.S @@ -0,0 +1,39 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Adapted for float by Ulrich Drepper . + * + * Changed to use fyl2xp1 for values near 1, . + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/logl.S b/programs/develop/libraries/newlib/math/logl.S new file mode 100644 index 0000000000..1ef4943f62 --- /dev/null +++ b/programs/develop/libraries/newlib/math/logl.S @@ -0,0 +1,40 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + .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 diff --git a/programs/develop/libraries/newlib/math/lrint.c b/programs/develop/libraries/newlib/math/lrint.c new file mode 100644 index 0000000000..7f2f94cd02 --- /dev/null +++ b/programs/develop/libraries/newlib/math/lrint.c @@ -0,0 +1,9 @@ +#include + +long lrint (double x) +{ + long retval; + __asm__ __volatile__ \ + ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ + return retval; +} diff --git a/programs/develop/libraries/newlib/math/lrintf.c b/programs/develop/libraries/newlib/math/lrintf.c new file mode 100644 index 0000000000..2b700bd8b7 --- /dev/null +++ b/programs/develop/libraries/newlib/math/lrintf.c @@ -0,0 +1,9 @@ +#include + +long lrintf (float x) +{ + long retval; + __asm__ __volatile__ \ + ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ + return retval; +} diff --git a/programs/develop/libraries/newlib/math/lrintl.c b/programs/develop/libraries/newlib/math/lrintl.c new file mode 100644 index 0000000000..06551ac13b --- /dev/null +++ b/programs/develop/libraries/newlib/math/lrintl.c @@ -0,0 +1,10 @@ +#include + +long lrintl (long double x) +{ + long retval; + __asm__ __volatile__ \ + ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ + return retval; +} + diff --git a/programs/develop/libraries/newlib/math/lround_generic.c b/programs/develop/libraries/newlib/math/lround_generic.c new file mode 100644 index 0000000000..49066cf413 --- /dev/null +++ b/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 + * + * 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 +#include + +/* 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 */ diff --git a/programs/develop/libraries/newlib/math/modff.c b/programs/develop/libraries/newlib/math/modff.c new file mode 100644 index 0000000000..5b809cfdd8 --- /dev/null +++ b/programs/develop/libraries/newlib/math/modff.c @@ -0,0 +1,22 @@ +#include +#include +#include +#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); +} diff --git a/programs/develop/libraries/newlib/math/modfl.c b/programs/develop/libraries/newlib/math/modfl.c new file mode 100644 index 0000000000..66d88efc9a --- /dev/null +++ b/programs/develop/libraries/newlib/math/modfl.c @@ -0,0 +1,22 @@ +#include +#include +#include +#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); +} diff --git a/programs/develop/libraries/newlib/math/nearbyint.S b/programs/develop/libraries/newlib/math/nearbyint.S new file mode 100644 index 0000000000..56f777d128 --- /dev/null +++ b/programs/develop/libraries/newlib/math/nearbyint.S @@ -0,0 +1,30 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for use as nearbyint by Ulrich Drepper . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/nearbyintf.S b/programs/develop/libraries/newlib/math/nearbyintf.S new file mode 100644 index 0000000000..af838f737d --- /dev/null +++ b/programs/develop/libraries/newlib/math/nearbyintf.S @@ -0,0 +1,29 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Adapted for use as nearbyint by Ulrich Drepper . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/nearbyintl.S b/programs/develop/libraries/newlib/math/nearbyintl.S new file mode 100644 index 0000000000..39a6c83f83 --- /dev/null +++ b/programs/develop/libraries/newlib/math/nearbyintl.S @@ -0,0 +1,30 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adaptedfor use as nearbyint by Ulrich Drepper . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/nextafterf.c b/programs/develop/libraries/newlib/math/nextafterf.c new file mode 100644 index 0000000000..78a5a2faf5 --- /dev/null +++ b/programs/develop/libraries/newlib/math/nextafterf.c @@ -0,0 +1,27 @@ +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/nextafterl.c b/programs/develop/libraries/newlib/math/nextafterl.c new file mode 100644 index 0000000000..021511e5ed --- /dev/null +++ b/programs/develop/libraries/newlib/math/nextafterl.c @@ -0,0 +1,65 @@ +/* + nextafterl.c + Contributed by Danny Smith + No copyright claimed, absolutely no warranties. + + 2005-05-09 +*/ + +#include + +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"))); diff --git a/programs/develop/libraries/newlib/math/nexttoward.c b/programs/develop/libraries/newlib/math/nexttoward.c new file mode 100644 index 0000000000..f59b141ab0 --- /dev/null +++ b/programs/develop/libraries/newlib/math/nexttoward.c @@ -0,0 +1,42 @@ +/* + nexttoward.c + Contributed by Danny Smith + No copyright claimed, absolutely no warranties. + + 2005-05-10 +*/ + +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/nexttowardf.c b/programs/develop/libraries/newlib/math/nexttowardf.c new file mode 100644 index 0000000000..5d76a599da --- /dev/null +++ b/programs/develop/libraries/newlib/math/nexttowardf.c @@ -0,0 +1,38 @@ +/* + nexttowardf.c + Contributed by Danny Smith + No copyright claimed, absolutely no warranties. + + 2005-05-10 +*/ + +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/op-1.h b/programs/develop/libraries/newlib/math/op-1.h new file mode 100644 index 0000000000..24c3ad7d0b --- /dev/null +++ b/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) diff --git a/programs/develop/libraries/newlib/math/op-2.h b/programs/develop/libraries/newlib/math/op-2.h new file mode 100644 index 0000000000..05407c4b47 --- /dev/null +++ b/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) diff --git a/programs/develop/libraries/newlib/math/op-4.h b/programs/develop/libraries/newlib/math/op-4.h new file mode 100644 index 0000000000..31167f1ab5 --- /dev/null +++ b/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) diff --git a/programs/develop/libraries/newlib/math/op-8.h b/programs/develop/libraries/newlib/math/op-8.h new file mode 100644 index 0000000000..1bbe3bd636 --- /dev/null +++ b/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) + diff --git a/programs/develop/libraries/newlib/math/op-common.h b/programs/develop/libraries/newlib/math/op-common.h new file mode 100644 index 0000000000..8f1f5576b5 --- /dev/null +++ b/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) diff --git a/programs/develop/libraries/newlib/math/pow.c b/programs/develop/libraries/newlib/math/pow.c new file mode 100644 index 0000000000..e15c836ccf --- /dev/null +++ b/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 +*/ + +#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); +} diff --git a/programs/develop/libraries/newlib/math/powf.c b/programs/develop/libraries/newlib/math/powf.c new file mode 100644 index 0000000000..9bcb569759 --- /dev/null +++ b/programs/develop/libraries/newlib/math/powf.c @@ -0,0 +1,3 @@ +#include +float powf (float x, float y) + {return (float) pow (x, y);} diff --git a/programs/develop/libraries/newlib/math/powi.c b/programs/develop/libraries/newlib/math/powi.c new file mode 100644 index 0000000000..ecd27252c4 --- /dev/null +++ b/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 +*/ + +#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); +} diff --git a/programs/develop/libraries/newlib/math/powif.c b/programs/develop/libraries/newlib/math/powif.c new file mode 100644 index 0000000000..aad75f03ec --- /dev/null +++ b/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 +*/ + +#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); +} diff --git a/programs/develop/libraries/newlib/math/powil.c b/programs/develop/libraries/newlib/math/powil.c new file mode 100644 index 0000000000..8fd705f950 --- /dev/null +++ b/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 +*/ + +#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); +} diff --git a/programs/develop/libraries/newlib/math/powl.c b/programs/develop/libraries/newlib/math/powl.c new file mode 100644 index 0000000000..c9bce81a90 --- /dev/null +++ b/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 +*/ + +#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); +} diff --git a/programs/develop/libraries/newlib/math/quad.h b/programs/develop/libraries/newlib/math/quad.h new file mode 100644 index 0000000000..653a4d4eaf --- /dev/null +++ b/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 */ diff --git a/programs/develop/libraries/newlib/math/remainder.S b/programs/develop/libraries/newlib/math/remainder.S new file mode 100644 index 0000000000..8fa47e96fd --- /dev/null +++ b/programs/develop/libraries/newlib/math/remainder.S @@ -0,0 +1,19 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/remainderf.S b/programs/develop/libraries/newlib/math/remainderf.S new file mode 100644 index 0000000000..8e76b7826e --- /dev/null +++ b/programs/develop/libraries/newlib/math/remainderf.S @@ -0,0 +1,19 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/remainderl.S b/programs/develop/libraries/newlib/math/remainderl.S new file mode 100644 index 0000000000..f0f6481de1 --- /dev/null +++ b/programs/develop/libraries/newlib/math/remainderl.S @@ -0,0 +1,22 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * Adapted for `long double' by Ulrich Drepper . + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/remquo.S b/programs/develop/libraries/newlib/math/remquo.S new file mode 100644 index 0000000000..befc95f6ed --- /dev/null +++ b/programs/develop/libraries/newlib/math/remquo.S @@ -0,0 +1,38 @@ +/* + * Written by Ulrich Drepper . + * Based on e_remainder by J.T. Conklin . + * Removed header file dependency for use in libmingwex.a by + * Danny Smith . + * Based on e_remainder by J.T. Conklin . + * Removed header file dependency for use in libmingwex.a by + * Danny Smith . + * Based on e_remainder by J.T. Conklin . + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + * 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 diff --git a/programs/develop/libraries/newlib/math/rint.c b/programs/develop/libraries/newlib/math/rint.c new file mode 100644 index 0000000000..6d966ca688 --- /dev/null +++ b/programs/develop/libraries/newlib/math/rint.c @@ -0,0 +1,6 @@ +#include +double rint (double x){ + double retval; + __asm__ ("frndint;" : "=t" (retval) : "0" (x)); + return retval; +} diff --git a/programs/develop/libraries/newlib/math/rintf.c b/programs/develop/libraries/newlib/math/rintf.c new file mode 100644 index 0000000000..9bcbf97144 --- /dev/null +++ b/programs/develop/libraries/newlib/math/rintf.c @@ -0,0 +1,7 @@ +#include + +float rintf (float x){ + float retval; + __asm__ ("frndint;": "=t" (retval) : "0" (x)); + return retval; +} diff --git a/programs/develop/libraries/newlib/math/rintl.c b/programs/develop/libraries/newlib/math/rintl.c new file mode 100644 index 0000000000..fec482d305 --- /dev/null +++ b/programs/develop/libraries/newlib/math/rintl.c @@ -0,0 +1,7 @@ +#include + +long double rintl (long double x){ + long double retval; + __asm__ ("frndint;": "=t" (retval) : "0" (x)); + return retval; +} diff --git a/programs/develop/libraries/newlib/math/round_generic.c b/programs/develop/libraries/newlib/math/round_generic.c new file mode 100644 index 0000000000..04d321bb2f --- /dev/null +++ b/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 + * + * 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 */ diff --git a/programs/develop/libraries/newlib/math/round_internal.h b/programs/develop/libraries/newlib/math/round_internal.h new file mode 100644 index 0000000000..9af4106f57 --- /dev/null +++ b/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 + * + * 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 +#include + +#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 + * + * 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 + */ + 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 */ diff --git a/programs/develop/libraries/newlib/math/s_erf.c b/programs/develop/libraries/newlib/math/s_erf.c new file mode 100644 index 0000000000..41c6ba2b19 --- /dev/null +++ b/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 >= 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 +#include +#include + +#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; + } +} diff --git a/programs/develop/libraries/newlib/math/s_expm1.S b/programs/develop/libraries/newlib/math/s_expm1.S new file mode 100644 index 0000000000..073961cf18 --- /dev/null +++ b/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 , 1996. + Based on code by John C. Bowman . + 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 + diff --git a/programs/develop/libraries/newlib/math/s_fpclassify.c b/programs/develop/libraries/newlib/math/s_fpclassify.c new file mode 100644 index 0000000000..2803ca776e --- /dev/null +++ b/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; +} diff --git a/programs/develop/libraries/newlib/math/s_isnand.c b/programs/develop/libraries/newlib/math/s_isnand.c new file mode 100644 index 0000000000..350ab23136 --- /dev/null +++ b/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); +} + diff --git a/programs/develop/libraries/newlib/math/s_modf.c b/programs/develop/libraries/newlib/math/s_modf.c new file mode 100644 index 0000000000..e293cf0c24 --- /dev/null +++ b/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 + <>, <>---split fractional and integer parts + +INDEX + modf +INDEX + modff + +ANSI_SYNOPSIS + #include + double modf(double <[val]>, double *<[ipart]>); + float modff(float <[val]>, float *<[ipart]>); + +TRAD_SYNOPSIS + #include + double modf(<[val]>, <[ipart]>) + double <[val]>; + double *<[ipart]>; + + float modff(<[val]>, <[ipart]>) + float <[val]>; + float *<[ipart]>; + +DESCRIPTION + <> 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]>. + <> is identical, save that it takes and returns + <> rather than <> values. + +RETURNS + The fractional part is returned. Each result has the same + sign as the supplied argument <[val]>. + +PORTABILITY + <> is ANSI C. <> 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 */ diff --git a/programs/develop/libraries/newlib/math/s_roundf.c b/programs/develop/libraries/newlib/math/s_roundf.c new file mode 100644 index 0000000000..7dc57cd5b8 --- /dev/null +++ b/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 , 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 +#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; +} diff --git a/programs/develop/libraries/newlib/math/s_signbit.c b/programs/develop/libraries/newlib/math/s_signbit.c new file mode 100644 index 0000000000..60bb8d060b --- /dev/null +++ b/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); +} diff --git a/programs/develop/libraries/newlib/math/s_tanh.c b/programs/develop/libraries/newlib/math/s_tanh.c new file mode 100644 index 0000000000..8ff6a79d4d --- /dev/null +++ b/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 +#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; +} diff --git a/programs/develop/libraries/newlib/math/scalbn.S b/programs/develop/libraries/newlib/math/scalbn.S new file mode 100644 index 0000000000..8948ce265f --- /dev/null +++ b/programs/develop/libraries/newlib/math/scalbn.S @@ -0,0 +1,19 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/scalbnf.S b/programs/develop/libraries/newlib/math/scalbnf.S new file mode 100644 index 0000000000..d012c34866 --- /dev/null +++ b/programs/develop/libraries/newlib/math/scalbnf.S @@ -0,0 +1,19 @@ +/* + * Written by J.T. Conklin . + * 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 diff --git a/programs/develop/libraries/newlib/math/scalbnl.S b/programs/develop/libraries/newlib/math/scalbnl.S new file mode 100644 index 0000000000..71831fca3a --- /dev/null +++ b/programs/develop/libraries/newlib/math/scalbnl.S @@ -0,0 +1,20 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * 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 diff --git a/programs/develop/libraries/newlib/math/sf_erf.c b/programs/develop/libraries/newlib/math/sf_erf.c new file mode 100644 index 0000000000..4ea69c0d92 --- /dev/null +++ b/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 +#include +#include + +#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; + } +} diff --git a/programs/develop/libraries/newlib/math/signbit.c b/programs/develop/libraries/newlib/math/signbit.c new file mode 100644 index 0000000000..5147673ee3 --- /dev/null +++ b/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); + diff --git a/programs/develop/libraries/newlib/math/signbitf.c b/programs/develop/libraries/newlib/math/signbitf.c new file mode 100644 index 0000000000..b2a705835a --- /dev/null +++ b/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); diff --git a/programs/develop/libraries/newlib/math/signbitl.c b/programs/develop/libraries/newlib/math/signbitl.c new file mode 100644 index 0000000000..ee7542092d --- /dev/null +++ b/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); diff --git a/programs/develop/libraries/newlib/math/sin.S b/programs/develop/libraries/newlib/math/sin.S new file mode 100644 index 0000000000..060a9e6b10 --- /dev/null +++ b/programs/develop/libraries/newlib/math/sin.S @@ -0,0 +1,30 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/sinf.S b/programs/develop/libraries/newlib/math/sinf.S new file mode 100644 index 0000000000..ea40c352ef --- /dev/null +++ b/programs/develop/libraries/newlib/math/sinf.S @@ -0,0 +1,32 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/single.h b/programs/develop/libraries/newlib/math/single.h new file mode 100644 index 0000000000..12c1e49b0b --- /dev/null +++ b/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) diff --git a/programs/develop/libraries/newlib/math/sinhf.c b/programs/develop/libraries/newlib/math/sinhf.c new file mode 100644 index 0000000000..e770cb7b80 --- /dev/null +++ b/programs/develop/libraries/newlib/math/sinhf.c @@ -0,0 +1,3 @@ +#include +float sinhf (float x) + {return (float) sinh (x);} diff --git a/programs/develop/libraries/newlib/math/sinhl.c b/programs/develop/libraries/newlib/math/sinhl.c new file mode 100644 index 0000000000..44b8688f2f --- /dev/null +++ b/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 +*/ + +#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)) ); +} diff --git a/programs/develop/libraries/newlib/math/sinl.S b/programs/develop/libraries/newlib/math/sinl.S new file mode 100644 index 0000000000..7a1adef396 --- /dev/null +++ b/programs/develop/libraries/newlib/math/sinl.S @@ -0,0 +1,32 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + + .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 diff --git a/programs/develop/libraries/newlib/math/soft-fp.h b/programs/develop/libraries/newlib/math/soft-fp.h new file mode 100644 index 0000000000..02aae74072 --- /dev/null +++ b/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 +#else +#include "longlong.h" +#endif +#endif + +#ifdef _LIBC +#include +#else +extern void abort (void); +#endif + +#endif diff --git a/programs/develop/libraries/newlib/math/sqrtf.c b/programs/develop/libraries/newlib/math/sqrtf.c new file mode 100644 index 0000000000..d4c4816610 --- /dev/null +++ b/programs/develop/libraries/newlib/math/sqrtf.c @@ -0,0 +1,37 @@ +#include +#include + +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; + } +} + diff --git a/programs/develop/libraries/newlib/math/sqrtl.c b/programs/develop/libraries/newlib/math/sqrtl.c new file mode 100644 index 0000000000..f0c823c928 --- /dev/null +++ b/programs/develop/libraries/newlib/math/sqrtl.c @@ -0,0 +1,20 @@ +#include +#include + +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; + } +} diff --git a/programs/develop/libraries/newlib/math/tan.S b/programs/develop/libraries/newlib/math/tan.S new file mode 100644 index 0000000000..d81801bdbe --- /dev/null +++ b/programs/develop/libraries/newlib/math/tan.S @@ -0,0 +1,31 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + .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 diff --git a/programs/develop/libraries/newlib/math/tanf.S b/programs/develop/libraries/newlib/math/tanf.S new file mode 100644 index 0000000000..1e7603b1be --- /dev/null +++ b/programs/develop/libraries/newlib/math/tanf.S @@ -0,0 +1,31 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + .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 diff --git a/programs/develop/libraries/newlib/math/tanhf.c b/programs/develop/libraries/newlib/math/tanhf.c new file mode 100644 index 0000000000..0f1b5a80af --- /dev/null +++ b/programs/develop/libraries/newlib/math/tanhf.c @@ -0,0 +1,3 @@ +#include +float tanhf (float x) + {return (float) tanh (x);} diff --git a/programs/develop/libraries/newlib/math/tanhl.c b/programs/develop/libraries/newlib/math/tanhl.c new file mode 100644 index 0000000000..ebd1366f8a --- /dev/null +++ b/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 +*/ + +#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 ); +} diff --git a/programs/develop/libraries/newlib/math/tanl.S b/programs/develop/libraries/newlib/math/tanl.S new file mode 100644 index 0000000000..05bbe4df06 --- /dev/null +++ b/programs/develop/libraries/newlib/math/tanl.S @@ -0,0 +1,33 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * + * Removed header file dependency for use in libmingwex.a by + * Danny Smith + */ + .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 diff --git a/programs/develop/libraries/newlib/math/tgamma.c b/programs/develop/libraries/newlib/math/tgamma.c new file mode 100644 index 0000000000..a702334b98 --- /dev/null +++ b/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 + */ + + +#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)); +} diff --git a/programs/develop/libraries/newlib/math/tgammaf.c b/programs/develop/libraries/newlib/math/tgammaf.c new file mode 100644 index 0000000000..6cee811737 --- /dev/null +++ b/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 + */ + + +#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)); +} diff --git a/programs/develop/libraries/newlib/math/tgammal.c b/programs/develop/libraries/newlib/math/tgammal.c new file mode 100644 index 0000000000..6a74d1aa5b --- /dev/null +++ b/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 + */ + + +#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)); +} + diff --git a/programs/develop/libraries/newlib/math/trunc.c b/programs/develop/libraries/newlib/math/trunc.c new file mode 100644 index 0000000000..7c3a5d6b43 --- /dev/null +++ b/programs/develop/libraries/newlib/math/trunc.c @@ -0,0 +1,16 @@ +#include +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/truncf.c b/programs/develop/libraries/newlib/math/truncf.c new file mode 100644 index 0000000000..2c6d368663 --- /dev/null +++ b/programs/develop/libraries/newlib/math/truncf.c @@ -0,0 +1,17 @@ +#include +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/truncl.c b/programs/develop/libraries/newlib/math/truncl.c new file mode 100644 index 0000000000..1713085e8e --- /dev/null +++ b/programs/develop/libraries/newlib/math/truncl.c @@ -0,0 +1,16 @@ +#include +#include + +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; +} diff --git a/programs/develop/libraries/newlib/math/w_atan2.c b/programs/develop/libraries/newlib/math/w_atan2.c new file mode 100644 index 0000000000..d6b850389b --- /dev/null +++ b/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 + <>, <>---arc tangent of y/x + +INDEX + atan2 +INDEX + atan2f + +ANSI_SYNOPSIS + #include + double atan2(double <[y]>,double <[x]>); + float atan2f(float <[y]>,float <[x]>); + +TRAD_SYNOPSIS + #include + double atan2(<[y]>,<[x]>); + double <[y]>; + double <[x]>; + + float atan2f(<[y]>,<[x]>); + float <[y]>; + float <[x]>; + +DESCRIPTION + +<> computes the inverse tangent (arc tangent) of <[y]>/<[x]>. +<> 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). + +<> is identical to <>, save that it takes and returns +<>. + +RETURNS +<> and <> 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 <>. + +PORTABILITY +<> is ANSI C. <> is an extension. + + +*/ + +/* + * wrapper atan2(y,x) + */ + +#include "fdlibm.h" +#include + +#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) */ diff --git a/programs/develop/libraries/newlib/math/w_hypot.c b/programs/develop/libraries/newlib/math/w_hypot.c new file mode 100644 index 0000000000..46396ea8b9 --- /dev/null +++ b/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 + <>, <>---distance from origin +INDEX + hypot +INDEX + hypotf + +ANSI_SYNOPSIS + #include + 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 + <> calculates the Euclidean distance + @tex + $\sqrt{x^2+y^2}$ + @end tex + @ifnottex + <*<[x]> + <[y]>*<[y]>)>> + @end ifnottex + between the origin (0,0) and a point represented by the + Cartesian coordinates (<[x]>,<[y]>). <> differs only + in the type of its arguments and result. + +RETURNS + Normally, the distance value is returned. On overflow, + <> returns <> and sets <> to + <>. + + You can change the error treatment with <>. + +PORTABILITY + <> and <> are not ANSI C. */ + +/* + * wrapper hypot(x,y) + */ + +#define _IEEE_LIBM + +#include "fdlibm.h" +#include + +#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) */ diff --git a/programs/develop/libraries/newlib/pe/list.h b/programs/develop/libraries/newlib/pe/list.h new file mode 100644 index 0000000000..3a43161306 --- /dev/null +++ b/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 diff --git a/programs/develop/libraries/newlib/pe/loader.c b/programs/develop/libraries/newlib/pe/loader.c new file mode 100644 index 0000000000..864464054e --- /dev/null +++ b/programs/develop/libraries/newlib/pe/loader.c @@ -0,0 +1,652 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#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; +}; + + diff --git a/programs/develop/libraries/newlib/pe/pe.h b/programs/develop/libraries/newlib/pe/pe.h new file mode 100644 index 0000000000..b32b894fc7 --- /dev/null +++ b/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) ) + + diff --git a/programs/develop/libraries/newlib/pe_app.lds b/programs/develop/libraries/newlib/pe_app.lds new file mode 100644 index 0000000000..7220c4c78d --- /dev/null +++ b/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) + } + +} + diff --git a/programs/develop/libraries/newlib/reent/getreent.c b/programs/develop/libraries/newlib/reent/getreent.c index c8cc822fc0..36aa8d2f18 100644 --- a/programs/develop/libraries/newlib/reent/getreent.c +++ b/programs/develop/libraries/newlib/reent/getreent.c @@ -4,10 +4,6 @@ #include #include -#ifdef __getreent -#undef __getreent -#endif - static inline void *user_alloc(int size) { @@ -28,21 +24,12 @@ void init_reent() _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) { diff --git a/programs/develop/libraries/newlib/reent/gettimeofdayr.c b/programs/develop/libraries/newlib/reent/gettimeofdayr.c new file mode 100644 index 0000000000..2b3bff9d54 --- /dev/null +++ b/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 +#include +#include +#include +#include <_syslist.h> +#include + +/* 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 + #include + int _gettimeofday_r(struct _reent *<[ptr]>, + struct timeval *<[ptimeval]>, + void *<[ptimezone]>); + +TRAD_SYNOPSIS + #include + #include + int _gettimeofday_r(<[ptr]>, <[ptimeval]>, <[ptimezone]>) + struct _reent *<[ptr]>; + struct timeval *<[ptimeval]>; + void *<[ptimezone]>; + +DESCRIPTION + This is a reentrant version of <>. It + takes a pointer to the global data block, which holds + <>. + + 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) */ diff --git a/programs/develop/libraries/newlib/reent/openr.c b/programs/develop/libraries/newlib/reent/openr.c index ef80e88ad6..fd04dfc807 100644 --- a/programs/develop/libraries/newlib/reent/openr.c +++ b/programs/develop/libraries/newlib/reent/openr.c @@ -8,6 +8,7 @@ #include #include #include +#include /* Some targets provides their own versions of this functions. Those targets should define REENTRANT_SYSCALLS_PROVIDED in TARGET_CFLAGS. */ @@ -49,62 +50,6 @@ DESCRIPTION */ -#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,99 +71,6 @@ typedef struct 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) { @@ -241,33 +93,6 @@ int debugwrite(const char *path, const void *buff, 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; diff --git a/programs/develop/libraries/newlib/signal/signal.c b/programs/develop/libraries/newlib/signal/signal.c new file mode 100644 index 0000000000..1d97e387d2 --- /dev/null +++ b/programs/develop/libraries/newlib/signal/signal.c @@ -0,0 +1,260 @@ +/* +FUNCTION +<>---specify handler subroutine for a signal + +INDEX + signal +INDEX + _signal_r + +ANSI_SYNOPSIS + #include + void (*signal(int <[sig]>, void(*<[func]>)(int))) (int); + + void (*_signal_r(void *<[reent]>, int <[sig]>, void(*<[func]>)(int))) (int); + +TRAD_SYNOPSIS + #include + char ( * signal(<[sig]>, <[func]>) )() + int <[sig]>; + char ( * <[func]> )(); + + char ( * _signal_r(<[reent]>, <[sig]>, <[func]>) )() + char *<[reent]>; + int <[sig]>; + char ( * <[func]> )(); + +DESCRIPTION +<> provides a simple signal-handling implementation for embedded +targets. + +<> allows you to request changed treatment for a particular +signal <[sig]>. You can use one of the predefined macros <> +(select system default handling) or <> (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 <> 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 `<>', then you may use that location in a signal handler to +store signal values. + +If your signal handler terminates using <> (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 <> and <> 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 +<>; a specific error number is also recorded in <>. + +Otherwise, the result is the previous handler (a function pointer or +one of the predefined macros). + +PORTABILITY +ANSI C requires <>. + +No supporting OS subroutines are required to link with <>, 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 +#include +#include +#include +#include +#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 */ diff --git a/programs/develop/libraries/newlib/static.lds b/programs/develop/libraries/newlib/static.lds new file mode 100644 index 0000000000..60df13981a --- /dev/null +++ b/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) + } + +} diff --git a/programs/develop/libraries/newlib/stdio/fdopen.c b/programs/develop/libraries/newlib/stdio/fdopen.c new file mode 100644 index 0000000000..de0a249f24 --- /dev/null +++ b/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 +<>---turn open file into a stream + +INDEX + fdopen +INDEX + _fdopen_r + +ANSI_SYNOPSIS + #include + FILE *fdopen(int <[fd]>, const char *<[mode]>); + FILE *_fdopen_r(struct _reent *<[reent]>, + int <[fd]>, const char *<[mode]>); + +TRAD_SYNOPSIS + #include + FILE *fdopen(<[fd]>, <[mode]>) + int <[fd]>; + char *<[mode]>; + + FILE *_fdopen_r(<[reent]>, <[fd]>, <[mode]>) + struct _reent *<[reent]>; + int <[fd]>; + char *<[mode]>); + +DESCRIPTION +<> produces a file descriptor of type <>, from a +descriptor for an already-open file (returned, for example, by the +system subroutine <> rather than by <>). +The <[mode]> argument has the same meanings as in <>. + +RETURNS +File pointer or <>, as for <>. + +PORTABILITY +<> is ANSI. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#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 diff --git a/programs/develop/libraries/newlib/stdio/fgets.c b/programs/develop/libraries/newlib/stdio/fgets.c new file mode 100644 index 0000000000..09fff83f86 --- /dev/null +++ b/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 +<>---get character string from a file or stream + +INDEX + fgets +INDEX + _fgets_r + +ANSI_SYNOPSIS + #include + char *fgets(char *<[buf]>, int <[n]>, FILE *<[fp]>); + + #include + char *_fgets_r(struct _reent *<[ptr]>, char *<[buf]>, int <[n]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include + char *fgets(<[buf]>,<[n]>,<[fp]>) + char *<[buf]>; + int <[n]>; + FILE *<[fp]>; + + #include + 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 + <> and is passed an additional reentrancy structure + pointer: <[ptr]>. + +RETURNS + <> 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 + <> should replace all uses of <>. Note however + that <> returns all of the data, while <> removes + the trailing newline (with no indication that it has done so.) + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. +*/ + +#include <_ansi.h> +#include +#include +#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 */ diff --git a/programs/develop/libraries/newlib/stdio/fiscanf.c b/programs/develop/libraries/newlib/stdio/fiscanf.c new file mode 100644 index 0000000000..8f9281fd58 --- /dev/null +++ b/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 +#include +#ifdef _HAVE_STDC +#include +#else +#include +#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); +} + diff --git a/programs/develop/libraries/newlib/stdio/fread.c b/programs/develop/libraries/newlib/stdio/fread.c new file mode 100644 index 0000000000..ba60847768 --- /dev/null +++ b/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 +<>---read array elements from a file + +INDEX + fread +INDEX + _fread_r + +ANSI_SYNOPSIS + #include + size_t fread(void *<[buf]>, size_t <[size]>, size_t <[count]>, + FILE *<[fp]>); + + #include + size_t _fread_r(struct _reent *<[ptr]>, void *<[buf]>, + size_t <[size]>, size_t <[count]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include + size_t fread(<[buf]>, <[size]>, <[count]>, <[fp]>) + char *<[buf]>; + size_t <[size]>; + size_t <[count]>; + FILE *<[fp]>; + + #include + size_t _fread_r(<[ptr]>, <[buf]>, <[size]>, <[count]>, <[fp]>) + struct _reent *<[ptr]>; + char *<[buf]>; + size_t <[size]>; + size_t <[count]>; + FILE *<[fp]>; + +DESCRIPTION +<> attempts to copy, from the file or stream identified by +<[fp]>, <[count]> elements (each of size <[size]>) into memory, +starting at <[buf]>. <> may copy fewer elements than +<[count]> if an error, or end of file, intervenes. + +<> 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 <> that +takes an additional reentrant structure pointer argument: <[ptr]>. + +RETURNS +The result of <> is the number of elements it succeeded in +reading. + +PORTABILITY +ANSI C requires <>. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. +*/ + +#include <_ansi.h> +#include +#include +#include +#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_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 diff --git a/programs/develop/libraries/newlib/stdio/freopen.c b/programs/develop/libraries/newlib/stdio/freopen.c new file mode 100644 index 0000000000..9d079ebded --- /dev/null +++ b/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 +<>---open a file using an existing file descriptor + +INDEX + freopen +INDEX + _freopen_r + +ANSI_SYNOPSIS + #include + 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 + 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 <> if you wish to specify a particular file +descriptor <[fp]> (notably <>, <>, or <>) for +the file. + +If <[fp]> was associated with another file or stream, <> +closes that other file or stream (but ignores any errors while closing +it). + +<[file]> and <[mode]> are used just as in <>. + +If <[file]> is <>, 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 <>. + +PORTABILITY +ANSI C requires <>. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>, <>. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#include +#include +#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 */ diff --git a/programs/develop/libraries/newlib/stdio/fscanf.c b/programs/develop/libraries/newlib/stdio/fscanf.c new file mode 100644 index 0000000000..cff3d8accb --- /dev/null +++ b/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 +#include +#ifdef _HAVE_STDC +#include +#else +#include +#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); +} + diff --git a/programs/develop/libraries/newlib/stdio/fseeko.c b/programs/develop/libraries/newlib/stdio/fseeko.c new file mode 100644 index 0000000000..7d30ab66bc --- /dev/null +++ b/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 +#include + +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 */ diff --git a/programs/develop/libraries/newlib/stdio/ftell.c b/programs/develop/libraries/newlib/stdio/ftell.c new file mode 100644 index 0000000000..c2c80f991a --- /dev/null +++ b/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 +<>, <>---return position in a stream or file + +INDEX + ftell +INDEX + ftello +INDEX + _ftell_r +INDEX + _ftello_r + +ANSI_SYNOPSIS + #include + 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 + 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 <> can have a ``position'' that records how much +of the file your program has already read. Many of the <> functions +depend on this position, and many change it as a side effect. + +The result of <>/<> is the current position for a file +identified by <[fp]>. If you record this result, you can later +use it with <>/<> to return the file to this +position. The difference between <> and <> is that +<> returns <> and <> returns <>. + +In the current implementation, <>/<> simply uses a character +count to represent the file position; this is the same number that +would be recorded by <>. + +RETURNS +<>/<> 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 <> indicates this condition with the +value <>. + +PORTABILITY +<> 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 <>. In particular, other +conforming C implementations may return a different result from +<> than what <> records. + +<> 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 +#include +#include +#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 */ diff --git a/programs/develop/libraries/newlib/stdio/ftello.c b/programs/develop/libraries/newlib/stdio/ftello.c new file mode 100644 index 0000000000..3976524811 --- /dev/null +++ b/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 +#include + +_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 */ diff --git a/programs/develop/libraries/newlib/stdio/putchar.c b/programs/develop/libraries/newlib/stdio/putchar.c new file mode 100644 index 0000000000..d4af25cafc --- /dev/null +++ b/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 +<>---write a character (macro) + +INDEX + putchar +INDEX + _putchar_r + +ANSI_SYNOPSIS + #include + int putchar(int <[ch]>); + + int _putchar_r(struct _reent *<[reent]>, int <[ch]>); + +TRAD_SYNOPSIS + #include + int putchar(<[ch]>) + int <[ch]>; + + int _putchar_r(<[reent]>, <[ch]>) + struct _reent *<[reent]>; + int <[ch]>; + +DESCRIPTION +<> is a macro, defined in <>. <> +writes its argument to the standard output stream, +after converting it from an <> to an <>. + +The alternate function <<_putchar_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +If successful, <> returns its argument <[ch]>. If an error +intervenes, the result is <>. You can use `<>' to +query for errors. + +PORTABILITY +ANSI C requires <>; it suggests, but does not require, that +<> be implemented as a macro. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. +*/ + +#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 +#include +#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 diff --git a/programs/develop/libraries/newlib/stdio/remove.c b/programs/develop/libraries/newlib/stdio/remove.c new file mode 100644 index 0000000000..f5dc19c2fa --- /dev/null +++ b/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 +<>---delete a file's name + +INDEX + remove +INDEX + _remove_r + +ANSI_SYNOPSIS + #include + int remove(char *<[filename]>); + + int _remove_r(struct _reent *<[reent]>, char *<[filename]>); + +TRAD_SYNOPSIS + #include + int remove(<[filename]>) + char *<[filename]>; + + int _remove_r(<[reent]>, <[filename]>) + struct _reent *<[reent]>; + char *<[filename]>; + +DESCRIPTION +Use <> to dissolve the association between a particular +filename (the string at <[filename]>) and the file it represents. +After calling <> with a particular filename, you will no +longer be able to open the file by that name. + +In this implementation, you may use <> 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 +<> returns <<0>> if it succeeds, <<-1>> if it fails. + +PORTABILITY +ANSI C requires <>, but only specifies that the result on +failure be nonzero. The behavior of <> when you call it on an +open file may vary among implementations. + +Supporting OS subroutine required: <>. +*/ + +#include <_ansi.h> +#include +#include +#include + + +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 diff --git a/programs/develop/libraries/newlib/stdio/rename.c b/programs/develop/libraries/newlib/stdio/rename.c new file mode 100644 index 0000000000..b341cb200c --- /dev/null +++ b/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 a file + +INDEX + rename + +ANSI_SYNOPSIS + #include + int rename(const char *<[old]>, const char *<[new]>); + +TRAD_SYNOPSIS + #include + int rename(<[old]>, <[new]>) + char *<[old]>; + char *<[new]>; + +DESCRIPTION +Use <> to establish a new name (the string at <[new]>) for a +file now known by the string at <[old]>. After a successful +<>, the file is no longer accessible by the string at <[old]>. + +If <> 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 <>, 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: <>, <>, or <>. +*/ + +#include <_ansi.h> +#include +#include +#include + +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 diff --git a/programs/develop/libraries/newlib/stdio/rget.c b/programs/develop/libraries/newlib/stdio/rget.c new file mode 100644 index 0000000000..0c2bae2e82 --- /dev/null +++ b/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 +#include +#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); +} diff --git a/programs/develop/libraries/newlib/stdio/setvbuf.c b/programs/develop/libraries/newlib/stdio/setvbuf.c new file mode 100644 index 0000000000..537a1a3f8e --- /dev/null +++ b/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 +<>---specify file or stream buffering + +INDEX + setvbuf + +ANSI_SYNOPSIS + #include + int setvbuf(FILE *<[fp]>, char *<[buf]>, + int <[mode]>, size_t <[size]>); + +TRAD_SYNOPSIS + #include + int setvbuf(<[fp]>, <[buf]>, <[mode]>, <[size]>) + FILE *<[fp]>; + char *<[buf]>; + int <[mode]>; + size_t <[size]>; + +DESCRIPTION +Use <> to specify what kind of buffering you want for the +file or stream identified by <[fp]>, by using one of the following +values (from <>) 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 <> +as the <[buf]> argument, and <> will allocate the buffer. + +WARNINGS +You may only use <> 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, <> failure (invalid <[mode]> or +<[size]> can cause failure). + +PORTABILITY +Both ANSI C and the System V Interface Definition (Issue 2) require +<>. However, they differ on the meaning of a <> buffer +pointer: the SVID issue 2 specification says that a <> buffer +pointer requests unbuffered output. For maximum portability, avoid +<> buffer pointers. + +Both specifications describe the result on failure only as a +nonzero value. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>. +*/ + +#include <_ansi.h> +#include +#include +#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; +} diff --git a/programs/develop/libraries/newlib/stdio/tmpfile.c b/programs/develop/libraries/newlib/stdio/tmpfile.c new file mode 100644 index 0000000000..2b526e8746 --- /dev/null +++ b/programs/develop/libraries/newlib/stdio/tmpfile.c @@ -0,0 +1,96 @@ +/* +FUNCTION +<>---create a temporary file + +INDEX + tmpfile +INDEX + _tmpfile_r + +ANSI_SYNOPSIS + #include + FILE *tmpfile(void); + + FILE *_tmpfile_r(struct _reent *<[reent]>); + +TRAD_SYNOPSIS + #include + 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 <>. 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 +<> normally returns a pointer to the temporary file. If no +temporary file could be created, the result is NULL, and <> +records the reason for failure. + +PORTABILITY +Both ANSI C and the System V Interface Definition (Issue 2) require +<>. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>, <>, <>. + +<> also requires the global pointer <>. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include + +#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 diff --git a/programs/develop/libraries/newlib/stdio/tmpnam.c b/programs/develop/libraries/newlib/stdio/tmpnam.c new file mode 100644 index 0000000000..ecfb0436fc --- /dev/null +++ b/programs/develop/libraries/newlib/stdio/tmpnam.c @@ -0,0 +1,209 @@ +/* + * tmpname.c + * Original Author: G. Haley + */ +/* +FUNCTION +<>, <>---name for a temporary file + +INDEX + tmpnam +INDEX + tempnam +INDEX + _tmpnam_r +INDEX + _tempnam_r + +ANSI_SYNOPSIS + #include + 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 + 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 <> calls of either function). + +<> generates file names with the value of <> +(defined in `<>') as the leading directory component of the path. + +You can use the <> argument <[s]> to specify a suitable area +of memory for the generated filename; otherwise, you can call +<> to use an internal static buffer. + +<> 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 <>, <> will attempt to use the value of +environment variable <> instead; if there is no such value, +<> uses the value of <> (defined in `<>'). + +If you don't need any particular prefix to the basename of temporary +files, you can pass <> as the <[pfx]> argument to <>. + +<<_tmpnam_r>> and <<_tempnam_r>> are reentrant versions of <> +and <> 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 <>, you must ensure +that it has room for at least <> elements of type <>. + +RETURNS +Both <> and <> return a pointer to the newly +generated filename. + +PORTABILITY +ANSI C requires <>, but does not specify the use of +<>. The System V Interface Definition (Issue 2) requires +both <> and <>. + +Supporting OS subroutines required: <>, <>, <>, +<>, <>, <>, <>, <>, <>. + +The global pointer <> is also required. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#include + +/* 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 diff --git a/programs/develop/libraries/newlib/stdio/vscanf.c b/programs/develop/libraries/newlib/stdio/vscanf.c new file mode 100644 index 0000000000..e6e0d22ed0 --- /dev/null +++ b/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 +#include +#ifdef _HAVE_STDC +#include +#else +#include +#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); +} + diff --git a/programs/develop/libraries/newlib/stdio/vsscanf.c b/programs/develop/libraries/newlib/stdio/vsscanf.c new file mode 100644 index 0000000000..c19bbeee72 --- /dev/null +++ b/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 +#include +#include +#ifdef _HAVE_STDC +#include +#else +#include +#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); +} diff --git a/programs/develop/libraries/newlib/stdlib/__atexit.c b/programs/develop/libraries/newlib/stdlib/__atexit.c new file mode 100644 index 0000000000..ba7e81620e --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/__atexit.c @@ -0,0 +1,99 @@ +/* + * Common routine to implement atexit-like functionality. + */ + +#include +#include +#include +#include +#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; +} diff --git a/programs/develop/libraries/newlib/stdlib/__call_atexit.c b/programs/develop/libraries/newlib/stdlib/__call_atexit.c new file mode 100644 index 0000000000..86410e2b62 --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/__call_atexit.c @@ -0,0 +1,161 @@ +/* + * COmmon routine to call call registered atexit-like routines. + */ + + +#include +#include +#include +#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 + +} diff --git a/programs/develop/libraries/newlib/stdlib/atof.c b/programs/develop/libraries/newlib/stdlib/atof.c new file mode 100644 index 0000000000..8e98782678 --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/atof.c @@ -0,0 +1,72 @@ +/* +FUNCTION + <>, <>---string to double or float + +INDEX + atof +INDEX + atoff + +ANSI_SYNOPSIS + #include + double atof(const char *<[s]>); + float atoff(const char *<[s]>); + +TRAD_SYNOPSIS + #include + double atof(<[s]>) + char *<[s]>; + + float atoff(<[s]>) + char *<[s]>; + +DESCRIPTION +<> converts the initial portion of a string to a <>. +<> converts the initial portion of a string to a <>. + +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 <> is empty, consists entirely +of whitespace, or if the first non-whitespace character is +something other than <<+>>, <<->>, <<.>>, or a digit. + +<)>> is implemented as <, NULL)>>. +<)>> is implemented as <, NULL)>>. + +RETURNS +<> returns the converted substring value, if any, as a +<>; or <<0.0>>, if no conversion could be performed. +If the correct value is out of the range of representable values, plus +or minus <> is returned, and <> is stored in +<>. +If the correct value would cause underflow, <<0.0>> is returned +and <> is stored in <>. + +<> obeys the same rules as <>, except that it +returns a <>. + +PORTABILITY +<> is ANSI C. <>, <>, and <> are subsumed by <> +and <>, 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: <>, <>, <>, +<>, <>, <>, <>. +*/ + + +#include +#include <_ansi.h> + +double +_DEFUN (atof, (s), + _CONST char *s) +{ + return strtod (s, NULL); +} diff --git a/programs/develop/libraries/newlib/stdlib/div.c b/programs/develop/libraries/newlib/stdlib/div.c new file mode 100644 index 0000000000..402bcf8b6b --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/div.c @@ -0,0 +1,132 @@ +/* +FUNCTION +<
>---divide two integers + +INDEX + div + +ANSI_SYNOPSIS + #include + div_t div(int <[n]>, int <[d]>); + +TRAD_SYNOPSIS + #include + 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 <>. + +RETURNS +The result is represented with the structure + +. typedef struct +. { +. int quot; +. int rem; +. } div_t; + +where the <> field represents the quotient, and <> the +remainder. For nonzero <[d]>, if `<<<[r]> = div(<[n]>,<[d]>);>>' then +<[n]> equals `<<<[r]>.rem + <[d]>*<[r]>.quot>>'. + +To divide <> rather than <> values, use the similar +function <>. + +PORTABILITY +<
> 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 /* 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); +} diff --git a/programs/develop/libraries/newlib/stdlib/exit.c b/programs/develop/libraries/newlib/stdlib/exit.c new file mode 100644 index 0000000000..808eaf4c1f --- /dev/null +++ b/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 +<>---end program execution + +INDEX + exit + +ANSI_SYNOPSIS + #include + void exit(int <[code]>); + +TRAD_SYNOPSIS + #include + void exit(<[code]>) + int <[code]>; + +DESCRIPTION +Use <> 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, <> and +<>, are defined in `<>' to indicate success or +failure in a portable fashion. + +<> does two kinds of cleanup before ending execution of your +program. First, it calls all application-defined cleanup functions +you have enrolled with <>. 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 <> are +deleted. + +RETURNS +<> does not return to its caller. + +PORTABILITY +ANSI C requires <>, and specifies that <> and +<> must be defined. + +Supporting OS subroutines required: <<_exit>>. +*/ + +#include +#include /* for _exit() declaration */ +#include +#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); +} diff --git a/programs/develop/libraries/newlib/stdlib/getenv.c b/programs/develop/libraries/newlib/stdlib/getenv.c new file mode 100644 index 0000000000..e7dcb9fdd2 --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/getenv.c @@ -0,0 +1,93 @@ +/* +FUNCTION +<>---look up environment variable + +INDEX + getenv +INDEX + environ + +ANSI_SYNOPSIS + #include + char *getenv(const char *<[name]>); + +TRAD_SYNOPSIS + #include + char *getenv(<[name]>) + char *<[name]>; + +DESCRIPTION +<> searches the list of environment variable names and values +(using the global pointer ``<>'') for a variable whose +name matches the string at <[name]>. If a variable name matches, +<> returns a pointer to the associated value. + +RETURNS +A pointer to the (string) value of the environment variable, or +<> if there is no such environment variable. + +PORTABILITY +<> is ANSI, but the rules for properly forming names of environment +variables vary from one system to another. + +<> requires a global pointer <>. +*/ + +/* + * 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 +#include +#include + +/* + * _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 */ diff --git a/programs/develop/libraries/newlib/stdlib/mallocr1.c b/programs/develop/libraries/newlib/stdlib/mallocr1.c deleted file mode 100644 index 62b7cf4bac..0000000000 --- a/programs/develop/libraries/newlib/stdlib/mallocr1.c +++ /dev/null @@ -1,1853 +0,0 @@ -/* - This is a version (aka dlmalloc) of malloc/free/realloc written by - Doug Lea and released to the public domain, as explained at - http://creativecommons.org/licenses/publicdomain. Send questions, - comments, complaints, performance data, etc to dl@cs.oswego.edu - -* Version 2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee) - - Note: There may be an updated version of this malloc obtainable at - ftp://gee.cs.oswego.edu/pub/misc/malloc.c - Check before installing! - -* Quickstart - - This library is all in one file to simplify the most common usage: - ftp it, compile it (-O3), and link it into another program. All of - the compile-time options default to reasonable values for use on - most platforms. You might later want to step through various - compile-time and dynamic tuning options. - - For convenience, an include file for code using this malloc is at: - ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.4.h - You don't really need this .h file unless you call functions not - defined in your system include files. The .h file contains only the - excerpts from this file needed for using this malloc on ANSI C/C++ - systems, so long as you haven't changed compile-time options about - naming and tuning parameters. If you do, then you can create your - own malloc.h that does include all settings by cutting at the point - indicated below. Note that you may already by default be using a C - library containing a malloc that is based on some version of this - malloc (for example in linux). You might still want to use the one - in this file to customize settings or to avoid overheads associated - with library versions. - -*/ - -#include -#include -#include - -struct malloc_chunk { - size_t prev_foot; /* Size of previous chunk (if free). */ - size_t head; /* Size and inuse bits. */ - struct malloc_chunk* fd; /* double links -- used only if free. */ - struct malloc_chunk* bk; -}; - -typedef struct malloc_chunk mchunk; -typedef struct malloc_chunk* mchunkptr; -typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ -typedef unsigned int bindex_t; /* Described below */ -typedef unsigned int binmap_t; /* Described below */ -typedef unsigned int flag_t; /* The type of various bit flag sets */ - - - -/* ------------------- size_t and alignment properties -------------------- */ - -/* The maximum possible size_t value has all bits set */ -#define MAX_SIZE_T (~(size_t)0) - -void *user_alloc(size_t size) -{ - void *val; - - __asm__("int3"); - - __asm__ __volatile__( - "int $0x40" - :"=eax"(val) - :"a"(68),"b"(12),"c"(size)); - return val; -} - -static inline -int user_free(void *mem) -{ - int val; - __asm__ __volatile__( - "int $0x40" - :"=eax"(val) - :"a"(68),"b"(12),"c"(mem)); - return val; -} - - -/* ------------------- size_t and alignment properties -------------------- */ - -/* The byte and bit size of a size_t */ -#define SIZE_T_SIZE (sizeof(size_t)) -#define SIZE_T_BITSIZE (sizeof(size_t) << 3) - -/* Some constants coerced to size_t */ -/* Annoying but necessary to avoid errors on some platforms */ -#define SIZE_T_ZERO ((size_t)0) -#define SIZE_T_ONE ((size_t)1) -#define SIZE_T_TWO ((size_t)2) -#define SIZE_T_FOUR ((size_t)4) -#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) -#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) -#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) -#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) - -#define USE_LOCK_BIT (2U) -#define USE_MMAP_BIT (SIZE_T_ONE) -#define USE_NONCONTIGUOUS_BIT (4U) - -/* segment bit set in create_mspace_with_base */ -#define EXTERN_BIT (8U) - -#define HAVE_MMAP 1 -#define CALL_MMAP(s) MMAP_DEFAULT(s) -#define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) -#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL -#define MAX_RELEASE_CHECK_RATE 4095 -#define NO_SEGMENT_TRAVERSAL 1 -#define MALLOC_ALIGNMENT ((size_t)8U) -#define CHUNK_OVERHEAD (SIZE_T_SIZE) -#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) -#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) -#define DEFAULT_TRIM_THRESHOLD ((size_t)512U * (size_t)1024U) - -/* The bit mask value corresponding to MALLOC_ALIGNMENT */ -#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) - -/* True if address a has acceptable alignment */ -#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) - -/* the number of bytes to offset an address to align it */ -#define align_offset(A)\ - ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ - ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) - - -#define MFAIL ((void*)(MAX_SIZE_T)) -#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ - -/* For sys_alloc, enough padding to ensure can malloc request on success */ -#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) - -/* - TOP_FOOT_SIZE is padding at the end of a segment, including space - that may be needed to place segment records and fenceposts when new - noncontiguous segments are added. -*/ -#define TOP_FOOT_SIZE\ - (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) - -/* ------------------- Chunks sizes and alignments ----------------------- */ - -#define MCHUNK_SIZE (sizeof(mchunk)) - -/* MMapped chunks need a second word of overhead ... */ -#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -/* ... and additional padding for fake next-chunk at foot */ -#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) - -/* The smallest size we can malloc is an aligned minimal chunk */ -#define MIN_CHUNK_SIZE\ - ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* conversion from malloc headers to user pointers, and back */ -#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) -#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) -/* chunk associated with aligned address A */ -#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) - -/* Bounds on request (not chunk) sizes. */ -#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) -#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) - -/* pad request bytes into a usable size */ -#define pad_request(req) \ - (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* pad request, checking for minimum (but not maximum) */ -#define request2size(req) \ - (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) - -/* ------------------ Operations on head and foot fields ----------------- */ - -/* - The head field of a chunk is or'ed with PINUSE_BIT when previous - adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in - use, unless mmapped, in which case both bits are cleared. - - FLAG4_BIT is not used by this malloc, but might be useful in extensions. -*/ - -#define PINUSE_BIT (SIZE_T_ONE) -#define CINUSE_BIT (SIZE_T_TWO) -#define FLAG4_BIT (SIZE_T_FOUR) -#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) -#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT) - -/* Head value for fenceposts */ -#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) - -/* extraction of fields from head words */ -#define cinuse(p) ((p)->head & CINUSE_BIT) -#define pinuse(p) ((p)->head & PINUSE_BIT) -#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) -#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) - -#define chunksize(p) ((p)->head & ~(FLAG_BITS)) - -#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) - -/* Treat space at ptr +/- offset as a chunk */ -#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) -#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) - -/* Ptr to next or previous physical malloc_chunk. */ -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS))) -#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) - -/* extract next chunk's pinuse bit */ -#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) - -/* Set size, pinuse bit, and foot */ -#define set_size_and_pinuse_of_free_chunk(p, s)\ - ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) - -/* Set size, pinuse bit, foot, and clear next pinuse */ -#define set_free_with_pinuse(p, s, n)\ - (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) - -/* Get the internal overhead associated with chunk p */ -#define overhead_for(p)\ - (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) - - -struct malloc_tree_chunk { - /* The first four fields must be compatible with malloc_chunk */ - size_t prev_foot; - size_t head; - struct malloc_tree_chunk* fd; - struct malloc_tree_chunk* bk; - - struct malloc_tree_chunk* child[2]; - struct malloc_tree_chunk* parent; - bindex_t index; -}; - -typedef struct malloc_tree_chunk tchunk; -typedef struct malloc_tree_chunk* tchunkptr; -typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ - -/* A little helper macro for trees */ -#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) - - -struct malloc_segment { - char* base; /* base address */ - size_t size; /* allocated size */ - struct malloc_segment* next; /* ptr to next segment */ - flag_t sflags; /* mmap and extern flag */ -}; - -#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) -#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) - -typedef struct malloc_segment msegment; -typedef struct malloc_segment* msegmentptr; - -/* ---------------------------- malloc_state ----------------------------- */ - -/* - A malloc_state holds all of the bookkeeping for a space. - The main fields are: - - Top - The topmost chunk of the currently active segment. Its size is - cached in topsize. The actual size of topmost space is - topsize+TOP_FOOT_SIZE, which includes space reserved for adding - fenceposts and segment records if necessary when getting more - space from the system. The size at which to autotrim top is - cached from mparams in trim_check, except that it is disabled if - an autotrim fails. - - Designated victim (dv) - This is the preferred chunk for servicing small requests that - don't have exact fits. It is normally the chunk split off most - recently to service another small request. Its size is cached in - dvsize. The link fields of this chunk are not maintained since it - is not kept in a bin. - - SmallBins - An array of bin headers for free chunks. These bins hold chunks - with sizes less than MIN_LARGE_SIZE bytes. Each bin contains - chunks of all the same size, spaced 8 bytes apart. To simplify - use in double-linked lists, each bin header acts as a malloc_chunk - pointing to the real first node, if it exists (else pointing to - itself). This avoids special-casing for headers. But to avoid - waste, we allocate only the fd/bk pointers of bins, and then use - repositioning tricks to treat these as the fields of a chunk. - - TreeBins - Treebins are pointers to the roots of trees holding a range of - sizes. There are 2 equally spaced treebins for each power of two - from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything - larger. - - Bin maps - There is one bit map for small bins ("smallmap") and one for - treebins ("treemap). Each bin sets its bit when non-empty, and - clears the bit when empty. Bit operations are then used to avoid - bin-by-bin searching -- nearly all "search" is done without ever - looking at bins that won't be selected. The bit maps - conservatively use 32 bits per map word, even if on 64bit system. - For a good description of some of the bit-based techniques used - here, see Henry S. Warren Jr's book "Hacker's Delight" (and - supplement at http://hackersdelight.org/). Many of these are - intended to reduce the branchiness of paths through malloc etc, as - well as to reduce the number of memory locations read or written. - - Segments - A list of segments headed by an embedded malloc_segment record - representing the initial space. - - Address check support - The least_addr field is the least address ever obtained from - MORECORE or MMAP. Attempted frees and reallocs of any address less - than this are trapped (unless INSECURE is defined). - - Magic tag - A cross-check field that should always hold same value as mparams.magic. - - Flags - Bits recording whether to use MMAP, locks, or contiguous MORECORE - - Statistics - Each space keeps track of current and maximum system memory - obtained via MORECORE or MMAP. - - Trim support - Fields holding the amount of unused topmost memory that should trigger - timming, and a counter to force periodic scanning to release unused - non-topmost segments. - - Locking - If USE_LOCKS is defined, the "mutex" lock is acquired and released - around every public call using this mspace. - - Extension support - A void* pointer and a size_t field that can be used to help implement - extensions to this malloc. -*/ - -/* Bin types, widths and sizes */ -#define NSMALLBINS (32U) -#define NTREEBINS (32U) -#define SMALLBIN_SHIFT (3U) -#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) -#define TREEBIN_SHIFT (8U) -#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) -#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) -#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) - -struct malloc_state { - binmap_t smallmap; - binmap_t treemap; - size_t dvsize; - size_t topsize; - char* least_addr; - mchunkptr dv; - mchunkptr top; - size_t trim_check; - size_t release_checks; - size_t magic; - mchunkptr smallbins[(NSMALLBINS+1)*2]; - tbinptr treebins[NTREEBINS]; - size_t footprint; - size_t max_footprint; - flag_t mflags; - struct mutex lock; /* locate lock among fields that rarely change */ - msegment seg; - void* extp; /* Unused but available for extensions */ - size_t exts; -}; - -typedef struct malloc_state* mstate; - -/* ------------- Global malloc_state and malloc_params ------------------- */ - -/* - malloc_params holds global properties, including those that can be - dynamically set using mallopt. There is a single instance, mparams, - initialized in init_mparams. Note that the non-zeroness of "magic" - also serves as an initialization flag. -*/ - -struct malloc_params -{ - volatile size_t magic; - size_t page_size; - size_t granularity; - size_t mmap_threshold; - size_t trim_threshold; - flag_t default_mflags; -}; - -static struct malloc_params mparams; - -#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams()) - -static struct malloc_state _gm_; -#define gm (&_gm_) -#define is_global(M) ((M) == &_gm_) - -#define is_initialized(M) ((M)->top != 0) - - -//struct mutex malloc_global_mutex; - -static DEFINE_MUTEX(malloc_global_mutex); - -#define ACQUIRE_MALLOC_GLOBAL_LOCK() MutexLock(&malloc_global_mutex); -#define RELEASE_MALLOC_GLOBAL_LOCK() MutexUnlock(&malloc_global_mutex); - -#define PREACTION(M) ( MutexLock(&(M)->lock)) -#define POSTACTION(M) { MutexUnlock(&(M)->lock); } - - -/* ---------------------------- Indexing Bins ---------------------------- */ - -#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) -#define small_index(s) ((s) >> SMALLBIN_SHIFT) -#define small_index2size(i) ((i) << SMALLBIN_SHIFT) -#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) - -/* addressing by index. See above about smallbin repositioning */ -#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) -#define treebin_at(M,i) (&((M)->treebins[i])) - - -#define compute_tree_index(S, I)\ -{\ - unsigned int X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K;\ - __asm__("bsrl\t%1, %0\n\t" : "=r" (K) : "g" (X));\ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} - -/* Bit representing maximum resolved size in a treebin at i */ -#define bit_for_tree_index(i) \ - (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) - -/* Shift placing maximum resolved bit in a treebin at i as sign bit */ -#define leftshift_for_tree_index(i) \ - ((i == NTREEBINS-1)? 0 : \ - ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) - -/* The size of the smallest chunk held in bin with index i */ -#define minsize_for_tree_index(i) \ - ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ - (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) - - -/* ------------------------ Operations on bin maps ----------------------- */ - -/* bit corresponding to given index */ -#define idx2bit(i) ((binmap_t)(1) << (i)) - -/* Mark/Clear bits with given index */ -#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) -#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) -#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) - -#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) -#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) -#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) - -/* isolate the least set bit of a bitmap */ -#define least_bit(x) ((x) & -(x)) - -/* mask with all bits to left of least bit of x on */ -#define left_bits(x) ((x<<1) | -(x<<1)) - -/* mask with all bits to left of or equal to least bit of x on */ -#define same_or_left_bits(x) ((x) | -(x)) - - -/* index corresponding to given bit. Use x86 asm if possible */ - -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - __asm__("bsfl\t%1, %0\n\t" : "=r" (J) : "g" (X));\ - I = (bindex_t)J;\ -} - - -#define mark_inuse_foot(M,p,s) - -/* Get/set size at footer */ -#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) -#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) - -/* Macros for setting head/foot of non-mmapped chunks */ - -/* Set cinuse bit and pinuse bit of next chunk */ -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set size, cinuse and pinuse bit of this chunk */ -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) - - -#define assert(x) -#define RTCHECK(e) __builtin_expect(e, 1) - -#define check_free_chunk(M,P) -#define check_inuse_chunk(M,P) -#define check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) -#define check_malloc_state(M) -#define check_top_chunk(M,P) - -/* Check if address a is at least as high as any from MORECORE or MMAP */ -#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) -/* Check if address of next chunk n is higher than base chunk p */ -#define ok_next(p, n) ((char*)(p) < (char*)(n)) -/* Check if p has inuse status */ -#define ok_inuse(p) is_inuse(p) -/* Check if p has its pinuse bit on */ -#define ok_pinuse(p) pinuse(p) - -#define CORRUPTION_ERROR_ACTION(m) \ - do { \ - printf("%s malloc heap corrupted\n",__FUNCTION__); \ - while(1) \ - { \ - delay(100); \ - } \ - }while(0) \ - - -#define USAGE_ERROR_ACTION(m, p) \ - do { \ - printf("%s malloc heap corrupted\n",__FUNCTION__); \ - while(1) \ - { \ - delay(100); \ - } \ - }while(0) \ - -/* ----------------------- Operations on smallbins ----------------------- */ - -/* - Various forms of linking and unlinking are defined as macros. Even - the ones for trees, which are very long but have very short typical - paths. This is ugly but reduces reliance on inlining support of - compilers. -*/ - -/* Link a free chunk into a smallbin */ -#define insert_small_chunk(M, P, S) {\ - bindex_t I = small_index(S);\ - mchunkptr B = smallbin_at(M, I);\ - mchunkptr F = B;\ - assert(S >= MIN_CHUNK_SIZE);\ - if (!smallmap_is_marked(M, I))\ - mark_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, B->fd)))\ - F = B->fd;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - B->fd = P;\ - F->bk = P;\ - P->fd = F;\ - P->bk = B;\ -} - -/* Unlink a chunk from a smallbin */ -#define unlink_small_chunk(M, P, S) {\ - mchunkptr F = P->fd;\ - mchunkptr B = P->bk;\ - bindex_t I = small_index(S);\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (F == B)\ - clear_smallmap(M, I);\ - else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\ - (B == smallbin_at(M,I) || ok_address(M, B)))) {\ - F->bk = B;\ - B->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Unlink the first chunk from a smallbin */ -#define unlink_first_small_chunk(M, B, P, I) {\ - mchunkptr F = P->fd;\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (B == F)\ - clear_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, F))) {\ - B->fd = F;\ - F->bk = B;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Replace dv node, binning the old one */ -/* Used only when dvsize known to be small */ -#define replace_dv(M, P, S) {\ - size_t DVS = M->dvsize;\ - if (DVS != 0) {\ - mchunkptr DV = M->dv;\ - assert(is_small(DVS));\ - insert_small_chunk(M, DV, DVS);\ - }\ - M->dvsize = S;\ - M->dv = P;\ -} - - -/* ------------------------- Operations on trees ------------------------- */ - -/* Insert chunk into tree */ -#define insert_large_chunk(M, X, S) {\ - tbinptr* H;\ - bindex_t I;\ - compute_tree_index(S, I);\ - H = treebin_at(M, I);\ - X->index = I;\ - X->child[0] = X->child[1] = 0;\ - if (!treemap_is_marked(M, I)) {\ - mark_treemap(M, I);\ - *H = X;\ - X->parent = (tchunkptr)H;\ - X->fd = X->bk = X;\ - }\ - else {\ - tchunkptr T = *H;\ - size_t K = S << leftshift_for_tree_index(I);\ - for (;;) {\ - if (chunksize(T) != S) {\ - tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ - K <<= 1;\ - if (*C != 0)\ - T = *C;\ - else if (RTCHECK(ok_address(M, C))) {\ - *C = X;\ - X->parent = T;\ - X->fd = X->bk = X;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - else {\ - tchunkptr F = T->fd;\ - if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ - T->fd = F->bk = X;\ - X->fd = F;\ - X->bk = T;\ - X->parent = 0;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - }\ - }\ -} - -/* - Unlink steps: - - 1. If x is a chained node, unlink it from its same-sized fd/bk links - and choose its bk node as its replacement. - 2. If x was the last node of its size, but not a leaf node, it must - be replaced with a leaf node (not merely one with an open left or - right), to make sure that lefts and rights of descendents - correspond properly to bit masks. We use the rightmost descendent - of x. We could use any other leaf, but this is easy to locate and - tends to counteract removal of leftmosts elsewhere, and so keeps - paths shorter than minimally guaranteed. This doesn't loop much - because on average a node in a tree is near the bottom. - 3. If x is the base of a chain (i.e., has parent links) relink - x's parent and children to x's replacement (or null if none). -*/ - -#define unlink_large_chunk(M, X) {\ - tchunkptr XP = X->parent;\ - tchunkptr R;\ - if (X->bk != X) {\ - tchunkptr F = X->fd;\ - R = X->bk;\ - if (RTCHECK(ok_address(M, F))) {\ - F->bk = R;\ - R->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else {\ - tchunkptr* RP;\ - if (((R = *(RP = &(X->child[1]))) != 0) ||\ - ((R = *(RP = &(X->child[0]))) != 0)) {\ - tchunkptr* CP;\ - while ((*(CP = &(R->child[1])) != 0) ||\ - (*(CP = &(R->child[0])) != 0)) {\ - R = *(RP = CP);\ - }\ - if (RTCHECK(ok_address(M, RP)))\ - *RP = 0;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - }\ - if (XP != 0) {\ - tbinptr* H = treebin_at(M, X->index);\ - if (X == *H) {\ - if ((*H = R) == 0) \ - clear_treemap(M, X->index);\ - }\ - else if (RTCHECK(ok_address(M, XP))) {\ - if (XP->child[0] == X) \ - XP->child[0] = R;\ - else \ - XP->child[1] = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - if (R != 0) {\ - if (RTCHECK(ok_address(M, R))) {\ - tchunkptr C0, C1;\ - R->parent = XP;\ - if ((C0 = X->child[0]) != 0) {\ - if (RTCHECK(ok_address(M, C0))) {\ - R->child[0] = C0;\ - C0->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - if ((C1 = X->child[1]) != 0) {\ - if (RTCHECK(ok_address(M, C1))) {\ - R->child[1] = C1;\ - C1->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ -} - -/* Relays to large vs small bin operations */ - -#define insert_chunk(M, P, S)\ - if (is_small(S)) insert_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } - -#define unlink_chunk(M, P, S)\ - if (is_small(S)) unlink_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } - - -/* -------------------------- system alloc setup ------------------------- */ - -/* Operations on mflags */ - -#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) -#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) -#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) - -#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) -#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) -#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) - -#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) -#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) - -#define set_lock(M,L)\ - ((M)->mflags = (L)?\ - ((M)->mflags | USE_LOCK_BIT) :\ - ((M)->mflags & ~USE_LOCK_BIT)) - -/* page-align a size */ -#define page_align(S)\ - (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) - -/* granularity-align a size */ -#define granularity_align(S)\ - (((S) + (mparams.granularity - SIZE_T_ONE))\ - & ~(mparams.granularity - SIZE_T_ONE)) - - -/* For mmap, use granularity alignment */ -#define mmap_align(S) granularity_align(S) - -/* For sys_alloc, enough padding to ensure can malloc request on success */ -#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) - -#define is_page_aligned(S)\ - (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) -#define is_granularity_aligned(S)\ - (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) - -/* True if segment S holds address A */ -#define segment_holds(S, A)\ - ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) - -/* Return segment holding given address */ -static msegmentptr segment_holding(mstate m, char* addr) -{ - msegmentptr sp = &m->seg; - for (;;) { - if (addr >= sp->base && addr < sp->base + sp->size) - return sp; - if ((sp = sp->next) == 0) - return 0; - } -} - -/* Return true if segment contains a segment link */ -static int has_segment_link(mstate m, msegmentptr ss) -{ - msegmentptr sp = &m->seg; - for (;;) { - if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) - return 1; - if ((sp = sp->next) == 0) - return 0; - } -} - -static inline void* os_mmap(size_t size) -{ - void* ptr = KernelAlloc(size); - return (ptr != 0)? ptr: MFAIL; -} - -static inline int os_munmap(void* ptr, size_t size) -{ - return (KernelFree(ptr) != 0) ? 0 : -1; -} - -#define should_trim(M,s) ((s) > (M)->trim_check) - - -#define MMAP_DEFAULT(s) os_mmap(s) -#define MUNMAP_DEFAULT(a, s) os_munmap((a), (s)) -#define DIRECT_MMAP_DEFAULT(s) os_mmap(s) - -#define internal_malloc(m, b) malloc(b) -#define internal_free(m, mem) free(mem) - -/* ----------------------- Direct-mmapping chunks ----------------------- */ - -/* - Directly mmapped chunks are set up with an offset to the start of - the mmapped region stored in the prev_foot field of the chunk. This - allows reconstruction of the required argument to MUNMAP when freed, - and also allows adjustment of the returned chunk to meet alignment - requirements (especially in memalign). -*/ - -/* Malloc using mmap */ -static void* mmap_alloc(mstate m, size_t nb) -{ - size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - if (mmsize > nb) /* Check for wrap around 0 */ - { - char* mm = (char*)(os_mmap(mmsize)); - if (mm != CMFAIL) - { - size_t offset = align_offset(chunk2mem(mm)); - size_t psize = mmsize - offset - MMAP_FOOT_PAD; - mchunkptr p = (mchunkptr)(mm + offset); - p->prev_foot = offset; - p->head = psize; - mark_inuse_foot(m, p, psize); - chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; - - if (m->least_addr == 0 || mm < m->least_addr) - m->least_addr = mm; - if ((m->footprint += mmsize) > m->max_footprint) - m->max_footprint = m->footprint; - assert(is_aligned(chunk2mem(p))); - check_mmapped_chunk(m, p); - return chunk2mem(p); - } - } - return 0; -} - -/* Realloc using mmap */ -static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) -{ - size_t oldsize = chunksize(oldp); - if (is_small(nb)) /* Can't shrink mmap regions below small size */ - return 0; - /* Keep old chunk if big enough but not too big */ - if (oldsize >= nb + SIZE_T_SIZE && - (oldsize - nb) <= (mparams.granularity << 1)) - return oldp; - else - { - size_t offset = oldp->prev_foot; - size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; - size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - char* cp = (char*)CALL_MREMAP((char*)oldp - offset, - oldmmsize, newmmsize, 1); - if (cp != CMFAIL) - { - mchunkptr newp = (mchunkptr)(cp + offset); - size_t psize = newmmsize - offset - MMAP_FOOT_PAD; - newp->head = psize; - mark_inuse_foot(m, newp, psize); - chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; - - if (cp < m->least_addr) - m->least_addr = cp; - if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) - m->max_footprint = m->footprint; - check_mmapped_chunk(m, newp); - return newp; - } - } - return 0; -} - -/* ---------------------------- setting mparams -------------------------- */ - -/* Initialize mparams */ -static int init_mparams(void) { - - ACQUIRE_MALLOC_GLOBAL_LOCK(); - - if (mparams.magic == 0) - { - size_t magic; - size_t psize; - size_t gsize; - - psize = 4096; - gsize = DEFAULT_GRANULARITY; - - /* Sanity-check configuration: - size_t must be unsigned and as wide as pointer type. - ints must be at least 4 bytes. - alignment must be at least 8. - Alignment, min chunk size, and page size must all be powers of 2. - */ - - mparams.granularity = gsize; - mparams.page_size = psize; - mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; - mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; - - /* Set up lock for main malloc area */ - gm->mflags = mparams.default_mflags; - MutexInit(&gm->lock); - - magic = (size_t)(GetTimerTicks() ^ (size_t)0x55555555U); - magic |= (size_t)8U; /* ensure nonzero */ - magic &= ~(size_t)7U; /* improve chances of fault for bad values */ - mparams.magic = magic; - } - - RELEASE_MALLOC_GLOBAL_LOCK(); - return 1; -} - -/* -------------------------- mspace management -------------------------- */ - -/* Initialize top chunk and its size */ -static void init_top(mstate m, mchunkptr p, size_t psize) -{ - /* Ensure alignment */ - size_t offset = align_offset(chunk2mem(p)); - p = (mchunkptr)((char*)p + offset); - psize -= offset; - - m->top = p; - m->topsize = psize; - p->head = psize | PINUSE_BIT; - /* set size of fake trailing chunk holding overhead space only once */ - chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; - m->trim_check = mparams.trim_threshold; /* reset on each update */ -} - -/* Initialize bins for a new mstate that is otherwise zeroed out */ -static void init_bins(mstate m) -{ - /* Establish circular links for smallbins */ - bindex_t i; - for (i = 0; i < NSMALLBINS; ++i) { - sbinptr bin = smallbin_at(m,i); - bin->fd = bin->bk = bin; - } -} - -/* Allocate chunk and prepend remainder with chunk in successor base. */ -static void* prepend_alloc(mstate m, char* newbase, char* oldbase, - size_t nb) -{ - mchunkptr p = align_as_chunk(newbase); - mchunkptr oldfirst = align_as_chunk(oldbase); - size_t psize = (char*)oldfirst - (char*)p; - mchunkptr q = chunk_plus_offset(p, nb); - size_t qsize = psize - nb; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - - assert((char*)oldfirst > (char*)q); - assert(pinuse(oldfirst)); - assert(qsize >= MIN_CHUNK_SIZE); - - /* consolidate remainder with first chunk of old base */ - if (oldfirst == m->top) { - size_t tsize = m->topsize += qsize; - m->top = q; - q->head = tsize | PINUSE_BIT; - check_top_chunk(m, q); - } - else if (oldfirst == m->dv) { - size_t dsize = m->dvsize += qsize; - m->dv = q; - set_size_and_pinuse_of_free_chunk(q, dsize); - } - else { - if (!is_inuse(oldfirst)) { - size_t nsize = chunksize(oldfirst); - unlink_chunk(m, oldfirst, nsize); - oldfirst = chunk_plus_offset(oldfirst, nsize); - qsize += nsize; - } - set_free_with_pinuse(q, qsize, oldfirst); - insert_chunk(m, q, qsize); - check_free_chunk(m, q); - } - - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); -} - -/* Add a segment to hold a new noncontiguous region */ -static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) -{ - /* Determine locations and sizes of segment, fenceposts, old top */ - char* old_top = (char*)m->top; - msegmentptr oldsp = segment_holding(m, old_top); - char* old_end = oldsp->base + oldsp->size; - size_t ssize = pad_request(sizeof(struct malloc_segment)); - char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - size_t offset = align_offset(chunk2mem(rawsp)); - char* asp = rawsp + offset; - char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; - mchunkptr sp = (mchunkptr)csp; - msegmentptr ss = (msegmentptr)(chunk2mem(sp)); - mchunkptr tnext = chunk_plus_offset(sp, ssize); - mchunkptr p = tnext; - int nfences = 0; - - /* reset top to new space */ - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - - /* Set up segment record */ - assert(is_aligned(ss)); - set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); - *ss = m->seg; /* Push current record */ - m->seg.base = tbase; - m->seg.size = tsize; - m->seg.sflags = mmapped; - m->seg.next = ss; - - /* Insert trailing fenceposts */ - for (;;) { - mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); - p->head = FENCEPOST_HEAD; - ++nfences; - if ((char*)(&(nextp->head)) < old_end) - p = nextp; - else - break; - } - assert(nfences >= 2); - - /* Insert the rest of old top into a bin as an ordinary free chunk */ - if (csp != old_top) { - mchunkptr q = (mchunkptr)old_top; - size_t psize = csp - old_top; - mchunkptr tn = chunk_plus_offset(q, psize); - set_free_with_pinuse(q, psize, tn); - insert_chunk(m, q, psize); - } - - check_top_chunk(m, m->top); -} - -/* -------------------------- System allocation -------------------------- */ - -/* Get memory from system using MORECORE or MMAP */ -static void* sys_alloc(mstate m, size_t nb) -{ - char* tbase = CMFAIL; - size_t tsize = 0; - flag_t mmap_flag = 0; - - ensure_initialization(); - - /* Directly map large chunks, but only if already initialized */ - if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) - { - void* mem = mmap_alloc(m, nb); - if (mem != 0) - return mem; - } - - /* - Try getting memory in any of three ways (in most-preferred to - least-preferred order): - 1. A call to MORECORE that can normally contiguously extend memory. - (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) - 2. A call to MMAP new space (disabled if not HAVE_MMAP). - Note that under the default settings, if MORECORE is unable to - fulfill a request, and HAVE_MMAP is true, then mmap is - used as a noncontiguous system allocator. This is a useful backup - strategy for systems with holes in address spaces -- in this case - sbrk cannot contiguously expand the heap, but mmap may be able to - find space. - 3. A call to MORECORE that cannot usually contiguously extend memory. - (disabled if not HAVE_MORECORE) - - In all cases, we need to request enough bytes from system to ensure - we can malloc nb bytes upon success, so pad with enough space for - top_foot, plus alignment-pad to make sure we don't lose bytes if - not on boundary, and round this up to a granularity unit. - */ - - if (HAVE_MMAP && tbase == CMFAIL) /* Try MMAP */ - { - size_t rsize = granularity_align(nb + SYS_ALLOC_PADDING); - if (rsize > nb) /* Fail if wraps around zero */ - { - char* mp = (char*)(CALL_MMAP(rsize)); - if (mp != CMFAIL) - { - tbase = mp; - tsize = rsize; - mmap_flag = USE_MMAP_BIT; - } - } - } - - - if (tbase != CMFAIL) - { - - if ((m->footprint += tsize) > m->max_footprint) - m->max_footprint = m->footprint; - - if (!is_initialized(m)) /* first-time initialization */ - { - if (m->least_addr == 0 || tbase < m->least_addr) - m->least_addr = tbase; - m->seg.base = tbase; - m->seg.size = tsize; - m->seg.sflags = mmap_flag; - m->magic = mparams.magic; - m->release_checks = MAX_RELEASE_CHECK_RATE; - init_bins(m); - - if (is_global(m)) - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - else - { - /* Offset top by embedded malloc_state */ - mchunkptr mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); - } - } - else - { - /* Try to merge with an existing segment */ - msegmentptr sp = &m->seg; - /* Only consider most recent segment if traversal suppressed */ - while (sp != 0 && tbase != sp->base + sp->size) - sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; - if (sp != 0 && !is_extern_segment(sp) && - (sp->sflags & USE_MMAP_BIT) == mmap_flag && - segment_holds(sp, m->top)) /* append */ - { - sp->size += tsize; - init_top(m, m->top, m->topsize + tsize); - } - else - { - if (tbase < m->least_addr) - m->least_addr = tbase; - sp = &m->seg; - while (sp != 0 && sp->base != tbase + tsize) - sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - (sp->sflags & USE_MMAP_BIT) == mmap_flag) - { - char* oldbase = sp->base; - sp->base = tbase; - sp->size += tsize; - return prepend_alloc(m, tbase, oldbase, nb); - } - else - add_segment(m, tbase, tsize, mmap_flag); - } - } - - if (nb < m->topsize) /* Allocate from new or extended top space */ - { - size_t rsize = m->topsize -= nb; - mchunkptr p = m->top; - mchunkptr r = m->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - check_top_chunk(m, m->top); - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); - } - } - -// MALLOC_FAILURE_ACTION; - return 0; -} - - -/* ----------------------- system deallocation -------------------------- */ - -/* Unmap and unlink any mmapped segments that don't contain used chunks */ -static size_t release_unused_segments(mstate m) -{ - size_t released = 0; - int nsegs = 0; - msegmentptr pred = &m->seg; - msegmentptr sp = pred->next; - while (sp != 0) - { - char* base = sp->base; - size_t size = sp->size; - msegmentptr next = sp->next; - ++nsegs; - if (is_mmapped_segment(sp) && !is_extern_segment(sp)) - { - mchunkptr p = align_as_chunk(base); - size_t psize = chunksize(p); - /* Can unmap if first chunk holds entire segment and not pinned */ - if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) - { - tchunkptr tp = (tchunkptr)p; - assert(segment_holds(sp, (char*)sp)); - if (p == m->dv) { - m->dv = 0; - m->dvsize = 0; - } - else { - unlink_large_chunk(m, tp); - } - if (CALL_MUNMAP(base, size) == 0) - { - released += size; - m->footprint -= size; - /* unlink obsoleted record */ - sp = pred; - sp->next = next; - } - else { /* back out if cannot unmap */ - insert_large_chunk(m, tp, psize); - } - } - } - if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ - break; - pred = sp; - sp = next; - } - /* Reset check counter */ - m->release_checks = ((nsegs > MAX_RELEASE_CHECK_RATE)? - nsegs : MAX_RELEASE_CHECK_RATE); - return released; -} - -static int sys_trim(mstate m, size_t pad) -{ - size_t released = 0; - ensure_initialization(); - if (pad < MAX_REQUEST && is_initialized(m)) - { - pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ - - if (m->topsize > pad) - { - /* Shrink top space in granularity-size units, keeping at least one */ - size_t unit = mparams.granularity; - size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - - SIZE_T_ONE) * unit; - msegmentptr sp = segment_holding(m, (char*)m->top); - - if (!is_extern_segment(sp)) - { - if (is_mmapped_segment(sp)) - { - if (HAVE_MMAP && - sp->size >= extra && - !has_segment_link(m, sp)) /* can't shrink if pinned */ - { - size_t newsize = sp->size - extra; - /* Prefer mremap, fall back to munmap */ - if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || - (CALL_MUNMAP(sp->base + newsize, extra) == 0)) - { - released = extra; - } - } - } - } - - if (released != 0) - { - sp->size -= released; - m->footprint -= released; - init_top(m, m->top, m->topsize - released); - check_top_chunk(m, m->top); - } - } - - /* Unmap any unused mmapped segments */ - if (HAVE_MMAP) - released += release_unused_segments(m); - - /* On failure, disable autotrim to avoid repeated failed future calls */ - if (released == 0 && m->topsize > m->trim_check) - m->trim_check = MAX_SIZE_T; - } - - return (released != 0)? 1 : 0; -} - - - -/* ---------------------------- malloc support --------------------------- */ - -/* allocate a large request from the best fitting chunk in a treebin */ -static void* tmalloc_large(mstate m, size_t nb) { - tchunkptr v = 0; - size_t rsize = -nb; /* Unsigned negation */ - tchunkptr t; - bindex_t idx; - compute_tree_index(nb, idx); - if ((t = *treebin_at(m, idx)) != 0) { - /* Traverse tree for this bin looking for node with size == nb */ - size_t sizebits = nb << leftshift_for_tree_index(idx); - tchunkptr rst = 0; /* The deepest untaken right subtree */ - for (;;) { - tchunkptr rt; - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - v = t; - if ((rsize = trem) == 0) - break; - } - rt = t->child[1]; - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - if (rt != 0 && rt != t) - rst = rt; - if (t == 0) { - t = rst; /* set t to least subtree holding sizes > nb */ - break; - } - sizebits <<= 1; - } - } - if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ - binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; - if (leftbits != 0) { - bindex_t i; - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - t = *treebin_at(m, i); - } - } - - while (t != 0) { /* find smallest of tree or subtree */ - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - t = leftmost_child(t); - } - - /* If dv is a better fit, return 0 so malloc will use it */ - if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { - if (RTCHECK(ok_address(m, v))) { /* split */ - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - insert_chunk(m, r, rsize); - } - return chunk2mem(v); - } - } - CORRUPTION_ERROR_ACTION(m); - } - return 0; -} - -/* allocate a small request from the best fitting chunk in a treebin */ -static void* tmalloc_small(mstate m, size_t nb) -{ - tchunkptr t, v; - size_t rsize; - bindex_t i; - binmap_t leastbit = least_bit(m->treemap); - compute_bit2idx(leastbit, i); - v = t = *treebin_at(m, i); - rsize = chunksize(t) - nb; - - while ((t = leftmost_child(t)) != 0) { - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - } - - if (RTCHECK(ok_address(m, v))) { - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(m, r, rsize); - } - return chunk2mem(v); - } - } - - CORRUPTION_ERROR_ACTION(m); - return 0; -} - -/* --------------------------- memalign support -------------------------- */ - -static void* internal_memalign(mstate m, size_t alignment, size_t bytes) -{ - if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */ - return internal_malloc(m, bytes); - if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ - alignment = MIN_CHUNK_SIZE; - if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ - size_t a = MALLOC_ALIGNMENT << 1; - while (a < alignment) a <<= 1; - alignment = a; - } - - if (bytes >= MAX_REQUEST - alignment) { - if (m != 0) { /* Test isn't needed but avoids compiler warning */ -// MALLOC_FAILURE_ACTION; - } - } - else - { - size_t nb = request2size(bytes); - size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; - char* mem = (char*)internal_malloc(m, req); - if (mem != 0) - { - void* leader = 0; - void* trailer = 0; - mchunkptr p = mem2chunk(mem); - - PREACTION(m); - - if ((((size_t)(mem)) % alignment) != 0) /* misaligned */ - { - /* - Find an aligned spot inside chunk. Since we need to give - back leading space in a chunk of at least MIN_CHUNK_SIZE, if - the first calculation places us at a spot with less than - MIN_CHUNK_SIZE leader, we can move to the next aligned spot. - We've allocated enough total room so that this is always - possible. - */ - char* br = (char*)mem2chunk((size_t)(((size_t)(mem + - alignment - - SIZE_T_ONE)) & - -alignment)); - char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? - br : br+alignment; - mchunkptr newp = (mchunkptr)pos; - size_t leadsize = pos - (char*)(p); - size_t newsize = chunksize(p) - leadsize; - - if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ - newp->prev_foot = p->prev_foot + leadsize; - newp->head = newsize; - } - else { /* Otherwise, give back leader, use the rest */ - set_inuse(m, newp, newsize); - set_inuse(m, p, leadsize); - leader = chunk2mem(p); - } - p = newp; - } - - /* Give back spare room at the end */ - if (!is_mmapped(p)) - { - size_t size = chunksize(p); - if (size > nb + MIN_CHUNK_SIZE) - { - size_t remainder_size = size - nb; - mchunkptr remainder = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, remainder, remainder_size); - trailer = chunk2mem(remainder); - } - } - - assert (chunksize(p) >= nb); - assert((((size_t)(chunk2mem(p))) % alignment) == 0); - check_inuse_chunk(m, p); - POSTACTION(m); - if (leader != 0) { - internal_free(m, leader); - } - if (trailer != 0) { - internal_free(m, trailer); - } - return chunk2mem(p); - } - } - return 0; -} - -void* memalign(size_t alignment, size_t bytes) -{ - return internal_memalign(gm, alignment, bytes); -} - - -void* malloc(size_t bytes) -{ - /* - Basic algorithm: - If a small request (< 256 bytes minus per-chunk overhead): - 1. If one exists, use a remainderless chunk in associated smallbin. - (Remainderless means that there are too few excess bytes to - represent as a chunk.) - 2. If it is big enough, use the dv chunk, which is normally the - chunk adjacent to the one used for the most recent small request. - 3. If one exists, split the smallest available chunk in a bin, - saving remainder in dv. - 4. If it is big enough, use the top chunk. - 5. If available, get memory from system and use it - Otherwise, for a large request: - 1. Find the smallest available binned chunk that fits, and use it - if it is better fitting than dv chunk, splitting if necessary. - 2. If better fitting than any binned chunk, use the dv chunk. - 3. If it is big enough, use the top chunk. - 4. If request size >= mmap threshold, try to directly mmap this chunk. - 5. If available, get memory from system and use it - - The ugly goto's here ensure that postaction occurs along all paths. - */ - - ensure_initialization(); /* initialize in sys_alloc if not using locks */ - - PREACTION(gm); - { - void* mem; - size_t nb; - - if (bytes <= MAX_SMALL_REQUEST) - { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = gm->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) /* Remainderless fit to a smallbin. */ - { - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(gm, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(gm, b, p, idx); - set_inuse_and_pinuse(gm, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - else if (nb > gm->dvsize) - { - if (smallbits != 0) /* Use chunk in next nonempty smallbin */ - { - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(gm, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(gm, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(gm, p, small_index2size(i)); - else - { - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(gm, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) - { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else - { - nb = pad_request(bytes); - if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) - { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - - if (nb <= gm->dvsize) { - size_t rsize = gm->dvsize - nb; - mchunkptr p = gm->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = gm->dv = chunk_plus_offset(p, nb); - gm->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - } - else { /* exhaust dv */ - size_t dvs = gm->dvsize; - gm->dvsize = 0; - gm->dv = 0; - set_inuse_and_pinuse(gm, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - else if (nb < gm->topsize) { /* Split top */ - size_t rsize = gm->topsize -= nb; - mchunkptr p = gm->top; - mchunkptr r = gm->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - mem = chunk2mem(p); - check_top_chunk(gm, gm->top); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - mem = sys_alloc(gm, nb); - - postaction: - POSTACTION(gm); - return mem; - } - - return 0; -} - - -void free(void* mem) -{ - /* - Consolidate freed chunks with preceeding or succeeding bordering - free chunks, if they exist, and then place in a bin. Intermixed - with special cases for top, dv, mmapped chunks, and usage errors. - */ - - if (mem != 0) - { - mchunkptr p = mem2chunk(mem); - -#define fm gm - - PREACTION(fm); - { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) - { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) - { - size_t prevsize = p->prev_foot; - if (is_mmapped(p)) - { - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else - { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) /* consolidate backward */ - { - if (p != fm->dv) - { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) - { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) - { - if (!cinuse(next)) /* consolidate forward */ - { - if (next == fm->top) - { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) - { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) - { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else - { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) - { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - - if (is_small(psize)) - { - insert_small_chunk(fm, p, psize); - check_free_chunk(fm, p); - } - else - { - tchunkptr tp = (tchunkptr)p; - insert_large_chunk(fm, tp, psize); - check_free_chunk(fm, p); - if (--fm->release_checks == 0) - release_unused_segments(fm); - } - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -#undef fm -} - - diff --git a/programs/develop/libraries/newlib/stdlib/rand.c b/programs/develop/libraries/newlib/stdlib/rand.c new file mode 100644 index 0000000000..024237d106 --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/rand.c @@ -0,0 +1,91 @@ +/* +FUNCTION +<>, <>---pseudo-random numbers + +INDEX + rand +INDEX + srand +INDEX + rand_r + +ANSI_SYNOPSIS + #include + int rand(void); + void srand(unsigned int <[seed]>); + int rand_r(unsigned int *<[seed]>); + +TRAD_SYNOPSIS + #include + int rand(); + + void srand(<[seed]>) + unsigned int <[seed]>; + + void rand_r(<[seed]>) + unsigned int *<[seed]>; + + +DESCRIPTION +<> 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 <> 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 <>. + +You can set the random seed using <>; it does nothing beyond +storing its argument in the static variable used by <>. 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 <>; or, if you wish to ensure +(for example, while debugging) that successive runs of your program +use the same ``random'' numbers, you can use <> to set the same +random seed at the outset. + +RETURNS +<> returns the next pseudo-random integer in sequence; it is a +number between <<0>> and <> (inclusive). + +<> does not return a result. + +NOTES +<> and <> are unsafe for multi-threaded applications. +<> is thread-safe and should be used instead. + + +PORTABILITY +<> 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. + +<> requires no supporting OS subroutines. +*/ + +#ifndef _REENT_ONLY + +#include +#include + +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 */ diff --git a/programs/develop/libraries/newlib/stdlib/rand48.c b/programs/develop/libraries/newlib/stdlib/rand48.c new file mode 100644 index 0000000000..eeb1da2456 --- /dev/null +++ b/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 + <>, <>, <>, <>, <>, <>, <>, <>, <>, <>---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 + 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 + 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 <> 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. + +<> and <> +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]. + +<> and <> +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. + +<> and <> +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. + +<>, <>, and <> +use an internal buffer to store r(n). For these functions +the initial value of r(0) = 0x1234abcd330e = 20017429951246. + +On the other hand, <>, <>, and <> +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. + +<> is used to initialize the internal buffer r(n) of +<>, <>, and <> +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. + +<> also initializes the internal buffer r(n) of +<>, <>, and <>, +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. +<> 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 <>. + +Finally, <> allows full control over the multiplicand and +addend used in <>, <>, <>, <>, +<>, and <>, +and the seed used in <>, <>, and <>. +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 <>. + +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; +} diff --git a/programs/develop/libraries/newlib/stdlib/rand_r.c b/programs/develop/libraries/newlib/stdlib/rand_r.c new file mode 100644 index 0000000000..a9ccf3992f --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/rand_r.c @@ -0,0 +1,37 @@ +#include + +/* 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); +} diff --git a/programs/develop/libraries/newlib/stdlib/seed48.c b/programs/develop/libraries/newlib/stdlib/seed48.c new file mode 100644 index 0000000000..d92cfb5e60 --- /dev/null +++ b/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 */ diff --git a/programs/develop/libraries/newlib/stdlib/srand48.c b/programs/develop/libraries/newlib/stdlib/srand48.c new file mode 100644 index 0000000000..8ffcf0bebb --- /dev/null +++ b/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 */ diff --git a/programs/develop/libraries/newlib/stdlib/strtod.c b/programs/develop/libraries/newlib/stdlib/strtod.c index 6cceb98c8e..42185ed042 100644 --- a/programs/develop/libraries/newlib/stdlib/strtod.c +++ b/programs/develop/libraries/newlib/stdlib/strtod.c @@ -300,10 +300,10 @@ _DEFUN (_strtod_r, (ptr, s00, se), s0 = s; y = z = 0; for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = 10*y + c - '0'; + if (nd < 9) + y = 10*y + c - '0'; else if (nd < 16) - z = 10*z + c - '0'; + z = 10*z + c - '0'; nd0 = nd; if (strncmp (s, _localeconv_r (ptr)->decimal_point, strlen (_localeconv_r (ptr)->decimal_point)) == 0) @@ -328,13 +328,13 @@ _DEFUN (_strtod_r, (ptr, s00, se), nf += nz; for(i = 1; i < nz; i++) if (nd++ < 9) - y *= 10; + y *= 10; else if (nd <= DBL_DIG + 1) - z *= 10; + z *= 10; if (nd++ < 9) - y = 10*y + c; + y = 10*y + c; else if (nd <= DBL_DIG + 1) - z = 10*z + c; + z = 10*z + c; nz = 0; } } diff --git a/programs/develop/libraries/newlib/stdlib/strtold.c b/programs/develop/libraries/newlib/stdlib/strtold.c new file mode 100644 index 0000000000..1e648b0b50 --- /dev/null +++ b/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 +#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 */ + diff --git a/programs/develop/libraries/newlib/stdlib/strtoll.c b/programs/develop/libraries/newlib/stdlib/strtoll.c new file mode 100644 index 0000000000..b184f1eaa4 --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/strtoll.c @@ -0,0 +1,138 @@ +/* +FUNCTION + <>---string to long long + +INDEX + strtoll +INDEX + _strtoll_r + +ANSI_SYNOPSIS + #include + 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 + 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 <> converts the string <<*<[s]>>> to +a <>. 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 <> 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 <>--<> (or, +equivalently, <>--<>) 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, +<> 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 <> 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 <>. + +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 <>). + +The alternate function <<_strtoll_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +<> returns the converted value, if any. If no conversion was +made, 0 is returned. + +<> returns <> or <> if the magnitude of +the converted value is too large, and sets <> to <>. + +PORTABILITY +<> 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 +#include +#include +#include +#include + +#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 diff --git a/programs/develop/libraries/newlib/stdlib/strtoll_r.c b/programs/develop/libraries/newlib/stdlib/strtoll_r.c new file mode 100644 index 0000000000..5ee2f5031d --- /dev/null +++ b/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 +#include +#include +#include +#include + +/* + * 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__ */ diff --git a/programs/develop/libraries/newlib/stdlib/strtoull.c b/programs/develop/libraries/newlib/stdlib/strtoull.c new file mode 100644 index 0000000000..d95fc57b6f --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/strtoull.c @@ -0,0 +1,139 @@ +/* +FUNCTION + <>---string to unsigned long long + +INDEX + strtoull +INDEX + _strtoull_r + +ANSI_SYNOPSIS + #include + 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 + 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 <> converts the string <<*<[s]>>> to +an <>. 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 <>--<> (or <>--<>) 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, +<> 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 <> 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 <>. + +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 <>). + +The alternate function <<_strtoull_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + + +RETURNS +<> returns the converted value, if any. If no conversion was +made, <<0>> is returned. + +<> returns <> if the magnitude of the converted +value is too large, and sets <> to <>. + +PORTABILITY +<> is ANSI. + +<> 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 +#include +#include +#include +#include + +#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 diff --git a/programs/develop/libraries/newlib/stdlib/strtoull_r.c b/programs/develop/libraries/newlib/stdlib/strtoull_r.c new file mode 100644 index 0000000000..6fcc976555 --- /dev/null +++ b/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 +#include +#include +#include +#include + +/* + * 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__ */ diff --git a/programs/develop/libraries/newlib/stdlib/system.c b/programs/develop/libraries/newlib/stdlib/system.c new file mode 100644 index 0000000000..5d26fbfa80 --- /dev/null +++ b/programs/develop/libraries/newlib/stdlib/system.c @@ -0,0 +1,85 @@ +/* +FUNCTION +<>---execute command string + +INDEX + system +INDEX + _system_r + +ANSI_SYNOPSIS + #include + int system(char *<[s]>); + + int _system_r(void *<[reent]>, char *<[s]>); + +TRAD_SYNOPSIS + #include + int system(<[s]>) + char *<[s]>; + + int _system_r(<[reent]>, <[s]>) + char *<[reent]>; + char *<[s]>; + +DESCRIPTION + +Use <> to pass a command string <<*<[s]>>> to <> on +your system, and wait for it to finish executing. + +Use ``<>'' to test whether your system has <> +available. + +The alternate function <<_system_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +<> returns a non-zero value if <> is available, and +<<0>> if it is not. + +With a command argument, the result of <> is the exit status +returned by <>. + +PORTABILITY +ANSI C requires <>, but leaves the nature and effects of a +command processor undefined. ANSI C does, however, specify that +<> return zero or nonzero to report on the existence of +a command processor. + +POSIX.2 requires <>, and requires that it invoke a <>. +Where <> is found is left unspecified. + +Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>, +<<_wait_r>>. +*/ + +#include <_ansi.h> +#include +#include +#include +#include +#include <_syslist.h> +#include + + +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 diff --git a/programs/develop/libraries/newlib/string/strcasestr.c b/programs/develop/libraries/newlib/string/strcasestr.c new file mode 100644 index 0000000000..38c22903ef --- /dev/null +++ b/programs/develop/libraries/newlib/string/strcasestr.c @@ -0,0 +1,147 @@ +/* +FUNCTION + <>---case-insensitive character string search + +INDEX + strcasestr + +ANSI_SYNOPSIS + #include + char *strcasestr(const char *<[s]>, const char *<[find]>); + +TRAD_SYNOPSIS + #include + int strcasecmp(<[s]>, <[find]>) + char *<[s]>; + char *<[find]>; + +DESCRIPTION + <> searchs the string <[s]> for + the first occurrence of the sequence <[find]>. <> + is identical to <> except the search is + case-insensitive. + +RETURNS + + A pointer to the first case-insensitive occurrence of the sequence + <[find]> or <> if no match was found. + +PORTABILITY +<> is in the Berkeley Software Distribution. + +<> 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 + +#include +#include + +#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 */ +} diff --git a/programs/develop/libraries/newlib/string/strcat.c b/programs/develop/libraries/newlib/string/strcat.c new file mode 100644 index 0000000000..ba8ee394ef --- /dev/null +++ b/programs/develop/libraries/newlib/string/strcat.c @@ -0,0 +1,104 @@ +/* +FUNCTION + <>---concatenate strings + +INDEX + strcat + +ANSI_SYNOPSIS + #include + char *strcat(char *<[dst]>, const char *<[src]>); + +TRAD_SYNOPSIS + #include + char *strcat(<[dst]>, <[src]>) + char *<[dst]>; + char *<[src]>; + +DESCRIPTION + <> 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 +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strcat ansi pure +*/ + +#include +#include + +/* 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 */ +} diff --git a/programs/develop/libraries/newlib/string/strcoll.c b/programs/develop/libraries/newlib/string/strcoll.c new file mode 100644 index 0000000000..5488612040 --- /dev/null +++ b/programs/develop/libraries/newlib/string/strcoll.c @@ -0,0 +1,48 @@ +/* +FUNCTION + <>---locale-specific character string compare + +INDEX + strcoll + +ANSI_SYNOPSIS + #include + int strcoll(const char *<[stra]>, const char * <[strb]>); + +TRAD_SYNOPSIS + #include + int strcoll(<[stra]>, <[strb]>) + char *<[stra]>; + char *<[strb]>; + +DESCRIPTION + <> compares the string pointed to by <[stra]> to + the string pointed to by <[strb]>, using an interpretation + appropriate to the current <> state. + +RETURNS + If the first string is greater than the second string, + <> returns a number greater than zero. If the two + strings are equivalent, <> returns zero. If the first + string is less than the second string, <> returns a + number less than zero. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strcoll ansi pure +*/ + +#include + +int +_DEFUN (strcoll, (a, b), + _CONST char *a _AND + _CONST char *b) + +{ + return strcmp (a, b); +} diff --git a/programs/develop/libraries/newlib/string/strncat.c b/programs/develop/libraries/newlib/string/strncat.c new file mode 100644 index 0000000000..c61f4d5139 --- /dev/null +++ b/programs/develop/libraries/newlib/string/strncat.c @@ -0,0 +1,114 @@ +/* +FUNCTION + <>---concatenate strings + +INDEX + strncat + +ANSI_SYNOPSIS + #include + char *strncat(char *<[dst]>, const char *<[src]>, size_t <[length]>); + +TRAD_SYNOPSIS + #include + char *strncat(<[dst]>, <[src]>, <[length]>) + char *<[dst]>; + char *<[src]>; + size_t <[length]>; + +DESCRIPTION + <> 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 <>. + +RETURNS + This function returns the initial value of <[dst]> + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strncat ansi pure +*/ + +#include +#include + +/* 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 */ +} diff --git a/programs/develop/libraries/newlib/string/strndup.c b/programs/develop/libraries/newlib/string/strndup.c new file mode 100644 index 0000000000..2af9f46b40 --- /dev/null +++ b/programs/develop/libraries/newlib/string/strndup.c @@ -0,0 +1,16 @@ +#ifndef _REENT_ONLY + +#include <_ansi.h> +#include +#include +#include + +char * +_DEFUN (strndup, (str, n), + _CONST char *str _AND + size_t n) +{ + return _strndup_r (_REENT, str, n); +} + +#endif /* !_REENT_ONLY */ diff --git a/programs/develop/libraries/newlib/string/strndup_r.c b/programs/develop/libraries/newlib/string/strndup_r.c new file mode 100644 index 0000000000..a863ca2647 --- /dev/null +++ b/programs/develop/libraries/newlib/string/strndup_r.c @@ -0,0 +1,27 @@ +#include +#include +#include + +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; +} diff --git a/programs/develop/libraries/newlib/string/strpbrk.c b/programs/develop/libraries/newlib/string/strpbrk.c new file mode 100644 index 0000000000..3f6f88625b --- /dev/null +++ b/programs/develop/libraries/newlib/string/strpbrk.c @@ -0,0 +1,58 @@ +/* +FUNCTION + <>---find characters in string + +INDEX + strpbrk + +ANSI_SYNOPSIS + #include + char *strpbrk(const char *<[s1]>, const char *<[s2]>); + +TRAD_SYNOPSIS + #include + 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 + <> returns a pointer to the character found in <[s1]>, or a + null pointer if no character from <[s2]> occurs in <[s1]>. + +PORTABILITY +<> requires no supporting OS subroutines. +*/ + +#include + +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; +} diff --git a/programs/develop/libraries/newlib/string/strsep.c b/programs/develop/libraries/newlib/string/strsep.c new file mode 100644 index 0000000000..11fdcf0811 --- /dev/null +++ b/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 +#include <_ansi.h> +#include + +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); +} diff --git a/programs/develop/libraries/newlib/string/strtok.c b/programs/develop/libraries/newlib/string/strtok.c new file mode 100644 index 0000000000..1e07ea315a --- /dev/null +++ b/programs/develop/libraries/newlib/string/strtok.c @@ -0,0 +1,101 @@ +/* +FUNCTION + <>, <>, <>---get next token from a string + +INDEX + strtok + +INDEX + strtok_r + +INDEX + strsep + +ANSI_SYNOPSIS + #include + 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 + 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 <> 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 <> 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 <> 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 <> function has the same behavior as <>, except + a pointer to placeholder <<*<[lasts]>>> must be supplied by the caller. + + The <> function is similar in behavior to <>, 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 <> and <>, 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 + <>, <>, and <> all return a pointer to the + next token, or <> if no more tokens can be found. For + <>, a token may be the empty string. + +NOTES + <> is unsafe for multi-threaded applications. <> + and <> are thread-safe and should be used instead. + +PORTABILITY +<> is ANSI C. +<> is POSIX. +<> is a BSD extension. + +<>, <>, and <> require no supporting OS subroutines. + +QUICKREF + strtok ansi impure +*/ + +/* undef STRICT_ANSI so that strtok_r prototype will be defined */ +#undef __STRICT_ANSI__ +#include +#include <_ansi.h> +#include + +#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 diff --git a/programs/develop/libraries/newlib/string/strtok_r.c b/programs/develop/libraries/newlib/string/strtok_r.c new file mode 100644 index 0000000000..82af55d772 --- /dev/null +++ b/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 + +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); +} diff --git a/programs/develop/libraries/newlib/string/strupr.c b/programs/develop/libraries/newlib/string/strupr.c new file mode 100644 index 0000000000..48679c6f35 --- /dev/null +++ b/programs/develop/libraries/newlib/string/strupr.c @@ -0,0 +1,46 @@ +/* +FUNCTION + <>---force string to uppercase + +INDEX + strupr + +ANSI_SYNOPSIS + #include + char *strupr(char *<[a]>); + +TRAD_SYNOPSIS + #include + char *strupr(<[a]>) + char *<[a]>; + +DESCRIPTION + <> converts each character in the string at <[a]> to + uppercase. + +RETURNS + <> returns its argument, <[a]>. + +PORTABILITY +<> is not widely portable. + +<> requires no supporting OS subroutines. + +QUICKREF + strupr +*/ + +#include +#include + +char * +_DEFUN (strupr, (s), + char *s) +{ + unsigned char *ucs = (unsigned char *) s; + for ( ; *ucs != '\0'; ucs++) + { + *ucs = toupper(*ucs); + } + return s; +} diff --git a/programs/develop/libraries/newlib/sys/create.c b/programs/develop/libraries/newlib/sys/create.c new file mode 100644 index 0000000000..b7d0149613 --- /dev/null +++ b/programs/develop/libraries/newlib/sys/create.c @@ -0,0 +1,25 @@ + +#include +#include + +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; +}; diff --git a/programs/develop/libraries/newlib/sys/delete.c b/programs/develop/libraries/newlib/sys/delete.c new file mode 100644 index 0000000000..92f18ff8bf --- /dev/null +++ b/programs/develop/libraries/newlib/sys/delete.c @@ -0,0 +1,26 @@ + +#include +#include + +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; +}; + diff --git a/programs/develop/libraries/newlib/sys/finfo.c b/programs/develop/libraries/newlib/sys/finfo.c new file mode 100644 index 0000000000..c114554fb7 --- /dev/null +++ b/programs/develop/libraries/newlib/sys/finfo.c @@ -0,0 +1,26 @@ + +#include +#include + +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; +}; + diff --git a/programs/develop/libraries/newlib/sys/fload.c b/programs/develop/libraries/newlib/sys/fload.c new file mode 100644 index 0000000000..30253cfa65 --- /dev/null +++ b/programs/develop/libraries/newlib/sys/fload.c @@ -0,0 +1,37 @@ + +#include +#include +#include + +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; +}; + + diff --git a/programs/develop/libraries/newlib/sys/fsize.c b/programs/develop/libraries/newlib/sys/fsize.c new file mode 100644 index 0000000000..86f0bc9ae6 --- /dev/null +++ b/programs/develop/libraries/newlib/sys/fsize.c @@ -0,0 +1,26 @@ + +#include +#include + + +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; +}; + diff --git a/programs/develop/libraries/newlib/sys/read.c b/programs/develop/libraries/newlib/sys/read.c new file mode 100644 index 0000000000..1840c7154e --- /dev/null +++ b/programs/develop/libraries/newlib/sys/read.c @@ -0,0 +1,31 @@ + +#include +#include + +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; +}; + diff --git a/programs/develop/libraries/newlib/sys/write.c b/programs/develop/libraries/newlib/sys/write.c new file mode 100644 index 0000000000..80afc7c7bb --- /dev/null +++ b/programs/develop/libraries/newlib/sys/write.c @@ -0,0 +1,29 @@ + +#include +#include + +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; +}; diff --git a/programs/develop/libraries/newlib/time/asctime.c b/programs/develop/libraries/newlib/time/asctime.c new file mode 100644 index 0000000000..63b9de0d3a --- /dev/null +++ b/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 +<>---format time as string + +INDEX + asctime +INDEX + _asctime_r + +ANSI_SYNOPSIS + #include + char *asctime(const struct tm *<[clock]>); + char *_asctime_r(const struct tm *<[clock]>, char *<[buf]>); + +TRAD_SYNOPSIS + #include + 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 <> +overwrites the string generated by previous calls. + +RETURNS +A pointer to the string containing a formatted timestamp. + +PORTABILITY +ANSI C requires <>. + +<> requires no supporting OS subroutines. +*/ + +#include +#include <_ansi.h> +#include + +#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 diff --git a/programs/develop/libraries/newlib/time/asctime_r.c b/programs/develop/libraries/newlib/time/asctime_r.c new file mode 100644 index 0000000000..11fe5cf728 --- /dev/null +++ b/programs/develop/libraries/newlib/time/asctime_r.c @@ -0,0 +1,27 @@ +/* + * asctime_r.c + */ + +#include +#include + +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; +} diff --git a/programs/develop/libraries/newlib/time/clock.c b/programs/develop/libraries/newlib/time/clock.c new file mode 100644 index 0000000000..5c29ce2668 --- /dev/null +++ b/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 +<>---cumulative processor time + +INDEX + clock + +ANSI_SYNOPSIS + #include + clock_t clock(void); + +TRAD_SYNOPSIS + #include + 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 <>. + +RETURNS +The amount of processor time used so far by your program, in units +defined by the machine-dependent macro <>. If no +measurement is available, the result is (clock_t)<<-1>>. + +PORTABILITY +ANSI C requires <> and <>. + +Supporting OS subroutine required: <>. +*/ + +#include +#include +#include + + +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 */ diff --git a/programs/develop/libraries/newlib/time/ctime.c b/programs/develop/libraries/newlib/time/ctime.c new file mode 100644 index 0000000000..5675f10a19 --- /dev/null +++ b/programs/develop/libraries/newlib/time/ctime.c @@ -0,0 +1,55 @@ +/* + * ctime.c + * Original Author: G. Haley + */ + +/* +FUNCTION +<>---convert time to local and format as string + +INDEX + ctime +INDEX + ctime_r + +ANSI_SYNOPSIS + #include + char *ctime(const time_t *<[clock]>); + char *ctime_r(const time_t *<[clock]>, char *<[buf]>); + +TRAD_SYNOPSIS + #include + 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 <>) +and format it into a string of the form +. Wed Jun 15 11:38:07 1988\n\0 +(like <>). + +RETURNS +A pointer to the string containing a formatted timestamp. + +PORTABILITY +ANSI C requires <>. + +<> requires no supporting OS subroutines. +*/ + +#include + +#ifndef _REENT_ONLY + +char * +_DEFUN (ctime, (tim_p), + _CONST time_t * tim_p) +{ + return asctime (localtime (tim_p)); +} + +#endif diff --git a/programs/develop/libraries/newlib/time/ctime_r.c b/programs/develop/libraries/newlib/time/ctime_r.c new file mode 100644 index 0000000000..984aa78c4c --- /dev/null +++ b/programs/develop/libraries/newlib/time/ctime_r.c @@ -0,0 +1,15 @@ +/* + * ctime_r.c + */ + +#include + +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); +} diff --git a/programs/develop/libraries/newlib/time/difftime.c b/programs/develop/libraries/newlib/time/difftime.c new file mode 100644 index 0000000000..8154f5f57a --- /dev/null +++ b/programs/develop/libraries/newlib/time/difftime.c @@ -0,0 +1,44 @@ +/* + * difftime.c + * Original Author: G. Haley + */ + +/* +FUNCTION +<>---subtract two times + +INDEX + difftime + +ANSI_SYNOPSIS + #include + double difftime(time_t <[tim1]>, time_t <[tim2]>); + +TRAD_SYNOPSIS + #include + 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 <>. + +PORTABILITY +ANSI C requires <>, and defines its result to be in seconds +in all implementations. + +<> requires no supporting OS subroutines. +*/ + +#include + +double +_DEFUN (difftime, (tim1, tim2), + time_t tim1 _AND + time_t tim2) +{ + return (double)(tim1 - tim2); +} diff --git a/programs/develop/libraries/newlib/time/gettzinfo.c b/programs/develop/libraries/newlib/time/gettzinfo.c new file mode 100644 index 0000000000..d0a3ffe9fd --- /dev/null +++ b/programs/develop/libraries/newlib/time/gettzinfo.c @@ -0,0 +1,15 @@ +#include +#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; +} diff --git a/programs/develop/libraries/newlib/time/gmtime.c b/programs/develop/libraries/newlib/time/gmtime.c new file mode 100644 index 0000000000..7d389298d7 --- /dev/null +++ b/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 +<>---convert time to UTC traditional form + +INDEX + gmtime +INDEX + gmtime_r + +ANSI_SYNOPSIS + #include + struct tm *gmtime(const time_t *<[clock]>); + struct tm *gmtime_r(const time_t *<[clock]>, struct tm *<[res]>); + +TRAD_SYNOPSIS + #include + struct tm *gmtime(<[clock]>) + const time_t *<[clock]>; + struct tm *gmtime_r(<[clock]>, <[res]>) + const time_t *<[clock]>; + struct tm *<[res]>; + +DESCRIPTION +<> 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 <> +representation. + +<> constructs the traditional time representation in static +storage; each call to <> or <> will overwrite the +information generated by previous calls to either function. + +RETURNS +A pointer to the traditional time representation (<>). + +PORTABILITY +ANSI C requires <>. + +<> requires no supporting OS subroutines. +*/ + +#include +#include + +#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 diff --git a/programs/develop/libraries/newlib/time/gmtime_r.c b/programs/develop/libraries/newlib/time/gmtime_r.c new file mode 100644 index 0000000000..8910827aad --- /dev/null +++ b/programs/develop/libraries/newlib/time/gmtime_r.c @@ -0,0 +1,14 @@ +/* + * gmtime_r.c + */ + +#include +#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)); +} diff --git a/programs/develop/libraries/newlib/time/lcltime.c b/programs/develop/libraries/newlib/time/lcltime.c new file mode 100644 index 0000000000..8a155e2bd0 --- /dev/null +++ b/programs/develop/libraries/newlib/time/lcltime.c @@ -0,0 +1,60 @@ +/* + * localtime.c + */ + +/* +FUNCTION +<>---convert time to local representation + +INDEX + localtime +INDEX + localtime_r + +ANSI_SYNOPSIS + #include + struct tm *localtime(time_t *<[clock]>); + struct tm *localtime_r(time_t *<[clock]>, struct tm *<[res]>); + +TRAD_SYNOPSIS + #include + struct tm *localtime(<[clock]>) + time_t *<[clock]>; + struct tm *localtime(<[clock]>, <[res]>) + time_t *<[clock]>; + struct tm *<[res]>; + +DESCRIPTION +<> converts the time at <[clock]> into local time, then +converts its representation from the arithmetic representation to the +traditional representation defined by <>. + +<> constructs the traditional time representation in static +storage; each call to <> or <> will overwrite the +information generated by previous calls to either function. + +<> is the inverse of <>. + +RETURNS +A pointer to the traditional time representation (<>). + +PORTABILITY +ANSI C requires <>. + +<> requires no supporting OS subroutines. +*/ + +#include +#include + +#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 diff --git a/programs/develop/libraries/newlib/time/lcltime_r.c b/programs/develop/libraries/newlib/time/lcltime_r.c new file mode 100644 index 0000000000..7dd42f0779 --- /dev/null +++ b/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 +#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); +} diff --git a/programs/develop/libraries/newlib/time/local.h b/programs/develop/libraries/newlib/time/local.h new file mode 100644 index 0000000000..15928b4465 --- /dev/null +++ b/programs/develop/libraries/newlib/time/local.h @@ -0,0 +1,36 @@ +/* local header used by libc/time routines */ +#include <_ansi.h> +#include + +#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)); + diff --git a/programs/develop/libraries/newlib/time/mktime.c b/programs/develop/libraries/newlib/time/mktime.c new file mode 100644 index 0000000000..a956207a31 --- /dev/null +++ b/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 +<>---convert time to arithmetic representation + +INDEX + mktime + +ANSI_SYNOPSIS + #include + time_t mktime(struct tm *<[timp]>); + +TRAD_SYNOPSIS + #include + time_t mktime(<[timp]>) + struct tm *<[timp]>; + +DESCRIPTION +<> assumes the time at <[timp]> is a local time, and converts +its representation from the traditional representation defined by +<> into a representation suitable for arithmetic. + +<> is the inverse of <>. + +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 <> value. + +PORTABILITY +ANSI C requires <>. + +<> requires no supporting OS subroutines. +*/ + +#include +#include +#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; +} diff --git a/programs/develop/libraries/newlib/time/mktm_r.c b/programs/develop/libraries/newlib/time/mktm_r.c new file mode 100644 index 0000000000..9f42643543 --- /dev/null +++ b/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 + * Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov + * + * 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 +#include +#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; +} + diff --git a/programs/develop/libraries/newlib/time/strftime.c b/programs/develop/libraries/newlib/time/strftime.c new file mode 100644 index 0000000000..e4954a63a1 --- /dev/null +++ b/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 +<>---convert date and time to a formatted string + +INDEX + strftime + +ANSI_SYNOPSIS + #include + size_t strftime(char *<[s]>, size_t <[maxsize]>, + const char *<[format]>, const struct tm *<[timp]>); + +TRAD_SYNOPSIS + #include + size_t strftime(<[s]>, <[maxsize]>, <[format]>, <[timp]>) + char *<[s]>; + size_t <[maxsize]>; + char *<[format]>; + struct tm *<[timp]>; + +DESCRIPTION +<> converts a <> 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 `<>', `<>', `<>', +`<>', `<>', `<>', `<>'. [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 `<>', `<>', +`<>', `<>', `<>', `<>', `<>', +`<>', `<>', `<>', `<>', +`<>'. [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<> +In some locales, the E modifier selects alternative representations of +certain modifiers <>. In newlib, it is ignored, and treated as %<>. + +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<> +In some locales, the O modifier selects alternative digit characters +for certain modifiers <>. In newlib, it is ignored, and treated as %<>. + +o %p +Either `<>' or `<>' 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 <>, but does not specify the contents of +<<*<[s]>>> when the formatted string would require more than +<[maxsize]> characters. Unrecognized specifiers and fields of +<> 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 <> being NULL, nor overlapping +<> and <>. + +<> requires no supporting OS subroutines. + +BUGS +<> ignores the LC_TIME category of the current locale, hard-coding +the "C" locale settings. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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; +} + + diff --git a/programs/develop/libraries/newlib/time/time.c b/programs/develop/libraries/newlib/time/time.c new file mode 100644 index 0000000000..58f06324f6 --- /dev/null +++ b/programs/develop/libraries/newlib/time/time.c @@ -0,0 +1,53 @@ +/* +FUNCTION +<