diff --git a/liba/Makefile b/liba/Makefile index 2e4a5653b..32d9116d9 100644 --- a/liba/Makefile +++ b/liba/Makefile @@ -4,7 +4,11 @@ liba/src/external/sqlite/mem5.o: CFLAGS += -w objs += $(addprefix liba/src/, \ assert.o \ + bzero.o \ + ctype.o \ errno.o \ + fpclassify.o \ + fpclassifyf.o \ ieee754.o \ isnand.o \ isnanf.o \ @@ -15,6 +19,7 @@ objs += $(addprefix liba/src/, \ memcpy.o \ memmove.o \ memset.o \ + nearbyintf.o \ strcmp.o \ strchr.o \ strlcpy.o \ @@ -27,8 +32,10 @@ objs += $(addprefix liba/src/external/openbsd/, \ e_acoshf.o \ e_asinf.o \ e_atanhf.o \ + e_atan2f.o \ e_coshf.o \ e_expf.o \ + e_fmodf.o \ e_lgammaf_r.o \ e_log10f.o \ e_logf.o \ @@ -85,6 +92,7 @@ objs += $(addprefix liba/src/external/openbsd/, \ s_fabs.o \ s_floor.o \ s_log1p.o \ + s_nan.o \ s_round.o \ s_scalbn.o \ s_sin.o \ diff --git a/liba/include/ctype.h b/liba/include/ctype.h new file mode 100644 index 000000000..a108cf3e0 --- /dev/null +++ b/liba/include/ctype.h @@ -0,0 +1,8 @@ +#ifndef LIBA_CTYPE_H +#define LIBA_CTYPE_H + +int isupper(int c); +int isxdigit(int c); +int isdigit(int c); + +#endif diff --git a/liba/include/math.h b/liba/include/math.h index a9f7ec0e5..a8d1efbd0 100644 --- a/liba/include/math.h +++ b/liba/include/math.h @@ -11,6 +11,12 @@ LIBA_BEGIN_DECLS #define M_E 2.71828182845904523536028747135266250 #define M_PI 3.14159265358979323846264338327950288 +#define FP_INFINITE 0x01 +#define FP_NAN 0x02 +#define FP_NORMAL 0x04 +#define FP_SUBNORMAL 0x08 +#define FP_ZERO 0x10 + /* The C99 standard requires isinf and isnan to be defined as macros that can * handle arbitrary precision float numbers. The names of the functions called * by those macros (depending on the argument size) are not standardized though. @@ -23,12 +29,16 @@ int isinfd(double d); int isnanf(float x); int isnand(double x); #define isnan(x) (sizeof(x) == sizeof(float) ? isnanf(x) : isnand(x)) +int __fpclassifyf(float x); +int __fpclassify(double x); +#define fpclassify(x) ((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) : __fpclassify(x)) float acosf(float x); float acoshf(float x); float asinf(float x); float asinhf(float x); float atanf(float x); +float atan2f(float y, float x); float atanhf(float x); float ceilf(float x); float copysignf(float x, float y); @@ -38,11 +48,14 @@ float expf(float x); float expm1f(float x); float fabsf(float x); float floorf(float x); +float fmodf(float x, float y); float lgammaf(float x); float lgammaf_r(float x, int *signgamp); float log1pf(float x); float log10f(float x); float logf(float x); +float nanf(const char *s); +float nearbyintf(float x); float powf(float x, float y); float roundf(float x); float scalbnf(float x, int n); diff --git a/liba/include/strings.h b/liba/include/strings.h new file mode 100644 index 000000000..0245a2886 --- /dev/null +++ b/liba/include/strings.h @@ -0,0 +1,8 @@ +#ifndef LIBA_STRINGS_H +#define LIBA_STRINGS_H + +#include + +void bzero(void * s, size_t n); + +#endif diff --git a/liba/src/bzero.c b/liba/src/bzero.c new file mode 100644 index 000000000..588c3cab7 --- /dev/null +++ b/liba/src/bzero.c @@ -0,0 +1,9 @@ +#include + +void bzero(void * s, size_t n) { + char *t = s; + while (n != 0) { + *t++ = 0; + n--; + } +} diff --git a/liba/src/ctype.c b/liba/src/ctype.c new file mode 100644 index 000000000..42ee7c082 --- /dev/null +++ b/liba/src/ctype.c @@ -0,0 +1,13 @@ +#include + +int isupper(int c) { + return (c >= 'A' && c <= 'Z'); +} + +int isxdigit(int c) { + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} + +int isdigit(int c) { + return (c >= '0' && c <= '9'); +} diff --git a/liba/src/external/openbsd/e_atan2f.c b/liba/src/external/openbsd/e_atan2f.c new file mode 100644 index 000000000..155a36cab --- /dev/null +++ b/liba/src/external/openbsd/e_atan2f.c @@ -0,0 +1,93 @@ +/* e_atan2f.c -- float version of e_atan2.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 "math.h" +#include "math_private.h" + +static const float +tiny = 1.0e-30, +zero = 0.0, +pi_o_4 = 7.8539818525e-01, /* 0x3f490fdb */ +pi_o_2 = 1.5707963705e+00, /* 0x3fc90fdb */ +pi = 3.1415925026e+00, /* 0x40490fda */ +pi_lo = 1.5099578832e-07; /* 0x34222168 */ + +float +atan2f(float y, float x) +{ + float z; + int32_t k,m,hx,hy,ix,iy; + + GET_FLOAT_WORD(hx,x); + ix = hx&0x7fffffff; + GET_FLOAT_WORD(hy,y); + iy = hy&0x7fffffff; + if((ix>0x7f800000)|| + (iy>0x7f800000)) /* x or y is NaN */ + return x+y; + if(hx==0x3f800000) return atanf(y); /* x=1.0 */ + m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ + + /* when y = 0 */ + if(iy==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==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* when x is INF */ + if(ix==0x7f800000) { + if(iy==0x7f800000) { + 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 (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ + case 3: return (float)-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==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* compute y/x */ + k = (iy-ix)>>23; + if(k > 60) z=pi_o_2+(float)0.5*pi_lo; /* |y/x| > 2**60 */ + else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */ + else z=atanf(fabsf(y/x)); /* safe to do y/x */ + switch (m) { + case 0: return z ; /* atan(+,+) */ + case 1: { + u_int32_t zh; + GET_FLOAT_WORD(zh,z); + SET_FLOAT_WORD(z,zh ^ 0x80000000); + } + return z ; /* atan(-,+) */ + case 2: return pi-(z-pi_lo);/* atan(+,-) */ + default: /* case 3 */ + return (z-pi_lo)-pi;/* atan(-,-) */ + } +} diff --git a/liba/src/external/openbsd/e_fmodf.c b/liba/src/external/openbsd/e_fmodf.c new file mode 100644 index 000000000..cca2f6f63 --- /dev/null +++ b/liba/src/external/openbsd/e_fmodf.c @@ -0,0 +1,101 @@ +/* e_fmodf.c -- float version of e_fmod.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. + * ==================================================== + */ + +/* + * fmodf(x,y) + * Return x mod y in exact arithmetic + * Method: shift and subtract + */ + +#include "math.h" +#include "math_private.h" + +static const float one = 1.0, Zero[] = {0.0, -0.0,}; + +float +fmodf(float x, float y) +{ + int32_t n,hx,hy,hz,ix,iy,sx,i; + + GET_FLOAT_WORD(hx,x); + GET_FLOAT_WORD(hy,y); + sx = hx&0x80000000; /* sign of x */ + hx ^=sx; /* |x| */ + hy &= 0x7fffffff; /* |y| */ + + /* purge off exception values */ + if(hy==0||(hx>=0x7f800000)|| /* y=0,or x not finite */ + (hy>0x7f800000)) /* or y is NaN */ + return (x*y)/(x*y); + if(hx>31]; /* |x|=|y| return x*0*/ + + /* determine ix = ilogb(x) */ + if(hx<0x00800000) { /* subnormal x */ + for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1; + } else ix = (hx>>23)-127; + + /* determine iy = ilogb(y) */ + if(hy<0x00800000) { /* subnormal y */ + for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1; + } else iy = (hy>>23)-127; + + /* set up {hx,lx}, {hy,ly} and align y to x */ + if(ix >= -126) + hx = 0x00800000|(0x007fffff&hx); + else { /* subnormal x, shift x to normal */ + n = -126-ix; + hx = hx<= -126) + hy = 0x00800000|(0x007fffff&hy); + else { /* subnormal y, shift y to normal */ + n = -126-iy; + hy = hy<>31]; + hx = hz+hz; + } + } + hz=hx-hy; + if(hz>=0) {hx=hz;} + + /* convert back to floating value and restore the sign */ + if(hx==0) /* return sign(x)*0 */ + return Zero[(u_int32_t)sx>>31]; + while(hx<0x00800000) { /* normalize x */ + hx = hx+hx; + iy -= 1; + } + if(iy>= -126) { /* normalize output */ + hx = ((hx-0x00800000)|((iy+127)<<23)); + SET_FLOAT_WORD(x,hx|sx); + } else { /* subnormal output */ + n = -126 - iy; + hx >>= n; + SET_FLOAT_WORD(x,hx|sx); + x *= one; /* create necessary signal */ + } + return x; /* exact output */ +} diff --git a/liba/src/external/openbsd/include/endian.h b/liba/src/external/openbsd/include/endian.h new file mode 100644 index 000000000..e69de29bb diff --git a/liba/src/external/openbsd/s_nan.c b/liba/src/external/openbsd/s_nan.c new file mode 100644 index 000000000..33628c823 --- /dev/null +++ b/liba/src/external/openbsd/s_nan.c @@ -0,0 +1,127 @@ +/* $OpenBSD: s_nan.c,v 1.13 2014/07/21 01:51:11 guenther Exp $ */ +/*- + * Copyright (c) 2007 David Schultz + * 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. + * + * THIS SOFTWARE IS PROVIDED BY 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 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. + * + * $FreeBSD: src/lib/msun/src/s_nan.c,v 1.2 2007/12/18 23:46:32 das Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "math_private.h" + +/* + * OpenBSD's ctype doesn't have digittoint, so we define it here. + */ +static int +_digittoint(int c) +{ + if (!isxdigit(c)) + return 0; + + if (isdigit(c)) + return c - '0'; + else + return isupper(c) ? c - 'A' + 10 : c - 'a' + 10; +} + +/* + * Scan a string of hexadecimal digits (the format nan(3) expects) and + * make a bit array (using the local endianness). We stop when we + * encounter an invalid character, NUL, etc. If we overflow, we do + * the same as gcc's __builtin_nan(), namely, discard the high order bits. + * + * The format this routine accepts needs to be compatible with what is used + * in contrib/gdtoa/hexnan.c (for strtod/scanf) and what is used in + * __builtin_nan(). In fact, we're only 100% compatible for strings we + * consider valid, so we might be violating the C standard. But it's + * impossible to use nan(3) portably anyway, so this seems good enough. + */ +void +_scan_nan(uint32_t *words, int num_words, const char *s) +{ + int si; /* index into s */ + int bitpos; /* index into words (in bits) */ + + bzero(words, num_words * sizeof(uint32_t)); + + /* Allow a leading '0x'. (It's expected, but redundant.) */ + if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + s += 2; + + /* Scan forwards in the string, looking for the end of the sequence. */ + for (si = 0; isxdigit((unsigned char)s[si]); si++) + ; + + /* Scan backwards, filling in the bits in words[] as we go. */ +#if BYTE_ORDER == LITTLE_ENDIAN + for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) { +#else + for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) { +#endif + if (--si < 0) + break; + words[bitpos / 32] |= _digittoint((unsigned char)s[si]) << (bitpos % 32); + } +} + +double +nan(const char *s) +{ + union { + double d; + uint32_t bits[2]; + } u; + + _scan_nan(u.bits, 2, s); +#if BYTE_ORDER == LITTLE_ENDIAN + u.bits[1] |= 0x7ff80000; +#else + u.bits[0] |= 0x7ff80000; +#endif + return (u.d); +} + +float +nanf(const char *s) +{ + union { + float f; + uint32_t bits[1]; + } u; + + _scan_nan(u.bits, 1, s); + u.bits[0] |= 0x7fc00000; + return (u.f); +} + +#if LDBL_MANT_DIG == DBL_MANT_DIG +__strong_alias(nanl, nan); +#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */ diff --git a/liba/src/fpclassify.c b/liba/src/fpclassify.c new file mode 100644 index 000000000..d1fe0276b --- /dev/null +++ b/liba/src/fpclassify.c @@ -0,0 +1,20 @@ +#include +#include + +int __fpclassify(double x) { + if (ieee754exp64(x) == 0) { + if (ieee754man64(x) == 0x0) { + return FP_ZERO; + } else { + return FP_SUBNORMAL; + } + } + if (ieee754exp64(x) == 0x7FF) { + if (ieee754man64(x) == 0) { + return FP_INFINITE; + } else { + return FP_NAN; + } + } + return FP_NORMAL; +} diff --git a/liba/src/fpclassifyf.c b/liba/src/fpclassifyf.c new file mode 100644 index 000000000..59f780bf6 --- /dev/null +++ b/liba/src/fpclassifyf.c @@ -0,0 +1,20 @@ +#include +#include + +int __fpclassifyf(float x) { + if (ieee754exp32(x) == 0) { + if (ieee754man32(x) == 0x0) { + return FP_ZERO; + } else { + return FP_SUBNORMAL; + } + } + if (ieee754exp32(x) == 0xFF) { + if (ieee754man32(x) == 0) { + return FP_INFINITE; + } else { + return FP_NAN; + } + } + return FP_NORMAL; +} diff --git a/liba/src/nearbyintf.c b/liba/src/nearbyintf.c new file mode 100644 index 000000000..9d214291b --- /dev/null +++ b/liba/src/nearbyintf.c @@ -0,0 +1,5 @@ +#include + +float nearbyintf(float x) { + return roundf(x); +} diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index fb0c8e6d4..588a165d8 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -24,13 +24,16 @@ Q(AssertionError) Q(AttributeError) Q(BaseException) Q(BufferError) +Q(complex) Q(EOFError) Q(Ellipsis) Q(Exception) Q(FileExistsError) Q(FileNotFoundError) +Q(float) Q(FloatingPointError) Q(GeneratorExit) +Q(imag) Q(ImportError) Q(IndentationError) Q(IndexError) @@ -43,6 +46,7 @@ Q(NoneType) Q(NotImplementedError) Q(OSError) Q(OverflowError) +Q(real) Q(RuntimeError) Q(StopIteration) Q(SyntaxError) diff --git a/python/port/mpconfigport.h b/python/port/mpconfigport.h index 2f55650be..d3f0142d5 100644 --- a/python/port/mpconfigport.h +++ b/python/port/mpconfigport.h @@ -53,7 +53,7 @@ #define MICROPY_MODULE_FROZEN_MPY (0) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) // type definitions for the specific machine