diff --git a/Makefile b/Makefile index 126227e0..7f54ba33 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ include ctype/Makefile include err/Makefile include errno/Makefile include locale/Makefile -include math/Makefile +include libm/Makefile include misc/Makefile include net/Makefile include netinet/Makefile @@ -86,7 +86,8 @@ install: install-headers install-libs install-headers: $(SRCHEADERS) @echo INSTALL "$(HEADERS_INSTALL_DIR)/*"; \ mkdir -p "$(HEADERS_INSTALL_DIR)"; \ - cp -a include/* "$(HEADERS_INSTALL_DIR)"; + cp -a include/* "$(HEADERS_INSTALL_DIR)"; \ + cp -a libm/libmcs/libm/include/* "$(HEADERS_INSTALL_DIR)"; # TODO: remove `rm crt0.o` when we will be sure it's not a symlink to libphoenix.a anymore install-libs: $(LIB_TARGETS) diff --git a/include/complex.h b/include/complex.h deleted file mode 100644 index 9c7a3427..00000000 --- a/include/complex.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Phoenix-RTOS - * - * libphoenix - * - * mathematical functions on complex numbers - * - * Copyright 2023 Phoenix Systems - * Author: Gerard Swiderski - * - * This file is part of Phoenix-RTOS. - * - * %LICENSE% - */ - -#ifndef _COMPLEX_H_ -#define _COMPLEX_H_ - -/* define complex numbers specifers */ -#define complex _Complex -#define _Complex_I 1.0fi -#define I _Complex_I - - -#ifdef __cplusplus -extern "C" { -#endif - - -static inline double creal(double complex z) -{ - return (__real__(z)); -} - - -static inline float crealf(float complex z) -{ - return (__real__(z)); -} - - -static inline double cimag(double complex z) -{ - return (__imag__(z)); -} - - -static inline float cimagf(float complex z) -{ - return (__imag__(z)); -} - - -static inline double complex conj(double complex z) -{ - return __builtin_complex((__real__(z)), -(__imag__(z))); -} - - -static inline float complex conjf(float complex z) -{ - return __builtin_complex((__real__(z)), -(__imag__(z))); -} - - -double cabs(double complex); - - -float cabsf(float complex); - - -double carg(double complex); - - -float cargf(float complex); - - -double complex cexp(double complex); - - -float complex cexpf(float complex); - - -/* - * TODO: functions not yet implemented - */ - -long double cabsl(long double complex); - - -double complex cacos(double complex); - - -float complex cacosf(float complex); - - -double complex cacosh(double complex); - - -float complex cacoshf(float complex); - - -long double complex cacoshl(long double complex); - - -long double complex cacosl(long double complex); - - -long double cargl(long double complex); - - -double complex casin(double complex); - - -float complex casinf(float complex); - - -double complex casinh(double complex); - - -float complex casinhf(float complex); - - -long double complex casinhl(long double complex); - - -long double complex casinl(long double complex); - - -double complex catan(double complex); - - -float complex catanf(float complex); - - -double complex catanh(double complex); - - -float complex catanhf(float complex); - - -long double complex catanhl(long double complex); - - -long double complex catanl(long double complex); - - -double complex ccos(double complex); - - -float complex ccosf(float complex); - - -double complex ccosh(double complex); - - -float complex ccoshf(float complex); - - -long double complex ccoshl(long double complex); - - -long double complex ccosl(long double complex); - - -long double complex cexpl(long double complex); - - -long double cimagl(long double complex); - - -double complex clog(double complex); - - -float complex clogf(float complex); - - -long double complex clogl(long double complex); - - -long double complex conjl(long double complex); - - -double complex cpow(double complex, double complex); - - -float complex cpowf(float complex, float complex); - - -long double complex cpowl(long double complex, long double complex); - - -double complex cproj(double complex); - - -float complex cprojf(float complex); - - -long double complex cprojl(long double complex); - - -long double creall(long double complex); - - -double complex csin(double complex); - - -float complex csinf(float complex); - - -double complex csinh(double complex); - - -float complex csinhf(float complex); - - -long double complex csinhl(long double complex); - - -long double complex csinl(long double complex); - - -double complex csqrt(double complex); - - -float complex csqrtf(float complex); - - -long double complex csqrtl(long double complex); - - -double complex ctan(double complex); - - -float complex ctanf(float complex); - - -double complex ctanh(double complex); - - -float complex ctanhf(float complex); - - -long double complex ctanhl(long double complex); - - -long double complex ctanl(long double complex); - - -#ifdef __cplusplus -} -#endif - - -#endif /* end of _COMPLEX_H_ */ diff --git a/include/math.h b/include/math.h deleted file mode 100644 index 3353192c..00000000 --- a/include/math.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Phoenix-RTOS - * - * libphoenix - * - * math.h - * - * Copyright 2017, 2022 Phoenix Systems - * Author: Aleksander Kaminski, Damian Loewnau - * - * This file is part of Phoenix-RTOS. - * - * %LICENSE% - */ - -#ifndef _LIBPHOENIX_MATH_H_ -#define _LIBPHOENIX_MATH_H_ - - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -#define MATH_ERRNO 1 -#define MATH_ERREXCEPT 2 -#define math_errhandling (MATH_ERRNO) - -#define FP_NAN 0 -#define FP_INFINITE 1 -#define FP_ZERO 2 -#define FP_SUBNORMAL 3 -#define FP_NORMAL 4 - - -#define fpclassify(x) __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x) -#define isfinite(x) __builtin_isfinite(x) -#define isgreater(x, y) __builtin_isgreater(x, y) -#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) -#define isinf(x) __builtin_isinf(x) -#define isless(x, y) __builtin_isless(x, y) -#define islessequal(x, y) __builtin_islessequal(x, y) -#define islessgreater(x, y) __builtin_islessgreater(x, y) -#define isnan(x) __builtin_isnan(x) -#define signbit(x) __builtin_signbit(x) -#define isnormal(x) __builtin_isnormal(x) -#define isunordered(x, y) __builtin_isunordered(x, y) - -#define HUGE_VAL __builtin_huge_val() -#define HUGE_VALF __builtin_huge_valf() -#define HUGE_VALL __builtin_huge_vall() -#define INFINITY __builtin_inff() -#define NAN __builtin_nanf("") - - -/* Trigonometric functions */ - - -/* Returns the cosine of an angle of x radians. */ -extern double cos(double x); - - -/* Returns the sine of an angle of x radians. */ -extern double sin(double x); - - -/* Returns the tangent of an angle of x radians. */ -extern double tan(double x); - - -/* Returns the principal value of the arc cosine of x, expressed in radians. */ -extern double acos(double x); - - -/* Returns the principal value of the arc sine of x, expressed in radians. */ -extern double asin(double x); - - -/* Returns the principal value of the arc tan of x, expressed in radians. */ -extern double atan(double x); - - -/* Returns the principal value of the arc tangent of y/x, expressed in radians. */ -extern double atan2(double y, double x); - - -/* Hyperbolic functions */ - - -/* Returns the hyperbolic cosine of x. */ -extern double cosh(double x); - - -/* Returns the hyperbolic sine of x. */ -extern double sinh(double x); - - -/* Returns the hyperbolic tangent of x. */ -extern double tanh(double x); - - -/* Exponential and logarithmic functions */ - - -/* Returns the base-e exponential function of x, which is e raised to the power x: e^x. */ -extern double exp(double x); - - -/* Breaks the floating point number x into its binary significand - * (a floating point with an absolute value between 0.5(included) and 1.0(excluded)) - * and an integral exponent for 2. */ -extern double frexp(double x, int *exp); - - -/* Returns the result of multiplying x (the significand) by 2 raised to the power of exp (the exponent). */ -extern double ldexp(double x, int exp); - - -/* Returns the natural logarithm of x. */ -extern double log(double x); - - -/* Returns the common (base-2) logarithm of x. */ -extern double log2(double x); - - -/* Returns the common (base-10) logarithm of x. */ -extern double log10(double x); - - -/* Breaks x into an integral and a fractional part. */ -extern double modf(double x, double *intpart); -extern float modff(float x, float *intpart); - - -/* Power functions */ - - -/* Returns base raised to the power exponent. */ -extern double pow(double base, double exponent); - - -/* Returns the square root of x. */ -extern double sqrt(double x); - - -/* Rounding and remainder functions */ - - -/* Rounds x upward, returning the smallest integral value that is not less than x. */ -extern double ceil(double x); -extern float ceilf(float x); - - -/* Rounds x downward, returning the largest integral value that is not greater than x. */ -extern double floor(double x); -extern float floorf(float x); - - -/* Returns the floating-point remainder of numer/denom (rounded towards zero). */ -extern double fmod(double numer, double denom); - - -/* Return the integral value nearest to x */ -extern double round(double x); -extern float roundf(float x); - - -/* Rounds x toward zero, returning the nearest integral value that is not larger in magnitude than x. */ -extern double trunc(double x); -extern float truncf(float x); - - -/* Miscellaneous */ - - -/* Returns the absolute value of x: |x|. */ -extern double fabs(double x); -extern float fabsf(float x); - - -/* C99 extensions */ -float cosf(float x); -float sinf(float x); -float tanf(float x); -float acosf(float x); -float asinf(float x); -float atanf(float x); -float atan2f(float y, float x); -float coshf(float x); -float sinhf(float x); -float tanhf(float x); -float expf(float x); -float frexpf(float x, int *exp); -float ldexpf(float x, int exp); -float logf(float x); -float log10f(float x); -float powf(float base, float exponent); -float sqrtf(float x); -float fmodf(float num, float denom); - - -#define cosf(x) ((float)cos(x)) -#define sinf(x) ((float)sin(x)) -#define tanf(x) ((float)tan(x)) -#define acosf(x) ((float)acos(x)) -#define asinf(x) ((float)asin(x)) -#define atanf(x) ((float)atan(x)) -#define atan2f(y, x) ((float)atan2(y, x)) -#define coshf(x) ((float)cosh(x)) -#define sinhf(x) ((float)sinh(x)) -#define tanhf(x) ((float)tanh(x)) -#define expf(x) ((float)exp(x)) -#define frexpf(x, exp) ((float)frexp(x, exp)) -#define ldexpf(x, exp) ((float)ldexp(x, exp)) -#define logf(x) ((float)log(x)) -#define log10f(x) ((float)log10(x)) -#define powf(base, exponent) ((float)pow(base, exponent)) -#define fmodf(num, denom) ((float)fmod(num, denom)) - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/include/math/consts.h b/include/math/consts.h deleted file mode 100644 index 40ac3e7d..00000000 --- a/include/math/consts.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Phoenix-RTOS - * - * libphoenix - * - * math.h constants - * - * Copyright 2017 Phoenix Systems - * Author: Aleksander Kaminski - * - * This file is part of Phoenix-RTOS. - * - * %LICENSE% - */ - -#ifndef _LIBPHOENIX_MATH_CONSTS_H_ -#define _LIBPHOENIX_MATH_CONSTS_H_ - -/* The base of natural logarithms. */ -#define M_E 2.7182818284590452354 - - -/* The logarithm to base 2 of M_E. */ -#define M_LOG2E 1.4426950408889634074 - - -/* The logarithm to base 10 of M_E. */ -#define M_LOG10E 0.43429448190325182765 - - -/* The natural logarithm of 2. */ -#define M_LN2 0.69314718055994530942 - - -/* The natural logarithm of 10. */ -#define M_LN10 2.30258509299404568402 - - -/* Pi, the ratio of a circle's circumference to its diameter. */ -#define M_PI 3.14159265358979323846 - - -/* Pi divided by two. */ -#define M_PI_2 1.57079632679489661923 - - -/* Pi divided by four. */ -#define M_PI_4 0.78539816339744830962 - - -/* The reciprocal of pi (1/pi) */ -#define M_1_PI 0.31830988618379067154 - - -/* Two times the reciprocal of pi. */ -#define M_2_PI 0.63661977236758134308 - - -/* Two times the reciprocal of the square root of pi. * */ -#define M_2_SQRTPI 1.12837916709551257390 - - -/* The square root of two. */ -#define M_SQRT2 1.41421356237309504880 - - -/* The reciprocal of the square root of two (also the square root of 1/2). */ -#define M_SQRT1_2 0.70710678118654752440 - - -#endif diff --git a/libm/Makefile b/libm/Makefile new file mode 100644 index 00000000..35ce473f --- /dev/null +++ b/libm/Makefile @@ -0,0 +1,87 @@ +# +# Makefile for math library +# +# Copyright 2025 Phoenix Systems +# Author: Mikolaj Matalowski +# +# This file is part of Phoenix-RTOS. +# +# %LICENSE% +# +LIBM_USE_LIBMCS ?= n +LIBM_LIBMCS_DAZ ?= n +LIBM_WANT_COMPLEX ?= y + +# Grab builtin definitions from gcc +GET_DEFINITIONS = $(shell $(CC) -dM -E - < /dev/null) +DEFINITIONS = $(filter-out #define, $(GET_DEFINITIONS)) + +# Setting sizes of floating point types +NAME_OF_TYPE_FOR_SIZE_CHECK := __SIZEOF_DOUBLE__ +DOUBLE_SIZE = $(word 2, $(shell echo "$(DEFINITIONS)" | grep -E -o '$(NAME_OF_TYPE_FOR_SIZE_CHECK)\s+(\w+)')) + +ifeq ($(DOUBLE_SIZE), 8) + CPPFLAGS += -DLIBMCS_DOUBLE_IS_64BITS +else + CPPFLAGS += -DLIBMCS_DOUBLE_IS_32BITS +endif + +NAME_OF_TYPE_FOR_SIZE_CHECK := __SIZEOF_LONG_DOUBLE__ +LDOUBLE_SIZE = $(word 2, $(shell echo "$(DEFINITIONS)" | grep -E -o '$(NAME_OF_TYPE_FOR_SIZE_CHECK)\s+(\w+)')) + +ifeq ($(LDOUBLE_SIZE), 10) + CPPFLAGS += -DLIBMCS_LONG_DOUBLE_IS_80BITS +else + CPPFLAGS += -DLIBMCS_LONG_DOUBLE_IS_64BITS +endif + +NAME_OF_TYPE_FOR_SIZE_CHECK := __SIZEOF_LONG__ +LONG_SIZE = $(word 2, $(shell echo "$(DEFINITIONS)" | grep -E -o '$(NAME_OF_TYPE_FOR_SIZE_CHECK)\s+(\w+)')) + +ifeq ($(LONG_SIZE), 8) + CPPFLAGS += -DLIBMCS_LONG_IS_64BITS +else + CPPFLAGS += -DLIBMCS_LONG_IS_32BITS +endif + +# Set options for denormals on the FPU +ifeq ($(LIBMCS_WANT_DAZ), y) + CPPFLAGS += -DLIBMCS_FPU_DAZ +endif + +ifeq ($(LIBM_WANT_COMPLEX), y) + CPPFLAGS += -DLIBMCS_WANT_COMPLEX +endif + +CFLAGS += -Ilibm/libmcs/libm/include + +# TODO: Separate math library implementation from libphoenix + +# Build for libmcs +ifeq ($(LIBM_USE_LIBMCS), y) + ifeq ($(LIBM_WANT_COMPLEX), y) + CPPFLAGS += -DLIBM_WANT_COMPLEX + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o,$(wildcard libm/libmcs/libm/complexd/internal/*.c))) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o,$(wildcard libm/libmcs/libm/complexd/*.c))) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o,$(wildcard libm/libmcs/libm/complexf/internal/*.c))) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o,$(wildcard libm/libmcs/libm/complexf/*.c))) + endif + + # fenv.c implementation is target specific + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o, $(filter-out %fenv.c,$(wildcard libm/libmcs/libm/common/*.c)))) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o,$(wildcard libm/libmcs/libm/mathf/*.c))) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o,$(wildcard libm/libmcs/libm/mathf/internal/*.c))) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o,$(wildcard libm/libmcs/libm/mathd/*.c))) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o,$(wildcard libm/libmcs/libm/mathd/internal/*.c))) +else + # Build for phoenix implementation + # OBJS += $(addprefix $(PREFIX_O)libm/, $(patsubst %.c,%.o, math/common.c math/trig.c)) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o, $(patsubst %complex.c,, $(wildcard libm/phoenix/*.c)))) + + ifeq ($(LIBM_WANT_COMPLEX), y) + OBJS += $(addprefix $(PREFIX_O), $(patsubst %.c,%.o, libm/phoenix/complex.c)) + endif + + # This part is needed for libmcs headers compatibility + CFLAGS += -include libm/libmcs/libm/include/internal_config.h +endif \ No newline at end of file diff --git a/libm/README.md b/libm/README.md new file mode 100644 index 00000000..1b65ade2 --- /dev/null +++ b/libm/README.md @@ -0,0 +1,21 @@ +# Phoenix math library implementation +This directory contains implementation of math library. It currently links to libphoenix with intention to be compiled to separate libm.a library. There are two implementation for two following reasons: +- libphoenix implementation is not complete. +- version for critical systems is nice to have :) + +Usage: For each project it is suggested to set following +- ```LIBM_USE_LIBMCS := y/n``` - select implementation of math library for critical systems (if not set will use phoenix implementation) +- ```LIBM_WANT_COMPLEX := y/n``` - select if project wants implementation of complex routines +- ```LIBM_LIBMCS_DAZ := y/n``` - (applicable only for libmcs) select whether denormals are zero. This is especially useful if underlying FPU has limited functionalities implemented. + +## LIBMCS +This is a copy of libmcs math library implementation from https://gitlab.com/gtd-gmbh/libmcs (commit: 79a3235511f01644139c95249487729621667249) + +For documentation please refer to /docs directory present on the main repo linked above. + +## Phoenix +This is implementation of math library developed alongside Pheonix RTOS operating system. Keep in mind that this implementation is not complete, not all functions in C99 standard are implemented. Since headers are shared for both implementations, and libmcs implementation contains complete set of C99 function, there might be some undefined symbols when linking projects that use this implementation in libphoenix. Not present functions will be added if such need arises in the future. + +# Notes +1. This is a temporary state, moving math library to be separate to libphoenix +2. libmcs - has no ARM optimization for ```sqrt``` function \ No newline at end of file diff --git a/libm/libmcs/.clang-format b/libm/libmcs/.clang-format new file mode 100644 index 00000000..3637168a --- /dev/null +++ b/libm/libmcs/.clang-format @@ -0,0 +1,3 @@ +--- +DisableFormat: true +--- diff --git a/libm/libmcs/.gitattributes b/libm/libmcs/.gitattributes new file mode 100644 index 00000000..06d51d28 --- /dev/null +++ b/libm/libmcs/.gitattributes @@ -0,0 +1,20 @@ +# -*- conf -*- + +## Set merge driver for ChangeLog files +# See gnulib's lib/git-merge-changelog.c (or git-merge-changelog(1)) +# for per-user setup instructions. +# +# The short version of this (optional) procedure is: +# +# (1) Install git-merge-changelog (this is the tricky part!) +# +# (2) Add something like the following to your ~/.gitconfig: +# +# [merge "merge-changelog"] +# name = GNU-style ChangeLog merge driver +# driver = git-merge-changelog %O %A %B +# +# (3) Enjoy mostly effortless ChangeLog merges, at least until the +# file gets renamed again ... + +ChangeLog merge=merge-changelog diff --git a/libm/libmcs/.gitignore b/libm/libmcs/.gitignore new file mode 100644 index 00000000..20b8bbbf --- /dev/null +++ b/libm/libmcs/.gitignore @@ -0,0 +1,54 @@ +*.diff +*.patch +*.orig +*.rej + +*~ +.#* +*# + +*.flt +*.gmo +*.info +*.la +*.lo +*.o +*.pyc +*.swp +*.tmp + +build* + +.deps +.libs + +autom4te.cache +config.cache +config.intl +config.log +config.status +libtool +POTFILES +*-POTFILES +user_make.mk +Makefile + +tags +TAGS +TAGS.sub + +.gdbinit +.gdb_history + +# ignore core files, but not java/net/protocol/core/ +core +!core/ + +lost+found +html_sdd/ +html_sum/ + +# SW Quality pipeline output +sw-quality/misra-c/* +report.json +*.log diff --git a/libm/libmcs/.gitlab-ci.yml b/libm/libmcs/.gitlab-ci.yml new file mode 100644 index 00000000..09321e5b --- /dev/null +++ b/libm/libmcs/.gitlab-ci.yml @@ -0,0 +1,102 @@ +stages: + - setup + - check + - doc + - pdf + - pages + +variables: + GIT_SUBMODULE_STRATEGY: recursive + +image: $CI_REGISTRY_IMAGE + +setup: + stage: setup + image: docker:stable + before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY + script: + - docker build -t $CI_REGISTRY_IMAGE -f Dockerfile . + - docker push $CI_REGISTRY_IMAGE + +mcdc-check: + stage: check + image: + name: registry.gitlab.com/gtd-gmbh/mcdc-checker/mcdc-checker + entrypoint: [""] + script: + - echo "#define __LIBMCS_WANT_COMPLEX" > ./libm/include/config.h + - find -regex ".*\.[ch]" | grep -v "lint\|tgmath.h\|fenv.h" | mcdc_checker -j report.json - + artifacts: + reports: + codequality: report.json + allow_failure: true + needs: [] + +code-quality: + stage: check + image: + name: local.gtd-gmbh.de:4567/tools/sqarg + entrypoint: [""] + script: + - ./sw-quality/lint.sh + artifacts: + reports: + codequality: sw-quality/misra-c/report.json + paths: + - sw-quality/misra-c/ + needs: [] + +doc: + stage: doc + script: + - sphinx-build -b html doc/sdd html_sdd 2>&1 | grep -v "duplicate label" | grep -v "documentation comment attached to unexpected cursor" + - sphinx-build -b html doc/sum html_sum 2>&1 | grep -v "duplicate label" | grep -v "documentation comment attached to unexpected cursor" + - sphinx-build -b latex doc/sdd latex_sdd 2>&1 | grep -v "duplicate label" | grep -v "documentation comment attached to unexpected cursor" + - sphinx-build -b latex doc/sum latex_sum 2>&1 | grep -v "duplicate label" | grep -v "documentation comment attached to unexpected cursor" + - chmod -R 777 latex_sdd + - chmod -R 777 latex_sum + artifacts: + paths: + - html_sdd/ + - html_sum/ + - latex_sdd/ + - latex_sum/ + expire_in: 30 days + needs: ["setup"] + +pdf: + stage: pdf + image: local.gtd-gmbh.de:4567/tools/doge:latest + dependencies: + - doc + script: + - cd latex_sdd + - make + - mv ./libmcs-sdd.pdf ../. + - cd ../latex_sum + - make + - mv ./libmcs-sum.pdf ../. + artifacts: + paths: + - ./*.pdf + expire_in: 30 days + needs: ["doc"] + +pages: + stage: pages + image: + name: pandoc/core:2.16.2 + entrypoint: [""] + dependencies: + - doc + needs: ["doc"] + script: + - mkdir public + - cp doc/index.html public + - pandoc -s -o public/README.html --metadata title="LibmCS Readme" --metadata mainfont="Lato,proxima-nova,Helvetica Neue,Arial,sans-serif" README.md + - mv html_sum public/sum + - mv html_sdd public/sdd + artifacts: + paths: + - public diff --git a/libm/libmcs/CITATION.cff b/libm/libmcs/CITATION.cff new file mode 100644 index 00000000..29c92cf1 --- /dev/null +++ b/libm/libmcs/CITATION.cff @@ -0,0 +1,74 @@ +cff-version: 1.2.0 +title: LibmCS +message: >- + If you use this software, please cite it using the + metadata from this file. +type: software +authors: + - name: GTD GmbH + address: Ravensburger Str. 32a + city: Markdorf + country: DE + post-code: '88677' + email: libmcs@gtd-gmbh.de + website: 'https://gtd-gmbh.de' + - name: ESA European Space Research and Technology Centre + address: Keplerlaan 1 + post-code: '2201' + city: Noordwijk + country: NL + website: 'https://www.esa.int' + - given-names: Fabian + family-names: Schriever + email: fabian.schriever@gtd-gmbh.de + affiliation: GTD GmbH + - given-names: Christoph + family-names: Weiß + email: christoph.weiss@gtd-gmbh.de + affiliation: GTD GmbH + - given-names: Thomas + family-names: Wucher + email: thomas.wucher@gtd-gmbh.de + affiliation: GTD GmbH + - given-names: Joan + family-names: Roig + email: joan.roig@gtd-gmbh.de + affiliation: GTD GmbH + - given-names: Andoni + family-names: Arregui + email: andoni.arregui@gtd-gmbh.de + affiliation: GTD GmbH + - given-names: Andreas + family-names: Jung + email: Andreas.Jung@esa.int + affiliation: ESA European Space Research and Technology Centre +identifiers: + - type: url + value: 'https://gtd-gmbh.gitlab.io/libmcs/' + description: LibmCS Documentation +repository-code: 'https://gitlab.com/gtd-gmbh/libmcs' +url: 'https://gtd-gmbh.de/libmcs/' +abstract: >- + The Mathematical Library for Critical Systems (LibmCS) is + an extensively tested and validated mathematical library + (libm), which provides predictable accuracy results in all + domains. The available wrappers give equal results for + auto-coding development approaches and the qualification + data package (QDP) supports an automatic qualification + according to ECSS E-ST-40 and Q-ST-80 Category B. +keywords: + - Mathematical Library + - POSIX + - IEEE-754 2019 + - ISO C18 + - MISRA-C 2012 + - ECSS E-ST-40 and Q-ST-80 Category B + - x86-64 + - ARM + - RISC-V + - SPARC V8 + - Critical Systems + - Embedded Systems +license: BSD-3-Clause +version: 1.2.0 +date-released: '2022-11-18' diff --git a/libm/libmcs/CONTRIBUTING.md b/libm/libmcs/CONTRIBUTING.md new file mode 100644 index 00000000..ebd59350 --- /dev/null +++ b/libm/libmcs/CONTRIBUTING.md @@ -0,0 +1,87 @@ +# Contributing to LibmCS + +## How Can I Contribute? + +### Reporting Bugs + +Report bugs by creating a GitLab issue with the following information: + +1. Give the Issue a meaningful title +2. Write a brief description of the issue you have +3. Describe the issue details answering the following questions: + - What are the steps to reproduce the *bug*? + - What is the current *bug* behavior? + - What is the expected *correct* behavior? + - Relevant logs/screenshots and/or associated data. + +We will pick up the issue and continue its workflow. + +### Suggesting Enhancements + +Suggest enhancements by creating a GitLab issue with the following information: + +1. Problem to solve +2. Proposed solution +3. Intended use-case + +### Pull Requests + +Contribute source code by following the next steps: + +1. Fork the repository +2. Create a branch with your code and/or documentation contribution: + - For the source code format please read the section [Styleguides](#styleguides). + - Corresponding source code documentation must be added + - All pipelines must pass +3. Create a merge request on the LibmCS repository + +We will pick up the merge request and continue its workflow. + +#### Styleguides + +To preformat the LibmCS sources we use Astyle. The concrete Astyle options we use are the following: + +```sh +> astyle --style=linux --indent=spaces=4 --break-blocks \ +--pad-oper --pad-comma --align-pointer=name --add-brackets \ +--convert-tabs --pad-header --unpad-paren \ +--indent-preproc-block --indent-preproc-define --max-code-length=99 +``` + +After running Astyle some further formatting may be carried out to adjust the overall readability. + +As an example you can take the `remquod.c` file in `libm/mathd`. There you +will see how the documentation is written and how the general source code +should look like. + +Here is an example `if` structure with comments: + +```c + /* purge off exception values */ + if ((hx >= 0x7ff00000) || (hy >= 0x7ff00000)) { /* x or y not finite */ + if (isnan(x) || isnan(y)) { /* x or y is NaN */ + return x + y; + } else if (hx == 0x7ff00000) { /* x is infinite */ + return __raise_invalid(); + } else { + /* No action required */ + } + } else if ((hy | ly) == 0) { /* y = 0 */ + return __raise_invalid(); + } else { + /* No action required */ + } +``` + +And here is a `for` loop: + +```c + /* compute q[0],q[1],...q[jk] */ + for (i = 0; i <= jk; i++) { + for (j = 0, fw = 0.0; j <= jx; j++) { + fw += x[j] * f[jx + i - j]; + } + + q[i] = fw; + } +``` diff --git a/libm/libmcs/COPYING.md b/libm/libmcs/COPYING.md new file mode 100644 index 00000000..d23eb122 --- /dev/null +++ b/libm/libmcs/COPYING.md @@ -0,0 +1,14 @@ +The LibmCS is provided under: + + SPDX-License-Identifier: GTDGmbH + +Being under the terms of the following licenses: + + LICENSES/NetBSD.md + LICENSES/PublicDomain.md + LICENSES/RedHat.md + LICENSES/RichFelker.md + LICENSES/SunMicrosystems.md + LICENSES/GTDGmbH.md + +All contributions to the LibmCS are subject to this COPYING file. diff --git a/libm/libmcs/CREDITS.md b/libm/libmcs/CREDITS.md new file mode 100644 index 00000000..dcc5ea85 --- /dev/null +++ b/libm/libmcs/CREDITS.md @@ -0,0 +1,66 @@ +This is at least a partial credits-file of people that have +contributed to the LibmCS project. + +It is sorted by name and formatted to allow easy grepping and +beautification by scripts. The fields are: name (N), email (E), +and description (D). + +Thanks, + +GTD GmbH + +N: Marco Atzeri; +E: marco.atzeri@gmail.com; +D: Integration of complex functions; + +N: Kito Cheng; +E: kito.cheng@sifive.com; +D: Misc fixes; + +N: Matthias Drochner; +E: drochner@NetBSD.org; +D: Some complex functions; + +N: Rich Felker; +E: -; +D: nexttowardf; + +N: Jeff Johnston; +E: jjohnston@redhat.com; +D: Misc fixes, tests, and contributions; + +N: Andreas Jung; +E: andreas.jung@esa.int; +D: Fixes, testing, and qualification to ECSS space software standards; + +N: Stephen L. Moshier; +E: drochner@NetBSD.org; +D: Complex functions (through Cephes -> NetBSD); + +N: Joseph Myers; +E: joseph@codesourcery.com; +D: Misc contributions; + +N: Kwok Choi Ng; +E: kwok.ng@sun.com; +D: Most double implementations of elementary transcendental functions (through FDLIBM); + +N: Keith Packard; +E: keithp@keithp.com; +D: Misc fixes and tests; + +N: Fabian Schriever; +E: fabian.schriever@gtd-gmbh.de; +D: Refactoring and qualification to ECSS space software standards; + +N: Joel Sherrill; +E: joel.sherrill@rtems.org; +D: Misc contributions; + +N: Ian Lance Taylor; +E: ian@cygnus.com; +D: Adapting double functions to float; + +N: Paul Zimmermann; +E: Paul.Zimmermann@inria.fr; +D: Misc contributions; diff --git a/libm/libmcs/Dockerfile b/libm/libmcs/Dockerfile new file mode 100644 index 00000000..7efe236e --- /dev/null +++ b/libm/libmcs/Dockerfile @@ -0,0 +1,20 @@ +FROM python:3.12-slim-bookworm + +# Install needed debian packages +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get -yq --no-install-recommends install \ + sudo \ + clang \ + llvm \ + libclang-dev \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Add a default developer user +RUN useradd -m -G sudo developer \ + && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +# Install dependencies +ADD pyproject.toml poetry.lock / +RUN pip install poetry && poetry config virtualenvs.create false && poetry install --no-root +# Open Links to GitLab in a new tab +RUN sed -i 's/fa-gitlab">/fa-gitlab" target="_blank">/' /usr/local/lib/python3.*/site-packages/sphinx_rtd_theme/breadcrumbs.html diff --git a/libm/libmcs/LICENSES/GTDGmbH.md b/libm/libmcs/LICENSES/GTDGmbH.md new file mode 100644 index 00000000..de0c589d --- /dev/null +++ b/libm/libmcs/LICENSES/GTDGmbH.md @@ -0,0 +1,27 @@ +Valid-License-Identifier: GTDGmbH +License-Text: + +Copyright (c) 2025 GTD GmbH. 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. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY GTD GMBH ``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 GTD GMBH 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. diff --git a/libm/libmcs/LICENSES/NetBSD.md b/libm/libmcs/LICENSES/NetBSD.md new file mode 100644 index 00000000..3db18484 --- /dev/null +++ b/libm/libmcs/LICENSES/NetBSD.md @@ -0,0 +1,23 @@ +Valid-License-Identifier: NetBSD +License-Text: + +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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. \ No newline at end of file diff --git a/libm/libmcs/LICENSES/PublicDomain.md b/libm/libmcs/LICENSES/PublicDomain.md new file mode 100644 index 00000000..1b9e71a9 --- /dev/null +++ b/libm/libmcs/LICENSES/PublicDomain.md @@ -0,0 +1,4 @@ +Valid-License-Identifier: PublicDomain +License-Text: + +Public domain. \ No newline at end of file diff --git a/libm/libmcs/LICENSES/RedHat.md b/libm/libmcs/LICENSES/RedHat.md new file mode 100644 index 00000000..4b01484e --- /dev/null +++ b/libm/libmcs/LICENSES/RedHat.md @@ -0,0 +1,5 @@ +Valid-License-Identifier: RedHat +License-Text: + +Permission to use, copy, modify, and distribute this software +is freely granted, provided that this notice is preserved. diff --git a/libm/libmcs/LICENSES/RichFelker.md b/libm/libmcs/LICENSES/RichFelker.md new file mode 100644 index 00000000..b6c92a54 --- /dev/null +++ b/libm/libmcs/LICENSES/RichFelker.md @@ -0,0 +1,21 @@ +Valid-License-Identifier: RichFelker +License-Text: + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/libm/libmcs/LICENSES/SunMicrosystems.md b/libm/libmcs/LICENSES/SunMicrosystems.md new file mode 100644 index 00000000..adb04a34 --- /dev/null +++ b/libm/libmcs/LICENSES/SunMicrosystems.md @@ -0,0 +1,7 @@ +Valid-License-Identifier: SunMicrosystems +License-Text: + +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. \ No newline at end of file diff --git a/libm/libmcs/Makefile.in b/libm/libmcs/Makefile.in new file mode 100644 index 00000000..6bcdb1af --- /dev/null +++ b/libm/libmcs/Makefile.in @@ -0,0 +1,340 @@ +# SPDX-License-Identifier: GTDGmbH +# Copyright 2020-2025 by GTD GmbH. + +# SHELL := bash +# +# -include user_make.mk +# +# ifndef ARCH +# ARCH = $(shell $(CROSS_COMPILE)gcc -v 2>&1 | grep Target | cut -d' ' -f 2) +# endif +# +# CC = $(CROSS_COMPILE)gcc +# AR = $(CROSS_COMPILE)ar +# MKDIR = mkdir -p +# CP = cp +# MV = mv +# RM = rm -rf +# DATE = date +# WHICH = which +# SHA256 = sha256sum +# INFO_FILENAME = build_info.yml +# +# ifeq ($(V),1) +# Q = +# else +# Q = @ +# endif +# +# ifeq ($(V),2) +# Q = +# CC += -v -Wl,-v +# endif + +INCLUDE = -Ilibm/include -Ilibm/common -Ilibm/mathd/internal -Ilibm/mathf/internal + +SRC_LIBMCS = libm/complexd/cabsd.c \ + libm/complexd/cacosd.c \ + libm/complexd/cacoshd.c \ + libm/complexd/cargd.c \ + libm/complexd/casind.c \ + libm/complexd/casinhd.c \ + libm/complexd/catand.c \ + libm/complexd/catanhd.c \ + libm/complexd/ccosd.c \ + libm/complexd/ccoshd.c \ + libm/complexd/cexpd.c \ + libm/complexd/cimagd.c \ + libm/complexd/clogd.c \ + libm/complexd/conjd.c \ + libm/complexd/cpowd.c \ + libm/complexd/cprojd.c \ + libm/complexd/creald.c \ + libm/complexd/csind.c \ + libm/complexd/csinhd.c \ + libm/complexd/csqrtd.c \ + libm/complexd/ctand.c \ + libm/complexd/ctanhd.c \ + libm/complexd/internal/ctrigd.c \ + libm/complexf/cabsf.c \ + libm/complexf/cacosf.c \ + libm/complexf/cacoshf.c \ + libm/complexf/cargf.c \ + libm/complexf/casinf.c \ + libm/complexf/casinhf.c \ + libm/complexf/catanf.c \ + libm/complexf/catanhf.c \ + libm/complexf/ccosf.c \ + libm/complexf/ccoshf.c \ + libm/complexf/cexpf.c \ + libm/complexf/cimagf.c \ + libm/complexf/clogf.c \ + libm/complexf/conjf.c \ + libm/complexf/cpowf.c \ + libm/complexf/cprojf.c \ + libm/complexf/crealf.c \ + libm/complexf/csinf.c \ + libm/complexf/csinhf.c \ + libm/complexf/csqrtf.c \ + libm/complexf/ctanf.c \ + libm/complexf/ctanhf.c \ + libm/complexf/internal/ctrigf.c + +SRC_LIBMCS += libm/common/signgam.c \ + libm/common/tools.c \ + libm/mathd/acosd.c \ + libm/mathd/acoshd.c \ + libm/mathd/asind.c \ + libm/mathd/asinhd.c \ + libm/mathd/atan2d.c \ + libm/mathd/atand.c \ + libm/mathd/atanhd.c \ + libm/mathd/cbrtd.c \ + libm/mathd/ceild.c \ + libm/mathd/copysignd.c \ + libm/mathd/cosd.c \ + libm/mathd/coshd.c \ + libm/mathd/erfcd.c \ + libm/mathd/erfd.c \ + libm/mathd/exp2d.c \ + libm/mathd/expd.c \ + libm/mathd/expm1d.c \ + libm/mathd/fabsd.c \ + libm/mathd/fdimd.c \ + libm/mathd/floord.c \ + libm/mathd/fmad.c \ + libm/mathd/fmaxd.c \ + libm/mathd/fmind.c \ + libm/mathd/fmodd.c \ + libm/mathd/frexpd.c \ + libm/mathd/hypotd.c \ + libm/mathd/ilogbd.c \ + libm/mathd/internal/fpclassifyd.c \ + libm/mathd/internal/gammad.c \ + libm/mathd/internal/signbitd.c \ + libm/mathd/internal/trigd.c \ + libm/mathd/j0d.c \ + libm/mathd/j1d.c \ + libm/mathd/jnd.c \ + libm/mathd/ldexpd.c \ + libm/mathd/lgammad.c \ + libm/mathd/llrintd.c \ + libm/mathd/llroundd.c \ + libm/mathd/log10d.c \ + libm/mathd/log1pd.c \ + libm/mathd/log2d.c \ + libm/mathd/logbd.c \ + libm/mathd/logd.c \ + libm/mathd/lrintd.c \ + libm/mathd/lroundd.c \ + libm/mathd/modfd.c \ + libm/mathd/nand.c \ + libm/mathd/nearbyintd.c \ + libm/mathd/nextafterd.c \ + libm/mathd/nexttowardd.c \ + libm/mathd/powd.c \ + libm/mathd/remainderd.c \ + libm/mathd/remquod.c \ + libm/mathd/rintd.c \ + libm/mathd/roundd.c \ + libm/mathd/scalblnd.c \ + libm/mathd/scalbnd.c \ + libm/mathd/sind.c \ + libm/mathd/sinhd.c \ + libm/mathd/sqrtd.c \ + libm/mathd/tand.c \ + libm/mathd/tanhd.c \ + libm/mathd/tgammad.c \ + libm/mathd/truncd.c \ + libm/mathd/y0d.c \ + libm/mathd/y1d.c \ + libm/mathd/ynd.c \ + libm/mathf/acosf.c \ + libm/mathf/acoshf.c \ + libm/mathf/asinf.c \ + libm/mathf/asinhf.c \ + libm/mathf/atan2f.c \ + libm/mathf/atanf.c \ + libm/mathf/atanhf.c \ + libm/mathf/cbrtf.c \ + libm/mathf/ceilf.c \ + libm/mathf/copysignf.c \ + libm/mathf/cosf.c \ + libm/mathf/coshf.c \ + libm/mathf/erfcf.c \ + libm/mathf/erff.c \ + libm/mathf/exp2f.c \ + libm/mathf/expf.c \ + libm/mathf/expm1f.c \ + libm/mathf/fabsf.c \ + libm/mathf/fdimf.c \ + libm/mathf/floorf.c \ + libm/mathf/fmaf.c \ + libm/mathf/fmaxf.c \ + libm/mathf/fminf.c \ + libm/mathf/fmodf.c \ + libm/mathf/frexpf.c \ + libm/mathf/hypotf.c \ + libm/mathf/ilogbf.c \ + libm/mathf/internal/fpclassifyf.c \ + libm/mathf/internal/gammaf.c \ + libm/mathf/internal/signbitf.c \ + libm/mathf/internal/trigf.c \ + libm/mathf/ldexpf.c \ + libm/mathf/lgammaf.c \ + libm/mathf/llrintf.c \ + libm/mathf/llroundf.c \ + libm/mathf/log10f.c \ + libm/mathf/log1pf.c \ + libm/mathf/log2f.c \ + libm/mathf/logbf.c \ + libm/mathf/logf.c \ + libm/mathf/lrintf.c \ + libm/mathf/lroundf.c \ + libm/mathf/modff.c \ + libm/mathf/nanf.c \ + libm/mathf/nearbyintf.c \ + libm/mathf/nextafterf.c \ + libm/mathf/nexttowardf.c \ + libm/mathf/powf.c \ + libm/mathf/remainderf.c \ + libm/mathf/remquof.c \ + libm/mathf/rintf.c \ + libm/mathf/roundf.c \ + libm/mathf/scalblnf.c \ + libm/mathf/scalbnf.c \ + libm/mathf/sinf.c \ + libm/mathf/sinhf.c \ + libm/mathf/sqrtf.c \ + libm/mathf/tanf.c \ + libm/mathf/tanhf.c \ + libm/mathf/tgammaf.c \ + libm/mathf/truncf.c + +ifeq ($(WANT_COMPLEX),1) + SRC += $(CSRC) + EXTRA_CFLAGS += -DLIBMCS_WANT_COMPLEX +endif + +# SRC_ROOT = . +# SRC_DIRS = $(sort $(dir $(SRC))) + +# BUILD_ROOT = build-$(ARCH) +# +# BUILD_INFO = $(BUILD_ROOT)/$(INFO_FILENAME) +# +# OBJ_ROOT = $(BUILD_ROOT)/obj +# OBJ_DIRS = $(addprefix $(OBJ_ROOT)/,$(SRC_DIRS)) +# +# BIN_DIR = $(BUILD_ROOT)/bin +# +# OUT = $(BIN_DIR)/libm.a + +CFLAGS += -Wall -std=c99 -pedantic -Wextra +CFLAGS += -Wstrict-prototypes +CFLAGS += -frounding-math -fsignaling-nans -g3 -O2 -fno-builtin $(EXTRA_CFLAGS) + +# ifndef COVERAGE +# COVERAGE=0 +# endif + +# ifeq ($(COVERAGE),1) +# CFLAGS +=-O0 -fprofile-arcs -ftest-coverage +# GCCVERSIONGTEQ14 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 14) +# ifeq "$(GCCVERSIONGTEQ14)" "1" +# CFLAGS += -fcondition-coverage +# endif +# endif + +# OBJ = $(addprefix $(OBJ_ROOT)/, $(SRC:.c=.o)) +# +# .SUFFIXES: +# .SUFFIXES: .o .c +# +# .PHONY: all debug release clean cleanall distclean install check_config help +# all: $(OUT) $(BUILD_INFO) +# @echo "[CP] include" +# $(Q)$(CP) -r $(SRC_ROOT)/libm/include/ $(BUILD_ROOT)/include/ +# +# check_config: +# @[ "1" == "$(CONFIGURE_SUCCESS)" ] || (echo "Either configuration was faulty or not done, please run configure" && exit 1) +# +# $(BUILD_INFO): $(OUT) +# @echo "[LOG] $(BUILD_INFO)" +# @echo "---" > $(BUILD_INFO) +# @printf "date: " >> $(BUILD_INFO) +# $(Q)$(DATE) +"%Y-%m-%dT%H:%M:%S%z" >> $(BUILD_INFO) +# @printf "compiler_path: " >> $(BUILD_INFO) +# $(Q)$(WHICH) $(CC) >> $(BUILD_INFO) +# @echo "compiler_information: |" >> $(BUILD_INFO) +# $(Q)$(CC) -v 2>&1 | sed 's/^/ /' >> $(BUILD_INFO) +# @echo "binutils_information: |" >> $(BUILD_INFO) +# $(Q)$(AR) -V 2>&1 | sed 's/^/ /' >> $(BUILD_INFO) +# @echo "cflags_and_include: $(CFLAGS) $(CFLAGS_TARGET) $(INCLUDE)" >> $(BUILD_INFO) +# @echo "git_info:" >> $(BUILD_INFO) +# @printf " branch: " >> $(BUILD_INFO) +# $(Q)(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "-") >> $(BUILD_INFO) +# @printf " commit: " >> $(BUILD_INFO) +# $(Q)(git rev-parse HEAD 2>/dev/null || echo "-") >> $(BUILD_INFO) +# @printf " dirty: " >> $(BUILD_INFO) +# $(Q)((git diff --exit-code > /dev/null 2>&1 && echo "no") || ([ $$? -eq 1 ] && echo "yes") || echo "-") >> $(BUILD_INFO) +# @printf "libm_sha256: " >> $(BUILD_INFO) +# $(Q)echo `$(SHA256) $(OUT) | head -c 64` >> $(BUILD_INFO) +# @echo "..." >> $(BUILD_INFO) +# +# # Include dependency info for *existing* .o files +# -include $(OBJ:.o=.d) +# +# $(OUT): $(OBJ) | check_config $(BIN_DIR) +# @echo "[AR] $@" +# $(Q)$(AR) -scr $@ $? +# +# $(OBJ_ROOT)/%.o: $(SRC_ROOT)/%.c | check_config $(OBJ_DIRS) +# @echo "[CC] $< > $@" +# $(Q)$(CC) $(CFLAGS) $(CFLAGS_TARGET) $(INCLUDE) -MD -MP $< -o $@ +# +# $(OBJ_DIRS) $(BIN_DIR): check_config +# @echo "[MKDIR] $@" +# $(Q)$(MKDIR) $@ +# +# debug: all +# +# release: CFLAGS += -DNDEBUG +# release: all +# +# clean: +# @echo "[RM] $(BUILD_ROOT)" +# $(Q)$(RM) $(BUILD_ROOT) +# +# cleanall: +# @echo "[RM] build-*" +# $(Q)$(RM) build-* +# +# distclean: cleanall +# @echo "[RM] user_make.mk" +# $(Q)$(RM) user_make.mk +# @echo "[RM] config.h" +# $(Q)$(RM) libm/include/config.h +# $(Q)$(RM) sizeoftypes.c +# $(Q)$(RM) sizeoftypes.o +# $(Q)$(RM) Makefile +# +# install: +# @echo "LibmCS cannot be installed." +# +# help: +# @echo "LibmCS make has the following targets:" +# @echo " all:" +# @echo " Builds the library. This is the default target." +# @echo " debug:" +# @echo " Builds the library. Currently equivalent to 'all'." +# @echo " release:" +# @echo " Builds the library. Equivalent to 'all' with the additional flag '-DNDEBUG' set." +# @echo " clean:" +# @echo " Removes the build directory of the library of the current ARCH. (ARCH can be set" +# @echo " manually or is extracted from using the compiler)" +# @echo " cleanall:" +# @echo " Removes all build directories of the library." +# @echo " distclean:" +# @echo " Removes all files created by 'configure' and all builds." +# \ No newline at end of file diff --git a/libm/libmcs/README.md b/libm/libmcs/README.md new file mode 100644 index 00000000..8d4200fd --- /dev/null +++ b/libm/libmcs/README.md @@ -0,0 +1,117 @@ +# LibmCS + +This is the mathematical library for critical systems (LibmCS). + +It has been developed in compliance with the European Cooperation for Space Standardization (ECSS) standards E-ST-40 and Q-ST-80 to criticality Category B and it is also compliant to the standards: + +- IEEE-754, +- C18, +- POSIX, and +- MISRA C + +The library has been developed by GTD GmbH under the ESA Contract No. 4000130278/20/NL/AS. + +The copyright and licensing condition of the library can be found in the COPYING.md file. + + +## Getting Started + +### Documentation Entry Point + +If you are a software architect interested in assessing the possibility to include the LibmCS in your software project you may start reading the: + +- Software Release Document (OR-SRelD.00-ML) + +If you are a software product assurance engineer interested in the aspects for the delta-qualification of the LibmCS for your specific project you may start reading the: + +- Qualification Guideline (OP-QG.00-ML) + +If you are a software engineer interested in using the library in your software project you can continue reading the following section and taking a look at the Software User Manual available in this repository. + +*Note*: The OR-SRelD.00-ML and OP-QG.00-ML documents are accessible through the [ESA ESSR (European Space Software Repository)](https://essr.esa.int/) site, which is accessible to all ESA member states (search this site for LibmCS). The documents and the qualification-kit can also be obtained through GTD GmbH (contact libmcs@gtd-gmbh.de). + +### Programmer's Entry Point + +To start using the LibmCS in your software project you can clone this repository and start configuring and compiling the library: + +``` +> ./configure +> make +``` + +#### Using Configure With Flags + +For CI and similar activities it can be useful to not use an interactive script for the configuration as such it is also possible to call `configure` with flags which answer the questions otherwise asked interactively (if only some flags are set, the remaining questions will still be asked). The following flags can be set: + +| Configure Flag | Description | +|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--cross-compile ` | Tells `make` which toolchain to use. | +| `--compilation-flags ` | Used do define additional flags to the compiler. Takes both user and library specific flags/defines, e.g. `-mcpu=...`. | +| `--enable-denormal-handling` | The library will assume the platform does not provide denormals and use the platform to convert denormal inputs/outputs to 0. | +| `--disable-denormal-handling` | The library will assume the platform does provide denormals properly. | +| `--enable-long-double-procedures` | Should be set if the size of `long double` is 64 bit and the procedures shall be provided. | +| `--disable-long-double-procedures` | Should be set if the size of `long double` is not 64 bit or the procedures shall not be provided. If this is set, the library will not have `long double` procedures built. | +| `--enable-complex-procedures` | If this is set complex procedures are available. | +| `--disable-complex-procedures` | If this is set the library will not have complex procedures built. | +| `--big-endian` | Tells the compilation that variables are in big endian. | +| `--little-endian` | Tells the compilation that variables are in little endian. | + +Of special note here is also that the library needs to know which endianness the platform uses (big endian for SPARC processors and little usually for the rest). Most compilers use the define `__BYTE_ORDER__` with either `__ORDER_BIG_ENDIAN__` or `__ORDER_LITTLE_ENDIAN__` set, but if your toolchain does not provide this define you have to do it yourself (e.g. the EDISOFT RTEMS does not). + +##### Some Examples + +1. For a LEON2 processor and the EDISOFT RTEMS 4.8 tool-chain, without `long double` functions nor complex functions, the configuration would look like this: + +``` +> ./configure --cross-compile /opt/rtems-4.8/bin/sparc-rtems4.8- --compilation-flags "-mcpu=leon" --enable-denormal-handling --disable-long-double-procedures --disable-complex-procedures --big-endian +``` + +2. For a LEON3/LEON4 processor and an OAR RTEMS 4.11 tool-chain, without `long double` functions nor complex functions, the configuration would look like this: + +``` +> ./configure --cross-compile /opt/rtems-4.11-2016.04.01.FPU/bin/sparc-rtems4.11- --compilation-flags "-mcpu=leon3" --disable-denormal-handling --disable-long-double-procedures --disable-complex-procedures --big-endian +``` + +3. For an ARM R52 processor and a certain GCC cross compiler, without `long double` functions nor complex functions, the configuration would look like this: + +``` +> ./configure --cross-compile --compilation-flags "-mcpu=cortex-r52" --enable-denormal-handling --disable-long-double-procedures --disable-complex-procedures --little-endian +``` + +4. For a LEON3/LEON4 processor and an RTEMS 6 UNI/SMP tool-chain, without `long double` functions nor complex functions, the configuration would look like this: + +``` +> ./configure --cross-compile /opt/rtems/rtems-6-sparc-gr712rc-smp-6/bin/sparc-rtems6- --compilation-flags "-mcpu=leon3" --disable-denormal-handling --disable-long-double-procedures --disable-complex-procedures --big-endian +``` + + +#### Test Coverage + +Test coverage is not set using `configure`, it can be enabled by adding `COVERAGE=1` to the `make` call. Note that `configure` still has to be run first before `make` also for this case. + +#### Make Targets + +| Make Target | Description | +|-------------|------------------------------------------------------------------------------------------------------------------------------------| +| `all` | Builds the library. This is the default target. | +| `debug` | Builds the library. Currently equivalent to `all`. | +| `release` | Builds the library. Equivalent to `all` with the additional flag `-DNDEBUG` set. | +| `clean` | Removes the build directory of the library of the current ARCH. (ARCH can be set manually or is extracted from using the compiler) | +| `cleanall` | Removes all build directories of the library. | +| `distclean` | Removes all files created by 'configure' and all builds. | + +Note: LibmCS does not have an `install` target. + +#### Using Hardware Instructions + +To replace LibmCS procedures with custom procedures, such as hardware instruction calling procedures (e.g., using the CPU hardware implementation of procedures such as square root), several steps need to be followed: + ++ Add the file containing the procedure into an architecture specific sub-directory within the `libm/machine` directory. If the directory does not exist, make one for your architecture. An example for this step has already been added to the library for the SPARC V8 architecture. ++ Replace the file you want to replace in the `Makefile.in`. As an example for this step check the branch `makefile-sparc-v8-hardware-sqrt` where this is done for the SPARC V8 `sqrt` procedure. + +Note that replacing procedures may cause different results and in turn may cause unit tests to fail. You will have to justify those fails, or change the respective tests and justify that change. + + +## How to Contribute + +To learn how to contribute to the LibmCS please read the CONTRIBUTING.md file. diff --git a/libm/libmcs/configure b/libm/libmcs/configure new file mode 100755 index 00000000..8f407b29 --- /dev/null +++ b/libm/libmcs/configure @@ -0,0 +1,261 @@ +#!/usr/bin/env bash +# shellcheck disable=all +# SPDX-License-Identifier: GTDGmbH +# Copyright 2020-2025 by GTD GmbH. + +pwd + +# Filenames +sizecheck=libm/libmcs/sizeoftypes.c +user_make=libm/libmcs/user_make.mk +user_config=libm/libmcs/libm/include/config.h +makefile_in=libm/libmcs/Makefile.in +makefile_out=libm/generated_make.mk + +usage() +{ + echo "Usage: configure [--help] [ --cross-compile CROSS_COMPILE ] [ --compilation-flags CFLAGS ] [ --enable-denormal-handling ] [ --disable-denormal-handling ] [ --enable-long-double-procedures ] [ --disable-long-double-procedures ] [ --enable-complex-procedures ] [ --disable-complex-procedures ] [ --big-endian ] [ --little-endian ]" + exit 2 +} + +help_message() +{ + echo "Usage: configure [--help] [ --cross-compile CROSS_COMPILE ] [ --compilation-flags CFLAGS ] [ --enable-denormal-handling ] [ --disable-denormal-handling ] [ --enable-long-double-procedures ] [ --disable-long-double-procedures ] [ --enable-complex-procedures ] [ --disable-complex-procedures ] [ --big-endian ] [ --little-endian ]" + echo "" + echo "This configuration file offers the following flags to directly answer the" + echo "questions otherwise asked within:" + echo " --cross-compile " + echo " Tells the Makefile which toolchain suffix to use for the compilation," + echo " linking, etc. For example 'sparc-rtems-'." + echo " --compilation-flags " + echo " Adds additional flags to the compilation. For example '-mlong-double-64'" + echo " to get 64 bit long doubles on x86 targets using gcc." + echo " --enable-denormal-handling" + echo " --disable-denormal-handling" + echo " Enables/Disables the use of DAZ/FTZ mode for handling denormal numbers." + echo " This hingly depends on the user's hardware, so please check whether your" + echo " platform supports/requires the use of DAZ/FTZ." + echo " --enable-long-double-procedures" + echo " --disable-long-double-procedures" + echo " Enables/Disables the compilation of long double procedures. Disabling" + echo " them causes the Makefile to not build long double procedures into the" + echo " libm. Long double procedures can only be enabled if the platform supports" + echo " and is configured with long double with a size of 64bit." + echo " --enable-complex-procedures" + echo " --disable-complex-procedures" + echo " Enables/Disables the compilation of complex procedures. Disabling them" + echo " causes the Makefile to not build complex procedures into the libm" + echo " (everything that is usually included with complex.h)." + echo " --big-endian" + echo " --little-endian" + echo " Manually inform the compiler which endianess the platform uses. This" + echo " question only needs to be answered if the toolchain compiler does not" + echo " provide the answer itself." + exit 2 +} + +PARSED_ARGUMENTS=$(getopt -a -n configure -o h --long help,cross-compile:,compilation-flags:,enable-denormal-handling,disable-denormal-handling,enable-long-double-procedures,disable-long-double-procedures,enable-complex-procedures,disable-complex-procedures,big-endian,little-endian -- "$@") +VALID_ARGUMENTS=$? +if [ "$VALID_ARGUMENTS" != "0" ]; then + usage +fi + +echo "Arguments are: $PARSED_ARGUMENTS" +eval set -- "$PARSED_ARGUMENTS" +while : +do + case "$1" in + -h) help_message ;; + --help) help_message ;; + --cross-compile) CROSS_COMPILE="$2" ; shift 2 ;; + --compilation-flags) extra_cflags="$2" ; shift 2 ;; + --enable-denormal-handling) WANT_DAZ=1 ; shift ;; + --disable-denormal-handling) WANT_DAZ=0 ; shift ;; + --enable-long-double-procedures) WANT_LD=1 ; shift ;; + --disable-long-double-procedures) WANT_LD=0 ; shift ;; + --enable-complex-procedures) WANT_COMPLEX=1 ; shift ;; + --disable-complex-procedures) WANT_COMPLEX=0 ; shift ;; + --big-endian) BIG_ENDIAN=1 ; shift ;; + --little-endian) BIG_ENDIAN=0 ; shift ;; + --) shift ; break ;; + *) echo "Unexpected option: $1" + usage ;; + esac +done + +# Delete old files created by configure if there are any +[ -f "${user_make}" ] && rm ${user_make} +[ -f "${user_config}" ] && rm ${user_config} +[ -f "${makefile_out}" ] && rm ${makefile_out} + +# Create .c file to check type sizes +echo "Creating minimal .c file to check type sizes." +printf "double d_data[16];\\nlong double l_data[16];\\nlong int li_data[16];\\n" > ${sizecheck} + +# Ask user for toolchain +if [ -z ${CROSS_COMPILE+x} ]; then echo "Please enter the path to your compiler toolchain including prefix (e.g. /opt/rtems-4.11/bin/sparc-rtems-), leave empty if compiling on & for host:"; fi +while true +do + if [ -z ${CROSS_COMPILE+x} ]; then read -r CROSS_COMPILE; fi + CC=${CROSS_COMPILE}gcc + CC_version=$($CC --version) + if [[ "$CC_version" == "" ]]; then + echo "No compiler found at specified location. Try entering path+prefix of your toolchain again:" + read -r CROSS_COMPILE + else + break + fi +done +echo "Found compiler:" +echo "${CC_version}" + +# Ask for CFLAGS +if [ -z ${extra_cflags+x} ]; then echo "Please enter additional compiler flags (e.g. -mlong-double-64):"; fi +while true +do + if [ -z ${extra_cflags+x} ]; then read -r extra_cflags; fi + if $($CC -c ${sizecheck} ${extra_cflags}); then + break + else + echo "Your compiler did not recognise all your flags. Try again:" + read -r extra_cflags + fi +done + +# Ask user for DAZ/FTZ +if [ -z ${WANT_DAZ+x} ]; then + echo "Does your platform by default use, or is configured to use, DAZ/FTZ (Denormals Are Zero / Flush To Zero) mode (e.g. your platform has an older GRFPU which does not support subnormals)?" + select yn in "Yes" "No"; do + case $yn in + Yes ) WANT_DAZ=1; extra_cflags="${extra_cflags} -DLIBMCS_FPU_DAZ"; break;; + No ) WANT_DAZ=0; break;; + esac + done +elif [ ${WANT_DAZ} -eq 1 ]; then + extra_cflags="${extra_cflags} -DLIBMCS_FPU_DAZ"; +fi + +# Build and run type sizes check to assign defines +echo "Build and run type sizes check to assign defines." +$CC -c ${sizecheck} ${extra_cflags} +long_int_size=$("${CROSS_COMPILE}"nm -S -t d ${sizecheck%.*}.o | grep "li_data" | awk '{print $2/16*8}') +if [ "$long_int_size" -eq "32" ]; then + extra_cflags="${extra_cflags} -DLIBMCS_LONG_IS_32BITS"; + echo "Found long int to be 32bit."; + LONG_INT_32=1; +else + LONG_INT_32=0; +fi +double_size=$("${CROSS_COMPILE}"nm -S -t d ${sizecheck%.*}.o | grep "d_data" | awk '{print $2/16*8}') +if [ "$double_size" -eq "32" ]; then + extra_cflags="${extra_cflags} -DLIBMCS_DOUBLE_IS_32BITS"; + echo "Found double to be 32bit."; + DOUBLE_32=1; + WANT_LD=0; +else + DOUBLE_32=0; + long_double_size=$("${CROSS_COMPILE}"nm -S -t d ${sizecheck%.*}.o | grep "l_data" | awk '{print $2/16*8}') + if [ "$long_double_size" -eq "64" ]; then + echo "Found long double to be 64bit."; + if [ -z ${WANT_LD+x} ]; then + echo "Do you want long double procedures? If 'No' is chosen long double procedures will not be compiled into the library, and will not need to be qualified."; + select yn in "Yes" "No"; do + case $yn in + Yes ) WANT_LD=1; extra_cflags="${extra_cflags} -DLIBMCS_LONG_DOUBLE_IS_64BITS"; break;; + No ) WANT_LD=0; break;; + esac + done + elif [ ${WANT_LD} -eq 1 ]; then + extra_cflags="${extra_cflags} -DLIBMCS_LONG_DOUBLE_IS_64BITS"; + fi + else + echo "Found long double to be not 64bit. The library will not have long double procedures."; + WANT_LD=0; + fi +fi + +# Check toolchain for endianness +echo "Check toolchain for endianness." +endianness=$($CC -dM -E ${extra_cflags} - < /dev/null | grep "__BYTE_ORDER__" | awk '{print $3}') +if [ "$endianness" != "__ORDER_LITTLE_ENDIAN__" ] && [ "$endianness" != "__ORDER_BIG_ENDIAN__" ] ; then + if [ -z ${BIG_ENDIAN+x} ]; then + echo "Your toolchain does not define endianness (__BYTE_ORDER__ is not defined as either __ORDER_BIG_ENDIAN__ or __ORDER_LITTLE_ENDIAN__). Which endianness is appropriate for your target platform (e.g. SPARCs are usually Big Endian)?"; + select endian in "Little Endian" "Big Endian"; do + case $endian in + "Little Endian" ) BIG_ENDIAN=0; extra_cflags="${extra_cflags} -D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__"; break;; + "Big Endian" ) BIG_ENDIAN=1; extra_cflags="${extra_cflags} -D__BYTE_ORDER__=__ORDER_BIG_ENDIAN__"; break;; + esac + done + elif [ ${BIG_ENDIAN} -eq 1 ]; then + extra_cflags="${extra_cflags} -D__BYTE_ORDER__=__ORDER_BIG_ENDIAN__" + elif [ ${BIG_ENDIAN} -eq 0 ]; then + extra_cflags="${extra_cflags} -D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__" + fi +else + echo "Found endianness to be ${endianness}."; +fi + +# Create configuration Makefile +echo "Creating configuration Makefile." +{ echo "ifndef CROSS_COMPILE"; +echo " CROSS_COMPILE = ${CROSS_COMPILE}"; +echo "endif"; +echo "EXTRA_CFLAGS += ${extra_cflags}"; } > ${user_make} +echo "Added the following extra compilation flags to make: ${extra_cflags}" + +# Ask user for complex procedures +if [ -z ${WANT_COMPLEX+x} ]; then + echo "Do you want complex procedures? If 'No' is chosen complex procedures will not be compiled into the library, and will not need to be qualified." + select yn in "Yes" "No"; do + case $yn in + Yes ) WANT_COMPLEX=1; echo "WANT_COMPLEX = 1" >> ${user_make}; echo "See user manual (SUM) for the limitations and inaccuracies in complex procedures!"; break;; + No ) WANT_COMPLEX=0; echo "WANT_COMPLEX = 0" >> ${user_make}; break;; + esac + done +elif [ ${WANT_COMPLEX} -eq 1 ]; then + echo "WANT_COMPLEX = 1" >> ${user_make} + echo "See user manual (SUM) for the limitations and inaccuracies in complex procedures!" +elif [ ${WANT_COMPLEX} -eq 0 ]; then + echo "WANT_COMPLEX = 0" >> ${user_make} +fi + +# Create config.h +printf "/* SPDX-License-Identifier: GTDGmbH */\\n/* Copyright 2020-2022 by GTD GmbH. */\\n" > ${user_config} +printf "\\n#ifndef LIBMCS_CONFIG_H\\n#define LIBMCS_CONFIG_H\\n\\n" >> ${user_config} +if [ ${WANT_DAZ} -eq 1 ]; then + printf "#ifndef LIBMCS_FPU_DAZ\\n #define LIBMCS_FPU_DAZ\\n#endif /* !LIBMCS_FPU_DAZ */\\n" >> ${user_config} +else + printf "#ifdef LIBMCS_FPU_DAZ\\n #undef LIBMCS_FPU_DAZ\\n#endif /* LIBMCS_FPU_DAZ */\\n" >> ${user_config} +fi +if [ ${LONG_INT_32} -eq 1 ]; then + printf "#ifndef LIBMCS_LONG_IS_32BITS\\n #define LIBMCS_LONG_IS_32BITS\\n#endif /* !LIBMCS_LONG_IS_32BITS */\\n" >> ${user_config} +fi +if [ ${DOUBLE_32} -eq 1 ]; then + printf "#ifndef LIBMCS_DOUBLE_IS_32BITS\\n #define LIBMCS_DOUBLE_IS_32BITS\\n#endif /* !LIBMCS_DOUBLE_IS_32BITS */\\n" >> ${user_config} +fi +if [ ${WANT_LD} -eq 1 ]; then + printf "#ifndef LIBMCS_LONG_DOUBLE_IS_64BITS\\n #define LIBMCS_LONG_DOUBLE_IS_64BITS\\n#endif /* !LIBMCS_LONG_DOUBLE_IS_64BITS */\\n" >> ${user_config} +else + printf "#ifdef LIBMCS_LONG_DOUBLE_IS_64BITS\\n #undef LIBMCS_LONG_DOUBLE_IS_64BITS\\n#endif /* LIBMCS_LONG_DOUBLE_IS_64BITS */\\n" >> ${user_config} +fi +if [ ${WANT_COMPLEX} -eq 1 ]; then + printf "#ifndef LIBMCS_WANT_COMPLEX\\n #define LIBMCS_WANT_COMPLEX\\n#endif /* !LIBMCS_WANT_COMPLEX */\\n" >> ${user_config} +else + printf "#ifdef LIBMCS_WANT_COMPLEX\\n #undef LIBMCS_WANT_COMPLEX\\n#endif /* LIBMCS_WANT_COMPLEX */\\n" >> ${user_config} +fi +if ! [ -z ${BIG_ENDIAN+x} ]; then + printf "#ifndef __BYTE_ORDER__\\n" >> ${user_config} + if [ ${BIG_ENDIAN} -eq 1 ]; then + printf " #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__\\n" >> ${user_config} + else + printf " #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__\\n" >> ${user_config} + fi + printf "#endif /* __BYTE_ORDER__ */\\n" >> ${user_config} +fi +printf "\\n#endif /* !LIBMCS_CONFIG_H */\\n" >> ${user_config} + +# Cleanup +rm ${sizecheck} +rm ${sizecheck%.*}.o +echo "CONFIGURE_SUCCESS = 1" >> ${user_make} +cp ${makefile_in} ${makefile_out} diff --git a/libm/libmcs/libm/common/cmplx.c b/libm/libmcs/libm/common/cmplx.c new file mode 100644 index 00000000..53f7d0ed --- /dev/null +++ b/libm/libmcs/libm/common/cmplx.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This family of macros is used to create a complex value out of the two + * inputs where :math:`x` is real and :math:`y` is the imaginary part. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex CMPLXF(float x, float y); + * double complex CMPLX(double x, double y); + * long double complex CMPLXL(long double x, long double y); + * + * Description + * =========== + * + * ``CMPLX`` creates a complex value out of the two inputs where :math:`x` is + * real and :math:`y` is the imaginary part. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * CMPLX(x, y) = x + iy + * + * Returns + * ======= + * + * ``CMPLX`` returns a complex value where :math:`x` is real and :math:`y` is + * the imaginary part. + * + */ diff --git a/libm/libmcs/libm/common/fenv.c b/libm/libmcs/libm/common/fenv.c new file mode 100644 index 00000000..ae91ab2e --- /dev/null +++ b/libm/libmcs/libm/common/fenv.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#include "fenv.h" + +int feclearexcept(int excepts) +{ + return -1; +} + +int feraiseexcept(int excepts) +{ + return -1; +} + +int fegetexceptflag(fexcept_t *flagp, int excepts) +{ + return -1; +} + +int fesetexceptflag(const fexcept_t *flagp, int excepts) +{ + return -1; +} + +int fegetround(void) +{ + return -1; +} + +int fesetround(int rdir) +{ + return -1; +} + +int fegetenv(fenv_t *envp) +{ + return -1; +} + +int fesetenv(const fenv_t *envp) +{ + return -1; +} + +int feholdexcept(fenv_t *envp) +{ + return -1; +} + +int feupdateenv(const fenv_t *envp) +{ + return -1; +} + +int fetestexcept(int excepts) +{ + return -1; +} diff --git a/libm/libmcs/libm/common/isfinite.c b/libm/libmcs/libm/common/isfinite.c new file mode 100644 index 00000000..1e5fd687 --- /dev/null +++ b/libm/libmcs/libm/common/isfinite.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is a finite floating-point value. It + * can be called with ``float``, ``double`` or ``long double`` input. This + * macro is implemented in ``math.h``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int isfinite(x); + * + * Description + * =========== + * + * ``isfinite`` tests whether the input value is finite (neither infinite nor + * :math:`NaN`) or not. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * isfinite(x) = \left\{\begin{array}{ll} 1, & x \in \mathbb{F} \setminus \left \{ \pm Inf, NaN \right \} \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``isfinite`` returns :math:`1` if the input is finite, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+------------------------------------------------------------------+--------------+-------------+ + * | **x** | :math:`-Inf` | :math:`\in \mathbb{F} \setminus \left \{ \pm Inf, NaN \right \}` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================================================================+==============+=============+ + * | **isfinite(x)** | :math:`0` | :math:`1` | :math:`0` | :math:`0` | + * +---------------------+--------------+------------------------------------------------------------------+--------------+-------------+ + * + */ + diff --git a/libm/libmcs/libm/common/isgreater.c b/libm/libmcs/libm/common/isgreater.c new file mode 100644 index 00000000..62d8e2db --- /dev/null +++ b/libm/libmcs/libm/common/isgreater.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is greater than :math:`y` without + * throwing an ``invalid operation`` exception on ``NaN`` inputs (this even + * includes ``sNaN``). + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int isgreater(x, y); + * + * Description + * =========== + * + * ``isgreater`` tests whether :math:`x` is greater than :math:`y` without + * throwing an ``invalid operation`` exception on ``NaN`` inputs. Not throwing + * an exception is the only difference to using a relational comparison + * operator. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * isgreater(x, y) = \left\{\begin{array}{ll} 1, & x > y \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``isgreater`` returns :math:`1` if :math:`x > y`, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. This includes ``sNaN`` inputs. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+ + * | isgreater(x,y) | x | + * +--------------------------+--------------------------+--------------------------+ + * | y | :math:`\neq NaN` | :math:`NaN` | + * +==========================+==========================+==========================+ + * | :math:`\neq NaN` | :math:`x > y\ ?\ 1 : 0` | :math:`0` | + * +--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`0` | | + * +--------------------------+--------------------------+--------------------------+ + * + */ diff --git a/libm/libmcs/libm/common/isgreaterequal.c b/libm/libmcs/libm/common/isgreaterequal.c new file mode 100644 index 00000000..394e4119 --- /dev/null +++ b/libm/libmcs/libm/common/isgreaterequal.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is greater than or equal to + * :math:`y` without throwing an ``invalid operation`` exception on ``NaN`` + * inputs (this even includes ``sNaN``). + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int isgreaterequal(x, y); + * + * Description + * =========== + * + * ``isgreaterequal`` tests whether :math:`x` is greater than or equal to + * :math:`y` without throwing an ``invalid operation`` exception on ``NaN`` + * inputs. Not throwing an exception is the only difference to using a + * relational comparison operator. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * isgreaterequal(x, y) = \left\{\begin{array}{ll} 1, & x \geq y \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``isgreaterequal`` returns :math:`1` if :math:`x \geq y`, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. This includes ``sNaN`` inputs. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+ + * | isgreaterequal(x,y) | x | + * +--------------------------+--------------------------+--------------------------+ + * | y | :math:`\neq NaN` | :math:`NaN` | + * +==========================+==========================+==========================+ + * | :math:`\neq NaN` | :math:`x >= y\ ?\ 1 : 0` | :math:`0` | + * +--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`0` | | + * +--------------------------+--------------------------+--------------------------+ + * + */ diff --git a/libm/libmcs/libm/common/isinf.c b/libm/libmcs/libm/common/isinf.c new file mode 100644 index 00000000..ac2af2a7 --- /dev/null +++ b/libm/libmcs/libm/common/isinf.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is an infinite floating-point value. + * It can be called with ``float``, ``double`` or ``long double`` input. This + * macro is implemented in ``math.h``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int isinf(x); + * + * Description + * =========== + * + * ``isinf`` tests whether the input value is infinite or not. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * isinf(x) = \left\{\begin{array}{ll} 1, & x = \pm Inf \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``isinf`` returns :math:`1` if the input is infinite, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+------------------------------------------------------------------+--------------+-------------+ + * | **x** | :math:`-Inf` | :math:`\in \mathbb{F} \setminus \left \{ \pm Inf, NaN \right \}` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================================================================+==============+=============+ + * | **isinf(x)** | :math:`1` | :math:`0` | :math:`1` | :math:`0` | + * +---------------------+--------------+------------------------------------------------------------------+--------------+-------------+ + * + */ + diff --git a/libm/libmcs/libm/common/isless.c b/libm/libmcs/libm/common/isless.c new file mode 100644 index 00000000..0fa33c27 --- /dev/null +++ b/libm/libmcs/libm/common/isless.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is less than :math:`y` without + * throwing an ``invalid operation`` exception on ``NaN`` inputs (this even + * includes ``sNaN``). + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int isless(x, y); + * + * Description + * =========== + * + * ``isless`` tests whether :math:`x` is less than :math:`y` without throwing + * an ``invalid operation`` exception on ``NaN`` inputs. Not throwing an + * exception is the only difference to using a relational comparison operator. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * isless(x, y) = \left\{\begin{array}{ll} 1, & x < y \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``isless`` returns :math:`1` if :math:`x < y`, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. This includes ``sNaN`` inputs. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+ + * | isless(x,y) | x | + * +--------------------------+--------------------------+--------------------------+ + * | y | :math:`\neq NaN` | :math:`NaN` | + * +==========================+==========================+==========================+ + * | :math:`\neq NaN` | :math:`x < y\ ?\ 1 : 0` | :math:`0` | + * +--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`0` | | + * +--------------------------+--------------------------+--------------------------+ + * + */ diff --git a/libm/libmcs/libm/common/islessequal.c b/libm/libmcs/libm/common/islessequal.c new file mode 100644 index 00000000..63ed3e79 --- /dev/null +++ b/libm/libmcs/libm/common/islessequal.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is less than or equal to :math:`y` + * without throwing an ``invalid operation`` exception on ``NaN`` inputs (this + * even includes ``sNaN``). + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int islessequal(x, y); + * + * Description + * =========== + * + * ``islessequal`` tests whether :math:`x` is less than or equal to :math:`y` + * without throwing an ``invalid operation`` exception on ``NaN`` inputs. Not + * throwing an exception is the only difference to using a relational + * comparison operator. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * islessequal(x, y) = \left\{\begin{array}{ll} 1, & x \leq y \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``islessequal`` returns :math:`1` if :math:`x \leq y`, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. This includes ``sNaN`` inputs. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+ + * | islessequal(x,y) | x | + * +--------------------------+--------------------------+--------------------------+ + * | y | :math:`\neq NaN` | :math:`NaN` | + * +==========================+==========================+==========================+ + * | :math:`\neq NaN` | :math:`x <= y\ ?\ 1 : 0` | :math:`0` | + * +--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`0` | | + * +--------------------------+--------------------------+--------------------------+ + * + */ diff --git a/libm/libmcs/libm/common/islessgreater.c b/libm/libmcs/libm/common/islessgreater.c new file mode 100644 index 00000000..81309800 --- /dev/null +++ b/libm/libmcs/libm/common/islessgreater.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is less than or greater than + * :math:`y` without throwing an ``invalid operation`` exception on ``NaN`` + * inputs (this even includes ``sNaN``). + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int islessgreater(x, y); + * + * Description + * =========== + * + * ``islessgreater`` tests whether :math:`x` is less than or greater than + * :math:`y` without throwing an ``invalid operation`` exception on ``NaN`` + * inputs. Not throwing an exception is the only difference to using a + * relational comparison operator. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * islessgreater(x, y) = \left\{\begin{array}{ll} 1, & x < y \vee x > y \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``islessgreater`` returns :math:`1` if :math:`x < y \vee x > y`, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. This includes ``sNaN`` inputs. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+ + * | islessgreater(x,y) | x | + * +--------------------------+--------------------------+--------------------------+ + * | y | :math:`\neq NaN` | :math:`NaN` | + * +==========================+==========================+==========================+ + * | :math:`\neq NaN` | :math:`x <> y\ ?\ 1 : 0` | :math:`0` | + * +--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`0` | | + * +--------------------------+--------------------------+--------------------------+ + * + */ diff --git a/libm/libmcs/libm/common/isnan.c b/libm/libmcs/libm/common/isnan.c new file mode 100644 index 00000000..29f73288 --- /dev/null +++ b/libm/libmcs/libm/common/isnan.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is a :math:`NaN`. It can be called + * with ``float``, ``double`` or ``long double`` input. This macro is + * implemented in ``math.h``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int isnan(x); + * + * Description + * =========== + * + * ``isnan`` tests whether the input value is a :math:`NaN` or not. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * isnan(x) = \left\{\begin{array}{ll} 1, & x = NaN \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``isnan`` returns :math:`1` if the input is a :math:`NaN`, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+------------------------------------------------------------------+--------------+-------------+ + * | **x** | :math:`-Inf` | :math:`\in \mathbb{F} \setminus \left \{ \pm Inf, NaN \right \}` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================================================================+==============+=============+ + * | **isnan(x)** | :math:`0` | :math:`0` | :math:`0` | :math:`1` | + * +---------------------+--------------+------------------------------------------------------------------+--------------+-------------+ + * + */ + diff --git a/libm/libmcs/libm/common/isnormal.c b/libm/libmcs/libm/common/isnormal.c new file mode 100644 index 00000000..f2565c0f --- /dev/null +++ b/libm/libmcs/libm/common/isnormal.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` is a normal floating-point value. It + * can be called with ``float``, ``double`` or ``long double`` input. This + * macro is implemented in ``math.h``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int isnormal(x); + * + * Description + * =========== + * + * ``isnormal`` tests whether the input value is a normal value or not. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * isnormal(x) = \left\{\begin{array}{ll} 1, & x \in \mathbb{F} \setminus (\left \{ \pm 0.0, \pm Inf, NaN \right \} \cup \mathbb{S}) \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``isnormal`` returns :math:`1` if the input is a normal value, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+---------------------------------------------------------------------------------------------+-----------------+------------------------+--------------+-------------+ + * | **x** | :math:`-Inf` | :math:`\in \mathbb{F} \setminus (\left \{ \pm 0.0, \pm Inf, NaN \right \} \cup \mathbb{S})` | :math:`\pm 0.0` | :math:`\in \mathbb{S}` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=============================================================================================+=================+========================+==============+=============+ + * | **isnormal(x)** | :math:`0` | :math:`1` | :math:`0` | :math:`0` | :math:`0` | :math:`0` | + * +---------------------+--------------+---------------------------------------------------------------------------------------------+-----------------+------------------------+--------------+-------------+ + * + */ + diff --git a/libm/libmcs/libm/common/isunordered.c b/libm/libmcs/libm/common/isunordered.c new file mode 100644 index 00000000..e6df648b --- /dev/null +++ b/libm/libmcs/libm/common/isunordered.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This macro is used to test if :math:`x` or :math:`y` are ``NaN``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int isunordered(x, y); + * + * Description + * =========== + * + * ``isunordered`` tests whether :math:`x` or :math:`y` are ``NaN`` as ``NaN`` + * values are neither less than, greater than, nor equal to another value, and + * as such cannot be ordered. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * isunordered(x, y) = \left\{\begin{array}{ll} 1, & x = \text{NaN} \vee y = \text{NaN} \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``isunordered`` returns :math:`1` if either input is ``NaN``, else :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. This includes ``sNaN`` inputs. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+ + * | isunordered(x,y) | x | + * +--------------------------+--------------------------+--------------------------+ + * | y | :math:`\neq NaN` | :math:`NaN` | + * +==========================+==========================+==========================+ + * | :math:`\neq NaN` | :math:`0` | :math:`1` | + * +--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`1` | | + * +--------------------------+--------------------------+--------------------------+ + * + */ diff --git a/libm/libmcs/libm/common/signgam.c b/libm/libmcs/libm/common/signgam.c new file mode 100644 index 00000000..ea38c7b0 --- /dev/null +++ b/libm/libmcs/libm/common/signgam.c @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This global variable is used to contain the sign of the integral within + * :ref:`lgamma`. Each call to :ref:`lgamma` will update :math:`signgam`. + * + * Note that usage of :math:`signgam` is not thread-safe when calling + * :ref:`lgamma` on multiple threads. + * + * The declaration of the macro :math:`signgam` is in ``math.h``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int signgam; + * + */ + +#include "math.h" + +int __signgam; diff --git a/libm/libmcs/libm/common/tools.c b/libm/libmcs/libm/common/tools.c new file mode 100644 index 00000000..bad606b2 --- /dev/null +++ b/libm/libmcs/libm/common/tools.c @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#include "tools.h" + +const float __inff = 1.0f/0.0f; +const double __infd = 1.0/0.0; diff --git a/libm/libmcs/libm/common/tools.h b/libm/libmcs/libm/common/tools.h new file mode 100644 index 00000000..7b97d700 --- /dev/null +++ b/libm/libmcs/libm/common/tools.h @@ -0,0 +1,449 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This file contains a set of functions used by multiple procedures as + * internal functions. These procedures should not be accessed directly by a + * user. Note that all procedures are either macros or static inline procedures. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include "tools.h" + * EXTRACT_WORDS(ix0,ix1,d); // this macro has no return value, the inputs are expected to be (int, int, double) + * GET_HIGH_WORD(i,d); // this macro has no return value, the inputs are expected to be (int, double) + * GET_LOW_WORD(i,d); // this macro has no return value, the inputs are expected to be (int, double) + * INSERT_WORDS(d,ix0,ix1); // this macro has no return value, the inputs are expected to be (double, int, int) + * SET_HIGH_WORD(d,v); // this macro has no return value, the inputs are expected to be (double, int) + * SET_LOW_WORD(d,v); // this macro has no return value, the inputs are expected to be (double, int) + * GET_FLOAT_WORD(i,d); // this macro has no return value, the inputs are expected to be (int, float) + * SET_FLOAT_WORD(d,i); // this macro has no return value, the inputs are expected to be (float, int) + * SAFE_RIGHT_SHIFT(op,amt); // this macros return value has the same type as input `op`, the inputs are expected to be integer types + * double __forced_calculation(double x); + * float __forced_calculationf(float x); + * double __raise_invalid(void); + * float __raise_invalidf(void); + * double __raise_div_by_zero(double x); + * float __raise_div_by_zerof(float x); + * double __raise_overflow(double x); + * float __raise_overflowf(float x); + * double __raise_underflow(double x); + * float __raise_underflowf(float x); + * double __raise_inexact(double x); + * float __raise_inexactf(float x); + * int __issignaling(double x); + * int __issignalingf(float x); + * REAL_PART(z); // this macros return value has the non-complex type of input `z`, the input is expected to be a complex floating-point datum + * IMAG_PART(z); // this macros return value has the non-complex type of input `z`, the input is expected to be a complex floating-point datum + * + * Description + * =========== + * + * ``EXTRACT_WORDS`` is a macro to extract two integer words from a double + * floating-point datum. + * + * ``GET_HIGH_WORD`` is a macro to extract only the highword of the two integer + * words from a double floating-point datum. + * + * ``GET_LOW_WORD`` is a macro to extract only the lowword of the two integer + * words from a double floating-point datum. + * + * ``INSERT_WORDS`` is a macro to insert two integer words into a double + * floating-point datum. + * + * ``SET_HIGH_WORD`` is a macro to insert only the highword of the two integer + * words into a double floating-point datum. + * + * ``SET_LOW_WORD`` is a macro to insert only the lowword of the two integer + * words into a double floating-point datum. + * + * ``GET_FLOAT_WORD`` is a macro to extract the integer representation from a + * single floating-point datum. + * + * ``SET_FLOAT_WORD`` is a macro to insert the integer representation into a + * single floating-point datum. + * + * ``SAFE_RIGHT_SHIFT`` is a macro to avoid undefined behaviour that can arise + * if the amount of a right shift is exactly equal to the size of the shifted + * operand. If the amount is equal to the size the macro returns 0. + * + * ``__forced_calculation`` is a function to force the execution of the input + * to go through the :ref:`FPU `. The input for this function is usually + * an arithmetic operation and not a single value. At the moment the function + * is only used by others within this file and not expected to be called from + * outside. + * + * ``__raise_invalid`` is a function to force the :ref:`FPU ` to generate + * an ``invalid operation`` exception. + * + * ``__raise_div_by_zero`` is a function to force the :ref:`FPU ` to + * generate an ``divide by zero`` exception. + * + * ``__raise_overflow`` is a function to force the :ref:`FPU ` to + * generate an ``overflow`` exception. + * + * ``__raise_underflow`` is a function to force the :ref:`FPU ` to + * generate an ``underflow`` exception. Even though the library usually does + * not care about this exception for qualification purposes, the library still + * tries to conform to the standards (mainly POSIX) in regards to where the + * exception shall be raised intentionally. In those places this function is + * used. + * + * ``__raise_inexact`` is a function to force the :ref:`FPU ` to generate + * an ``inexact`` exception. Even though the library usually does not care + * about this exception for qualification purposes, the library still tries to + * conform to the standards (mainly POSIX) in regards to where the exception + * shall be raised intentionally. In those places this function is used. + * + * ``__issignaling`` is a function to check if a value is a signaling NaN. + * + * ``REAL_PART`` is a macro to extract only the real part of a complex + * floating-point datum. + * + * ``IMAG_PART`` is a macro to extract only the imaginary part of a complex + * floating-point datum. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * EXTRACT\_WORDS_{ix0}(d) &= \text{highword of } d \\ + * EXTRACT\_WORDS_{ix1}(d) &= \text{lowword of } d \\ + * GET\_HIGH\_WORD_{i}(d) &= \text{highword of } d \\ + * GET\_LOW\_WORD_{i}(d) &= \text{lowword of } d \\ + * SET\_HIGH\_WORD_{\text{highword of } d}(d, v) &= d \text{ with highword } v \\ + * SET\_LOW\_WORD_{\text{lowword of } d}(d, v) &= d \text{ with lowword } v \\ + * GET\_FLOAT\_WORD_{i}(d) &= \text{integer representation of } d \\ + * SET\_FLOAT\_WORD_{d}(i) &= \text{floating-point representation of } i \\ + * SAFE\_RIGHT\_SHIFT(op, amt) &= \left\{\begin{array}{ll} op \gg amt, & amt < \text{size of } op \\ 0, & otherwise \end{array}\right. \\ + * \_\_forced\_calculation(x) &= x \\ + * \_\_raise\_invalid() &= NaN \\ + * \_\_raise\_div\_by\_zero(x) &= \left\{\begin{array}{ll} -Inf, & x \in \mathbb{F}^{-} \\ +Inf, & otherwise \end{array}\right. \\ + * \_\_raise\_overflow(x) &= \left\{\begin{array}{ll} -Inf, & x \in \mathbb{F}^{-} \\ +Inf, & otherwise \end{array}\right. \\ + * \_\_raise\_underflow(x) &= \left\{\begin{array}{ll} -0.0, & x \in \mathbb{F}^{-} \\ +0.0, & otherwise \end{array}\right. \\ + * \_\_raise\_inexact(x) &= x \\ + * \_\_issignaling(x) &= \left\{\begin{array}{ll} 1, & x = sNaN \\ 0, & otherwise \end{array}\right. \\ + * REAL\_PART(z) &= \Re(z) \\ + * IMAG\_PART(z) &= \Im(z) + * + * Returns + * ======= + * + * ``EXTRACT_WORDS`` has no return value. It places the two extracted integer + * words into the parameters ``ix0`` and ``ix1``. + * + * ``GET_HIGH_WORD`` has no return value. It places the extracted integer word + * into the parameter ``i``. + * + * ``GET_LOW_WORD`` has no return value. It places the extracted integer word + * into the parameter ``i``. + * + * ``INSERT_WORDS`` has no return value. It places the created double + * floating-point datum into the parameter ``d``. + * + * ``SET_HIGH_WORD`` has no return value. It places the created double + * floating-point datum into the parameter ``d``. + * + * ``SET_LOW_WORD`` has no return value. It places the created double + * floating-point datum into the parameter ``d``. + * + * ``GET_FLOAT_WORD`` has no return value. It places the extracted integer word + * into the parameter ``i``. + * + * ``SET_FLOAT_WORD`` has no return value. It places the created single + * floating-point datum into the parameter ``d``. + * + * ``SAFE_RIGHT_SHIFT`` returns the value ``op`` right shifted by ``amt`` if + * ``amt`` is smaller than the size of ``op``, otherwise it returns zero. + * + * ``__forced_calculation`` returns the input value, or rather the result of + * the arithmetic calculation used as an input. + * + * ``__raise_invalid`` returns ``NaN``. + * + * ``__raise_div_by_zero`` returns ``-Inf`` for negative inputs and ``+Inf`` + * for positive inputs. + * + * ``__raise_overflow`` returns ``-Inf`` for negative inputs and ``+Inf`` for + * positive inputs. + * + * ``__raise_underflow`` returns ``-0.0`` for negative inputs and ``+0.0`` for + * positive inputs. + * + * ``__raise_inexact`` returns the input value. + * + * ``__issignaling`` returns ``1`` if the input value is a signaling ``NaN``, + * else ``0``. + * + * ``REAL_PART`` returns the real part of the input as a floating-point datum + * of the adequate size. + * + * ``IMAG_PART`` returns the imaginary part of the input as a floating-point + * datum of the adequate size. + * + * Exceptions + * ========== + * + * The macros do not raise exceptions. + * + * The functions raise the exceptions they are named after, it is their sole + * purpose. Additionally the procedures ``__raise_overflow`` and + * ``__raise_underflow`` may raise ``inexact``. + * + */ + +#ifndef LIBMCS_TOOLS_H +#define LIBMCS_TOOLS_H + +#include +#include +#include + +#include + +#ifdef __LIBMCS_WANT_COMPLEX + #include +#endif /* __LIBMCS_WANT_COMPLEX */ + +/* 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 == 1) + +/* 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 == 1) + +/* 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 == 1) + +/* 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 == 1) + +/* 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 == 1) + +/* 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 == 1) + +/* 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 == 1) + +/* 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 == 1) + +/* Macros to avoid undefined behaviour that can arise if the amount + of a shift is exactly equal to the size of the shifted operand. */ + +#define SAFE_RIGHT_SHIFT(op,amt) \ + (((amt) < 8 * sizeof(op)) ? ((op) >> (amt)) : 0) + +/* Exception raising and signaling check functions */ + +static inline double __forced_calculation(double x); +static inline float __forced_calculationf(float x); + +static inline double __raise_invalid(void); +static inline double __raise_div_by_zero(double x); +static inline double __raise_overflow(double x); +static inline double __raise_underflow(double x); +static inline double __raise_inexact(double x); + +static inline float __raise_invalidf(void); +static inline float __raise_div_by_zerof(float x); +static inline float __raise_overflowf(float x); +static inline float __raise_underflowf(float x); +static inline float __raise_inexactf(float x); + +static inline int __issignaling(double x); +static inline int __issignalingf(float x); + + +static inline double __forced_calculation(double x) { + volatile double r = x; + return r; +} +static inline float __forced_calculationf(float x) { + volatile float r = x; + return r; +} + +static inline double __raise_invalid(void) { + double r = __forced_calculation(0.0 / 0.0); + return r; +} +static inline double __raise_div_by_zero(double x) { + return (signbit(x) != 0) ? __forced_calculation(-1.0 / 0.0) : __forced_calculation(1.0 / 0.0); +} +static inline double __raise_overflow(double x) { + volatile double huge = 1.0e300; + return (signbit(x) != 0) ? -__forced_calculation(huge * huge) : __forced_calculation(huge * huge); +} +static inline double __raise_underflow(double x) { + volatile double tiny = 1.0e-300; + return (signbit(x) != 0) ? -__forced_calculation(tiny * tiny) : __forced_calculation(tiny * tiny); +} +static inline double __raise_inexact(double x) { + volatile double huge = 1.0e300; + return (__forced_calculation(huge - 1.0e-300) != 0.0) ? x : 0.0; +} +static inline float __raise_invalidf(void) { + float r = __forced_calculationf(0.0f / 0.0f); + return r; +} +static inline float __raise_div_by_zerof(float x) { + return (signbit(x) != 0) ? __forced_calculationf(-1.0f / 0.0f) : __forced_calculationf(1.0f / 0.0f); +} +static inline float __raise_overflowf(float x) { + volatile float huge = 1.0e30f; + return (signbit(x) != 0) ? -__forced_calculationf(huge * huge) : __forced_calculationf(huge * huge); +} +static inline float __raise_underflowf(float x) { + volatile float tiny = 1.0e-30f; + return (signbit(x) != 0) ? -__forced_calculationf(tiny * tiny) : __forced_calculationf(tiny * tiny); +} +static inline float __raise_inexactf(float x) { + volatile float huge = 1.0e30f; + return (__forced_calculationf(huge - 1.0e-30f) != 0.0f) ? x : 0.0f; +} + +static inline int __issignaling(double x) { + uint32_t hx; + GET_HIGH_WORD(hx, x); + if (isnan(x) && (hx & 0x00080000U) == 0) { + return 1; + } + else { + return 0; + } +} +static inline int __issignalingf(float x) { + uint32_t ix; + GET_FLOAT_WORD(ix, x); + if (FLT_UWORD_IS_NAN(ix & 0x7fffffffU) && (ix & 0x00400000U) == 0) { + return 1; + } + else { + return 0; + } +} + +#ifdef __LIBMCS_WANT_COMPLEX + /* + * Quoting from ISO/IEC 9899:TC2: + * + * 6.2.5.13 Types + * Each complex type has the same representation and alignment requirements as + * an array type containing exactly two elements of the corresponding real type; + * the first element is equal to the real part, and the second element to the + * imaginary part, of the complex number. + */ + typedef union { + float complex z; + float parts[2]; + } float_complex; + + typedef union { + double complex z; + double parts[2]; + } double_complex; + + typedef union { + long double complex z; + long double parts[2]; + } long_double_complex; + + #define REAL_PART(z) ((z).parts[0]) + #define IMAG_PART(z) ((z).parts[1]) + +#endif /* __LIBMCS_WANT_COMPLEX */ + +#endif /* !LIBMCS_TOOLS_H */ diff --git a/libm/libmcs/libm/complexd/cabsd.c b/libm/libmcs/libm/complexd/cabsd.c new file mode 100644 index 00000000..86c89288 --- /dev/null +++ b/libm/libmcs/libm/complexd/cabsd.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +/** + * + * This family of functions implements the absolute value ot the complex + * argument :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float cabsf(float z); + * double cabs(double z); + * long double cabsl(long double z); + * + * Description + * =========== + * + * ``cabs`` computes the absolute value (also called norm, modulus, or + * magnitude) of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cabs(z) \approx |z| + * + * Returns + * ======= + * + * ``cabs`` returns the absolute value of :math:`z`. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double cabs(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return hypot(creal(z), cimag(z)); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double cabsl(long double complex z) +{ + return (long double) cabs((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/cacosd.c b/libm/libmcs/libm/complexd/cacosd.c new file mode 100644 index 00000000..47b86ed1 --- /dev/null +++ b/libm/libmcs/libm/complexd/cacosd.c @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex arc cosine of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex cacosf(float complex z); + * double complex cacos(double complex z); + * long double complex cacosl(long double complex z); + * + * Description + * =========== + * + * ``cacos`` computes the complex inverse cosine (*arc cosine*) of the input + * value, with branch cuts outside the interval :math:`[-1, +1]` along the real + * axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cacos(z) \approx cos^{-1}(z) + * + * Returns + * ======= + * + * ``cacos`` returns the complex inverse cosine of the input value in the + * output range of a strip mathematically unbounded along the imaginary axis + * and in the interval :math:`[0, \pi]` radians along the real axis. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex cacos(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double complex tmp0; + double tmp1; + + tmp0 = casin(z); + tmp1 = M_PI_2 - creal(tmp0); + /* w = tmp1 - (cimag(tmp0) * I); */ + w = CMPLX(tmp1, -cimag(tmp0)); + + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex cacosl(long double complex z) +{ + return (long double complex) cacos((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/cacoshd.c b/libm/libmcs/libm/complexd/cacoshd.c new file mode 100644 index 00000000..c83643ac --- /dev/null +++ b/libm/libmcs/libm/complexd/cacoshd.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex hyperbolic arc cosine of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex cacoshf(float complex z); + * double complex cacosh(double complex z); + * long double complex cacoshl(long double complex z); + * + * Description + * =========== + * + * ``cacosh`` computes the complex hyperbolic inverse cosine (*arc cosine*) of + * the input value, with a branch cut at values less than :math:`+1` along the + * real axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cacosh(z) \approx cosh^{-1}(z) + * + * Returns + * ======= + * + * ``cacosh`` returns the complex hyperbolic inverse cosine of the input value + * in the output range of a half-strip of non-negative values along the real + * axis and in the interval :math:`[-\pi i, +\pi i]` along the imaginary axis. + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex cacosh(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + + w = clog(z + csqrt(z + 1) * csqrt(z - 1)); + + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex cacoshl(long double complex z) +{ + return (long double complex) cacosh((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/cargd.c b/libm/libmcs/libm/complexd/cargd.c new file mode 100644 index 00000000..c1c76f4f --- /dev/null +++ b/libm/libmcs/libm/complexd/cargd.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +/** + * + * This family of functions implements the argument of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float cargf(float complex z); + * double carg(double complex z); + * long double cargl(long double complex z); + * + * Description + * =========== + * + * ``carg`` computes the argument (also called phase angle) of the input value, + * with a branch cut along the negative real axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * carg(z) \approx \varphi (z) = \tan^{-1} \frac{\Im(z)}{\Re(z)} + * + * Returns + * ======= + * + * ``carg`` returns the argument of the input value in the interval + * :math:`[-\pi, \pi]`. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double carg(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return atan2(cimag(z), creal(z)); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double cargl(long double complex z) +{ + return (long double) carg((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/casind.c b/libm/libmcs/libm/complexd/casind.c new file mode 100644 index 00000000..b0a62e48 --- /dev/null +++ b/libm/libmcs/libm/complexd/casind.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex arc sine of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex casinf(float complex z); + * double complex casin(double complex z); + * long double complex casinl(long double complex z); + * + * Description + * =========== + * + * ``casin`` computes the complex inverse sine (*arc sine*) of the input value, + * with branch cuts outside the interval :math:`[-1, +1]` along the real axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * casin(z) \approx sin^{-1}(z) + * + * Returns + * ======= + * + * ``casin`` returns the complex inverse sine of the input value in the output + * range of a strip mathematically unbounded along the imaginary axis and in + * the interval :math:`[-\frac{\pi}{2}, \frac{\pi}{2}]` radians along the real + * axis. + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex casin(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double complex ct, zz, z2; + double x, y; + + x = creal(z); + y = cimag(z); + + ct = CMPLX(-y, x); + /* zz = (x - y) * (x + y) + (2.0 * x * y) * I; */ + zz = CMPLX((x - y) * (x + y), 2.0 * x * y); + + /* zz = 1.0 - creal(zz) - cimag(zz) * I; */ + zz = CMPLX(1.0 - creal(zz), -cimag(zz)); + z2 = csqrt(zz); + + zz = ct + z2; + zz = clog(zz); + /* w = zz * (-1.0 * I); */ + w = CMPLX(cimag(zz), -creal(zz)); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex casinl(long double complex z) +{ + return (long double complex) casin((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/casinhd.c b/libm/libmcs/libm/complexd/casinhd.c new file mode 100644 index 00000000..bb6f6595 --- /dev/null +++ b/libm/libmcs/libm/complexd/casinhd.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex hyperbolic arc sine of + * :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex casinhf(float complex z); + * double complex casinh(double complex z); + * long double complex casinhl(long double complex z); + * + * Description + * =========== + * + * ``casinh`` computes the complex hyperbolic inverse sine (*arc sine*) of the + * input value, with branch cuts outside the interval :math:`[-i, +i]` along + * the imaginary axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * casinh(z) \approx sinh^{-1}(z) + * + * Returns + * ======= + * + * ``casinh`` returns the complex hyperbolic inverse sine of the input value in + * the output range of a strip mathematically unbounded along the real axis and + * in the interval :math:`[-\frac{\pi}{2}i, \frac{\pi}{2}i]` along the + * imaginary axis. + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex casinh(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double complex tmp; + + /* w = -1.0 * I * casin(z * I); */ + tmp = CMPLX(-cimag(z), creal(z)); + tmp = casin(tmp); + w = CMPLX(cimag(tmp), -creal(tmp)); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex casinhl(long double complex z) +{ + return (long double complex) casinh((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/catand.c b/libm/libmcs/libm/complexd/catand.c new file mode 100644 index 00000000..f2f00c90 --- /dev/null +++ b/libm/libmcs/libm/complexd/catand.c @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex arc tangent of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex catanf(float complex z); + * double complex catan(double complex z); + * long double complex catanl(long double complex z); + * + * Description + * =========== + * + * ``catan`` computes the complex inverse tangent (*arc tangent*) of the input + * value, with branch cuts outside the interval :math:`[-i, +i]` along the + * imaginary axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * catan(z) \approx tan^{-1}(z) + * + * Returns + * ======= + * + * ``catan`` returns the complex inverse tangent of the input value in the + * output range of a strip mathematically unbounded along the imaginary axis + * and in the interval :math:`[-\frac{\pi}{2}, \frac{\pi}{2}]` radians along + * the real axis. + * + */ + +#include +#include +#include "internal/ctrigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex catan(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double a, t, x, x2, y, tmp; + + x = creal(z); + y = cimag(z); + + if ((x == 0.0) && (y > 1.0)) { + goto ovrf; + } + + x2 = x * x; + a = 1.0 - x2 - (y * y); + + t = 0.5 * atan2(2.0 * x, a); + tmp = __redupi(t); + + t = y - 1.0; + a = x2 + (t * t); + + t = y + 1.0; + a = (x2 + (t * t)) / a; + /* w = tmp + (0.25 * log(a)) * I; */ + w = CMPLX(tmp, 0.25 * log(a)); + return w; + +ovrf: + w = CMPLX(HUGE_VAL, HUGE_VAL); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex catanl(long double complex z) +{ + return (long double complex) catan((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/catanhd.c b/libm/libmcs/libm/complexd/catanhd.c new file mode 100644 index 00000000..a2dce220 --- /dev/null +++ b/libm/libmcs/libm/complexd/catanhd.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex hyperbolic arc tangent of + * :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex catanhf(float complex z); + * double complex catanh(double complex z); + * long double complex catanhl(long double complex z); + * + * Description + * =========== + * + * ``catanh`` computes the complex hyperbolic inverse tangent (*arc tangent*) + * of the input value, with branch cuts outside the interval :math:`[-1, +1]` + * along the real axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * catanh(z) \approx tanh^{-1}(z) + * + * Returns + * ======= + * + * ``catanh`` returns the complex hyperbolic inverse tangent of the input value + * in the output range of a strip mathematically unbounded along the real axis + * and in the interval :math:`[-\frac{\pi}{2}i, \frac{\pi}{2}i]` along the + * imaginary axis. + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex catanh(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double complex tmp; + + /* w = -1.0 * I * catan(z * I) */ + tmp = CMPLX(-cimag(z), creal(z)); + tmp = catan(tmp); + w = CMPLX(cimag(tmp), -creal(tmp)); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex catanhl(long double complex z) +{ + return (long double complex) catanh((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/ccosd.c b/libm/libmcs/libm/complexd/ccosd.c new file mode 100644 index 00000000..de0116a3 --- /dev/null +++ b/libm/libmcs/libm/complexd/ccosd.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex cosine of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex ccosf(float complex z); + * double complex ccos(double complex z); + * long double complex ccosl(long double complex z); + * + * Description + * =========== + * + * ``ccos`` computes the complex cosine of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * ccos(z) \approx cos(z) + * + * Returns + * ======= + * + * ``ccos`` returns the complex cosine of the input value. + * + */ + +#include +#include +#include "internal/ctrigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex ccos(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double ch, sh; + + __ccoshsinh(cimag(z), &ch, &sh); + /* w = cos(creal(z)) * ch - (sin(creal(z)) * sh) * I; */ + w = CMPLX(cos(creal(z)) * ch, -(sin(creal(z)) * sh)); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex ccosl(long double complex z) +{ + return (long double complex) ccos((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/ccoshd.c b/libm/libmcs/libm/complexd/ccoshd.c new file mode 100644 index 00000000..ed6f61f7 --- /dev/null +++ b/libm/libmcs/libm/complexd/ccoshd.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex hyperbolic cosine of + * :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex ccoshf(float complex z); + * double complex ccosh(double complex z); + * long double complex ccoshl(long double complex z); + * + * Description + * =========== + * + * ``ccosh`` computes the complex hyperbolic cosine of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * ccosh(z) \approx cosh(z) + * + * Returns + * ======= + * + * ``ccosh`` returns the complex hyperbolic cosine of the input value. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex ccosh(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double x, y; + + x = creal(z); + y = cimag(z); + /* w = cosh(x) * cos(y) + (sinh(x) * sin(y)) * I; */ + w = CMPLX(cosh(x) * cos(y), sinh(x) * sin(y)); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex ccoshl(long double complex z) +{ + return (long double complex) ccosh((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/cexpd.c b/libm/libmcs/libm/complexd/cexpd.c new file mode 100644 index 00000000..102dbf38 --- /dev/null +++ b/libm/libmcs/libm/complexd/cexpd.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex exponential function, that + * is :math:`e` powered by :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex cexpf(float z); + * double complex cexp(double z); + * long double complex cexpl(long double z); + * + * Description + * =========== + * + * ``cexp`` computes :math:`e` powered by the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cexp(z) \approx e^z + * + * Returns + * ======= + * + * ``cexp`` returns :math:`e` powered by :math:`z`. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex cexp(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double r, x, y; + + x = creal(z); + y = cimag(z); + r = exp(x); + /* w = r * cos(y) + r * sin(y) * I; */ + w = CMPLX(r * cos(y), r * sin(y)); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex cexpl(long double complex z) +{ + return (long double complex) cexp((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/cimagd.c b/libm/libmcs/libm/complexd/cimagd.c new file mode 100644 index 00000000..10400a30 --- /dev/null +++ b/libm/libmcs/libm/complexd/cimagd.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +/** + * + * This family of functions returns the imaginary part of :math:`z` as a real. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float cimagf(float complex z); + * double cimag(double complex z); + * long double cimagl(long double complex z); + * + * Description + * =========== + * + * ``cimag`` computes the imaginary part of :math:`z` as a real. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cimag(z) = \Im(z) + * + * Returns + * ======= + * + * ``cimag`` returns the imaginary part of :math:`z` as a real. + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double cimag(double complex z) +{ + double_complex w; + w.z = z; + + return (IMAG_PART(w)); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double cimagl(long double complex z) +{ + return (long double) cimag((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/clogd.c b/libm/libmcs/libm/complexd/clogd.c new file mode 100644 index 00000000..739bacaa --- /dev/null +++ b/libm/libmcs/libm/complexd/clogd.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex natural logarithm function, + * that is :math:`ln(z)`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex clogf(float z); + * double complex clog(double z); + * long double complex clogl(long double z); + * + * Description + * =========== + * + * ``clog`` computes the complex natural logarithm of :math:`z`, with a branch + * cut along the negative real axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * clog(z) \approx ln(z) + * + * Returns + * ======= + * + * ``clog`` returns the complex natural logarithm of the input value in the + * output range of a strip mathematically unbounded along the real axis and in + * the interval :math:`[-\pi i, \pi i]` along the imaginary axis. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex clog(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double p, rr; + + rr = cabs(z); + p = log(rr); + rr = atan2(cimag(z), creal(z)); + /* w = p + rr * I; */ + w = CMPLX(p, rr); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex clogl(long double complex z) +{ + return (long double complex) clog((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/conjd.c b/libm/libmcs/libm/complexd/conjd.c new file mode 100644 index 00000000..29877a65 --- /dev/null +++ b/libm/libmcs/libm/complexd/conjd.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +/** + * + * This family of functions evaluates the complex conjugate of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex conjf(float complex z); + * double complex conj(double complex z); + * long double complex conjl(long double complex z); + * + * Description + * =========== + * + * ``conj`` computes the complex conjugate of :math:`z`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * conj(z) = \Re(z) - \Im(z) \cdot i + * + * Returns + * ======= + * + * ``conj`` returns the complex conjugate of :math:`z`. + * + */ + +/* +FUNCTION + <>, <>---complex conjugate + +INDEX + conj +INDEX + conjf + +SYNOPSIS + #include + double complex conj(double complex <[z]>); + float complex conjf(float complex <[z]>); + + +DESCRIPTION + These functions compute the complex conjugate of <[z]>, + by reversing the sign of its imaginary part. + + <> is identical to <>, except that it performs + its calculations on <>. + +RETURNS + The conj functions return the complex conjugate value. + +PORTABILITY + <> and <> are ISO C99 + +QUICKREF + <> and <> are ISO C99 + +*/ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex conj(double complex z) +{ + double_complex w = { .z = z }; + + IMAG_PART(w) = -IMAG_PART(w); + + return (w.z); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex conjl(long double complex z) +{ + return (long double complex) conj((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/cpowd.c b/libm/libmcs/libm/complexd/cpowd.c new file mode 100644 index 00000000..63a15d6d --- /dev/null +++ b/libm/libmcs/libm/complexd/cpowd.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the value of complex :math:`x` raised to + * the power of complex :math:`y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex cpowf(float complex x, float complex y); + * double complex cpow(double complex x, double complex y); + * long double complex cpowl(long double complex x, long double complex y); + * + * Description + * =========== + * + * ``cpow`` computes the value of complex :math:`x` raised to the power of + * complex :math:`y`, with a branch cut for the first parameter along the + * negative real axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cpow(x, y) \approx x^y + * + * Returns + * ======= + * + * ``cpow`` returns the value of complex :math:`x` raised to the power of + * complex :math:`y`. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex cpow(double complex x, double complex y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double realz, imagz, result, theta, absx, argx; + + realz = creal(y); + imagz = cimag(y); + absx = cabs(x); + + if (absx == 0.0) { + return CMPLX(0.0, 0.0); + } + + argx = carg(x); + result = pow(absx, realz); + theta = realz * argx; + + if (imagz != 0.0) { + result = result * exp(-imagz * argx); + theta = theta + imagz * log(absx); + } + + /* w = result * cos(theta) + (result * sin(theta)) * I; */ + w = CMPLX(result * cos(theta), result * sin(theta)); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex cpowl(long double complex x, long double complex y) +{ + return (long double complex) cpow((double complex) x, (double complex) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/cprojd.c b/libm/libmcs/libm/complexd/cprojd.c new file mode 100644 index 00000000..cb9aa153 --- /dev/null +++ b/libm/libmcs/libm/complexd/cprojd.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions evaluates the value of the projection of the + * complex argument :math:`z` onto the Riemann sphere. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex cprojf(float complex z); + * double complex cproj(double complex z); + * long double complex cprojl(long double complex z); + * + * Description + * =========== + * + * ``cproj`` computes the value of the projection of :math:`z` onto the Riemann + * sphere. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cproj(z) = \left\{\begin{array}{ll} z, & \Re(z) \neq \pm Inf \wedge \Im(z) \neq \pm Inf \\ +Inf \pm 0i, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``cproj`` returns the value of the projection of :math:`z` onto the Riemann + * sphere. + * + */ + +#include +#include + +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +/* + * cproj(double complex z) + * + * These functions return the value of the projection (not stereographic!) + * onto the Riemann sphere. + * + * z projects to z, except that all complex infinities (even those with one + * infinite part and one NaN part) project to positive infinity on the real axis. + * If z has an infinite part, then cproj(z) shall be equivalent to: + * + * INFINITY + I * copysign(0.0, cimag(z)) + */ +double complex cproj(double complex z) +{ + double_complex w = { .z = z }; + + if (isinf(REAL_PART(w)) || isinf(IMAG_PART(w))) { + REAL_PART(w) = INFINITY; + IMAG_PART(w) = copysign(0.0, cimag(z)); + } + + return (w.z); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex cprojl(long double complex z) +{ + return (long double complex) cproj((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/creald.c b/libm/libmcs/libm/complexd/creald.c new file mode 100644 index 00000000..de49cfc3 --- /dev/null +++ b/libm/libmcs/libm/complexd/creald.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +/** + * + * This family of functions returns the real part of :math:`z` as a real. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float crealf(float complex z); + * double creal(double complex z); + * long double creall(long double complex z); + * + * Description + * =========== + * + * ``creal`` computes the real part of :math:`z` as a real. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * creal(z) = \Re(z) + * + * Returns + * ======= + * + * ``creal`` returns the real part of :math:`z` as a real. + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double creal(double complex z) +{ + double_complex w; + w.z = z; + + return (REAL_PART(w)); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double creall(long double complex z) +{ + return (long double) creal((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/csind.c b/libm/libmcs/libm/complexd/csind.c new file mode 100644 index 00000000..c1f799c1 --- /dev/null +++ b/libm/libmcs/libm/complexd/csind.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex sine of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex csinf(float complex z); + * double complex csin(double complex z); + * long double complex csinl(long double complex z); + * + * Description + * =========== + * + * ``csin`` computes the complex sine of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * csin(z) \approx sin(z) + * + * Returns + * ======= + * + * ``csin`` returns the complex sine of the input value. + * + */ + +#include +#include +#include "internal/ctrigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex csin(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double ch, sh; + + __ccoshsinh(cimag(z), &ch, &sh); + /* w = sin(creal(z)) * ch + (cos(creal(z)) * sh) * I; */ + w = CMPLX(sin(creal(z)) * ch, cos(creal(z)) * sh); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex csinl(long double complex z) +{ + return (long double complex) csin((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/csinhd.c b/libm/libmcs/libm/complexd/csinhd.c new file mode 100644 index 00000000..1c2ae076 --- /dev/null +++ b/libm/libmcs/libm/complexd/csinhd.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex hyperbolic sine of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex csinhf(float complex z); + * double complex csinh(double complex z); + * long double complex csinhl(long double complex z); + * + * Description + * =========== + * + * ``csinh`` computes the complex hyperbolic sine of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * csinh(z) \approx sinh(z) + * + * Returns + * ======= + * + * ``csinh`` returns the complex hyperbolic sine of the input value. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex csinh(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double x, y; + + x = creal(z); + y = cimag(z); + /* w = sinh(x) * cos(y) + (cosh(x) * sin(y)) * I; */ + w = CMPLX(sinh(x) * cos(y), cosh(x) * sin(y)); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex csinhl(long double complex z) +{ + return (long double complex) csinh((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/csqrtd.c b/libm/libmcs/libm/complexd/csqrtd.c new file mode 100644 index 00000000..0f0865bd --- /dev/null +++ b/libm/libmcs/libm/complexd/csqrtd.c @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex square root of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex csqrtf(float complex z); + * double complex csqrt(double complex z); + * long double complex csqrtl(long double complex z); + * + * Description + * =========== + * + * ``csqrt`` computes the complex square root of the input value, with a branch + * cut along the negative real axis. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * csqrt(z) \approx \sqrt{z} + * + * Returns + * ======= + * + * ``csqrt`` returns the complex square root of the input value, in the range + * of the right halfplane (including the imaginary axis). + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex csqrt(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double x, y, r, t, scale; + + x = creal(z); + y = cimag(z); + + if (y == 0.0) { + if (x == 0.0) { + w = CMPLX(0.0, y); + } else { + r = fabs(x); + r = sqrt(r); + + if (x < 0.0) { + w = CMPLX(0.0, r); + } else { + w = CMPLX(r, y); + } + } + + return w; + } + + if (x == 0.0) { + r = fabs(y); + r = sqrt(0.5 * r); + + if (y > 0) { + w = CMPLX(r, r); + } else { + w = CMPLX(r, -r); + } + + return w; + } + + /* Rescale to avoid internal overflow or underflow. */ + if ((fabs(x) > 4.0) || (fabs(y) > 4.0)) { + x *= 0.25; + y *= 0.25; + scale = 2.0; + } else { + x *= 1.8014398509481984e16; /* 2^54 */ + y *= 1.8014398509481984e16; + scale = 7.450580596923828125e-9; /* 2^-27 */ + } + + w = CMPLX(x, y); + r = cabs(w); + + if (x > 0) { + t = sqrt(0.5 * r + 0.5 * x); + r = scale * fabs((0.5 * y) / t); + t *= scale; + } else { + r = sqrt(0.5 * r - 0.5 * x); + t = scale * fabs((0.5 * y) / r); + r *= scale; + } + + if (y < 0) { + w = CMPLX(t, -r); + } else { + w = CMPLX(t, r); + } + + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex csqrtl(long double complex z) +{ + return (long double complex) csqrt((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/ctand.c b/libm/libmcs/libm/complexd/ctand.c new file mode 100644 index 00000000..3590645d --- /dev/null +++ b/libm/libmcs/libm/complexd/ctand.c @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex tangent of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex ctanf(float complex z); + * double complex ctan(double complex z); + * long double complex ctanl(long double complex z); + * + * Description + * =========== + * + * ``ctan`` computes the complex tangent of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * ctan(z) \approx tan(z) + * + * Returns + * ======= + * + * ``ctan`` returns the complex tangent of the input value. + * + */ + +#include +#include +#include "internal/ctrigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +/* Taylor series expansion for cosh(2y) - cos(2x) */ + +static inline double __ctans(double complex z) +{ + double f, x, x2, y, y2, rn, t; + double d; + + x = fabs(2.0 * creal(z)); + y = fabs(2.0 * cimag(z)); + + x = __redupi(x); + + x = x * x; + y = y * y; + x2 = 1.0; + y2 = 1.0; + f = 1.0; + rn = 0.0; + d = 0.0; + + do { + rn += 1.0; + f *= rn; + rn += 1.0; + f *= rn; + x2 *= x; + y2 *= y; + t = y2 + x2; + t /= f; + d += t; + + rn += 1.0; + f *= rn; + rn += 1.0; + f *= rn; + x2 *= x; + y2 *= y; + t = y2 - x2; + t /= f; + d += t; + } while (fabs(t / d) > MACHEP); + + return d; +} + +double complex ctan(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double d; + + d = cos(2.0 * creal(z)) + cosh(2.0 * cimag(z)); + + if (fabs(d) < 0.25) { + d = __ctans(z); + } + + if (d == 0.0) { + w = CMPLX(HUGE_VAL, HUGE_VAL); + return w; + } + + /* w = sin(2.0 * creal(z)) / d + (sinh(2.0 * cimag(z)) / d) * I; */ + w = CMPLX(sin(2.0 * creal(z)) / d, sinh(2.0 * cimag(z)) / d); + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex ctanl(long double complex z) +{ + return (long double complex) ctan((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/ctanhd.c b/libm/libmcs/libm/complexd/ctanhd.c new file mode 100644 index 00000000..5f9cd3ce --- /dev/null +++ b/libm/libmcs/libm/complexd/ctanhd.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: NetBSD */ + +/** + * + * This family of functions implements the complex hyperbolic tangent of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float complex ctanhf(float complex z); + * double complex ctanh(double complex z); + * long double complex ctanhl(long double complex z); + * + * Description + * =========== + * + * ``ctanh`` computes the complex hyperbolic tangent of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * ctanh(z) \approx tanh(z) + * + * Returns + * ======= + * + * ``ctanh`` returns the complex hyperbolic tangent of the input value. + * + */ + +#include +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double complex ctanh(double complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double complex w; + double x, y, d; + + x = creal(z); + y = cimag(z); + d = cosh(2.0 * x) + cos(2.0 * y); + /* w = sinh(2.0 * x) / d + (sin(2.0 * y) / d) * I; */ + w = CMPLX(sinh(2.0 * x) / d, sin(2.0 * y) / d); + + return w; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double complex ctanhl(long double complex z) +{ + return (long double complex) ctanh((double complex) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/internal/ctrigd.c b/libm/libmcs/libm/complexd/internal/ctrigd.c new file mode 100644 index 00000000..db08cdc8 --- /dev/null +++ b/libm/libmcs/libm/complexd/internal/ctrigd.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +#include "ctrigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +/* calculate cosh and sinh */ + +void __ccoshsinh(double x, double *c, double *s) +{ + double e, ei; + + if (fabs(x) <= 0.5) { + *c = cosh(x); + *s = sinh(x); + } else { + e = exp(x); + if (__fpclassifyd(e) != FP_ZERO) { + ei = 0.5 / e; + } else { + ei = HUGE_VAL; + } + e = 0.5 * e; + *s = e - ei; + *c = e + ei; + } +} + +/* Program to subtract nearest integer multiple of PI */ + +/* extended precision value of PI: */ +static const double DP1 = 3.14159265160560607910E0; +static const double DP2 = 1.98418714791870343106E-9; +static const double DP3 = 1.14423774522196636802E-17; + +double __redupi(double x) +{ + double t; + long i; + + t = x / M_PI; + + if (t >= 0.0) { + t += 0.5; + } else { + t -= 0.5; + } + + i = t; /* the multiple */ + t = i; + t = ((x - t * DP1) - t * DP2) - t * DP3; + return t; +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexd/internal/ctrigd.h b/libm/libmcs/libm/complexd/internal/ctrigd.h new file mode 100644 index 00000000..cf3180ad --- /dev/null +++ b/libm/libmcs/libm/complexd/internal/ctrigd.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_CTRIGD_H +#define LIBMCS_CTRIGD_H + +#define MACHEP 1.1e-16 + +extern void __ccoshsinh(double x, double *c, double *s); +extern double __redupi(double x); + +#endif /* !LIBMCS_CTRIGD_H */ diff --git a/libm/libmcs/libm/complexf/cabsf.c b/libm/libmcs/libm/complexf/cabsf.c new file mode 100644 index 00000000..1f3eccc6 --- /dev/null +++ b/libm/libmcs/libm/complexf/cabsf.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +#include +#include + +float cabsf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return hypotf(crealf(z), cimagf(z)); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double cabs(double complex z) +{ + return (double) cabsf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/cacosf.c b/libm/libmcs/libm/complexf/cacosf.c new file mode 100644 index 00000000..ca1a3234 --- /dev/null +++ b/libm/libmcs/libm/complexf/cacosf.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +float complex cacosf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float complex tmp0; + float tmp1; + + tmp0 = casinf(z); + tmp1 = (float)M_PI_2 - crealf(tmp0); + w = CMPLXF(tmp1, -cimagf(tmp0)); + + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex cacos(double complex z) +{ + return (double complex) cacosf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/cacoshf.c b/libm/libmcs/libm/complexf/cacoshf.c new file mode 100644 index 00000000..de5febae --- /dev/null +++ b/libm/libmcs/libm/complexf/cacoshf.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include + +float complex cacoshf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + + w = clogf(z + csqrtf(z + 1) * csqrtf(z - 1)); + + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex cacosh(double complex z) +{ + return (double complex) cacoshf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/cargf.c b/libm/libmcs/libm/complexf/cargf.c new file mode 100644 index 00000000..b4260015 --- /dev/null +++ b/libm/libmcs/libm/complexf/cargf.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +#include +#include + +float cargf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return atan2f(cimagf(z), crealf(z)); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double carg(double complex z) +{ + return (double) cargf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/casinf.c b/libm/libmcs/libm/complexf/casinf.c new file mode 100644 index 00000000..a38b9481 --- /dev/null +++ b/libm/libmcs/libm/complexf/casinf.c @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include + +float complex casinf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float complex ct, zz, z2; + float x, y; + + x = crealf(z); + y = cimagf(z); + + ct = CMPLXF(-y, x); + /* zz = (x - y) * (x + y) + (2.0f * x * y) * I; */ + zz = CMPLXF((x - y) * (x + y), 2.0f * x * y); + + /* zz = 1.0f - crealf(zz) - cimagf(zz) * I; */ + zz = CMPLXF(1.0f - crealf(zz), -cimagf(zz)); + z2 = csqrtf(zz); + + zz = ct + z2; + zz = clogf(zz); + /* w = zz * (-1.0f * I); */ + w = CMPLXF(cimagf(zz), -crealf(zz)); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex casin(double complex z) +{ + return (double complex) casinf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/casinhf.c b/libm/libmcs/libm/complexf/casinhf.c new file mode 100644 index 00000000..d827b3fc --- /dev/null +++ b/libm/libmcs/libm/complexf/casinhf.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include + +float complex casinhf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float complex tmp; + + /* w = -1.0f * I * casinf(z * I); */ + tmp = CMPLXF(-cimagf(z), crealf(z)); + tmp = casinf(tmp); + w = CMPLXF(cimagf(tmp), -crealf(tmp)); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex casinh(double complex z) +{ + return (double complex) casinhf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/catanf.c b/libm/libmcs/libm/complexf/catanf.c new file mode 100644 index 00000000..f8d034e8 --- /dev/null +++ b/libm/libmcs/libm/complexf/catanf.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include +#include "internal/ctrigf.h" + +float complex catanf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float a, t, x, x2, y, tmp; + + x = crealf(z); + y = cimagf(z); + + if ((x == 0.0f) && (y > 1.0f)) { + goto ovrf; + } + + x2 = x * x; + a = 1.0f - x2 - (y * y); + + t = 0.5f * atan2f(2.0f * x, a); + tmp = __redupif(t); + + t = y - 1.0f; + a = x2 + (t * t); + + t = y + 1.0f; + a = (x2 + (t * t)) / a; + /* w = tmp + (0.25f * logf(a)) * I; */ + w = CMPLXF(tmp, 0.25f * logf(a)); + return w; + +ovrf: + w = CMPLXF(HUGE_VALF, HUGE_VALF); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex catan(double complex z) +{ + return (double complex) catanf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/catanhf.c b/libm/libmcs/libm/complexf/catanhf.c new file mode 100644 index 00000000..5660d20b --- /dev/null +++ b/libm/libmcs/libm/complexf/catanhf.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include + +float complex catanhf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float complex tmp; + + /* w = -1.0f * I * catanf(z * I); */ + tmp = CMPLXF(-cimagf(z), crealf(z)); + tmp = catanf(tmp); + w = CMPLXF(cimagf(tmp), -crealf(tmp)); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex catanh(double complex z) +{ + return (double complex) catanhf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/ccosf.c b/libm/libmcs/libm/complexf/ccosf.c new file mode 100644 index 00000000..0df90fa4 --- /dev/null +++ b/libm/libmcs/libm/complexf/ccosf.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include +#include "internal/ctrigf.h" + +float complex ccosf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float ch, sh; + + __ccoshsinhf(cimagf(z), &ch, &sh); + /* w = cosf(crealf(z)) * ch - (sinf(crealf(z)) * sh) * I; */ + w = CMPLXF(cosf(crealf(z)) * ch, -(sinf(crealf(z)) * sh)); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex ccos(double complex z) +{ + return (double complex) ccosf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/ccoshf.c b/libm/libmcs/libm/complexf/ccoshf.c new file mode 100644 index 00000000..79c1fd8c --- /dev/null +++ b/libm/libmcs/libm/complexf/ccoshf.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +float complex ccoshf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float x, y; + + x = crealf(z); + y = cimagf(z); + /* w = coshf(x) * cosf(y) + (sinhf(x) * sinf(y)) * I; */ + w = CMPLXF(coshf(x) * cosf(y), sinhf(x) * sinf(y)); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex ccosh(double complex z) +{ + return (double complex) ccoshf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/cexpf.c b/libm/libmcs/libm/complexf/cexpf.c new file mode 100644 index 00000000..b27fe943 --- /dev/null +++ b/libm/libmcs/libm/complexf/cexpf.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +float complex cexpf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float r, x, y; + + x = crealf(z); + y = cimagf(z); + r = expf(x); + /* w = r * cosf(y) + r * sinf(y) * I; */ + w = CMPLXF(r * cosf(y), r * sinf(y)); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex cexp(double complex z) +{ + return (double complex) cexpf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/cimagf.c b/libm/libmcs/libm/complexf/cimagf.c new file mode 100644 index 00000000..b0115327 --- /dev/null +++ b/libm/libmcs/libm/complexf/cimagf.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +#include +#include "../common/tools.h" + +float cimagf(float complex z) +{ + float_complex w; + w.z = z; + + return (IMAG_PART(w)); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double cimag(double complex z) +{ + return (double) cimagf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/clogf.c b/libm/libmcs/libm/complexf/clogf.c new file mode 100644 index 00000000..31bc1af3 --- /dev/null +++ b/libm/libmcs/libm/complexf/clogf.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +float complex clogf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float p, rr; + + rr = cabsf(z); + p = logf(rr); + rr = atan2f(cimagf(z), crealf(z)); + /* w = p + rr * I; */ + w = CMPLXF(p, rr); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex clog(double complex z) +{ + return (double complex) clogf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/conjf.c b/libm/libmcs/libm/complexf/conjf.c new file mode 100644 index 00000000..8a783f0e --- /dev/null +++ b/libm/libmcs/libm/complexf/conjf.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +#include +#include "../common/tools.h" + +float complex conjf(float complex z) +{ + float_complex w = { .z = z }; + + IMAG_PART(w) = -IMAG_PART(w); + + return (w.z); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex conj(double complex z) +{ + return (double complex) conjf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/cpowf.c b/libm/libmcs/libm/complexf/cpowf.c new file mode 100644 index 00000000..f18b6aad --- /dev/null +++ b/libm/libmcs/libm/complexf/cpowf.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +float complex cpowf(float complex x, float complex y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float realz, imagz, result, theta, absx, argx; + + realz = crealf(y); + imagz = cimagf(y); + absx = cabsf(x); + + if (absx == 0.0f) { + return CMPLXF(0.0f, 0.0f); + } + + argx = cargf(x); + result = powf(absx, realz); + theta = realz * argx; + + if (imagz != 0.0f) { + result = result * expf(-imagz * argx); + theta = theta + imagz * logf(absx); + } + + /*w = result * cosf(theta) + (result * sinf(theta)) * I; */ + w = CMPLXF(result * cosf(theta), result * sinf(theta)); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex cpow(double complex x, double complex y) +{ + return (double complex) cpowf((float complex) x, (float complex) y); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/cprojf.c b/libm/libmcs/libm/complexf/cprojf.c new file mode 100644 index 00000000..aed288de --- /dev/null +++ b/libm/libmcs/libm/complexf/cprojf.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +#include "../common/tools.h" + +float complex cprojf(float complex z) +{ + float_complex w = { .z = z }; + + if (isinf(REAL_PART(w)) || isinf(IMAG_PART(w))) { + REAL_PART(w) = INFINITY; + IMAG_PART(w) = copysignf(0.0, cimagf(z)); + } + + return (w.z); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex cproj(double complex z) +{ + return (double complex) cprojf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/crealf.c b/libm/libmcs/libm/complexf/crealf.c new file mode 100644 index 00000000..a70bddbb --- /dev/null +++ b/libm/libmcs/libm/complexf/crealf.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: PublicDomain */ +/* Written by Matthias Drochner . */ + +#include +#include "../common/tools.h" + +float crealf(float complex z) +{ + float_complex w; + w.z = z; + + return (REAL_PART(w)); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double creal(double complex z) +{ + return (double) crealf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/csinf.c b/libm/libmcs/libm/complexf/csinf.c new file mode 100644 index 00000000..da3b305a --- /dev/null +++ b/libm/libmcs/libm/complexf/csinf.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include +#include "internal/ctrigf.h" + +float complex csinf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float ch, sh; + + __ccoshsinhf(cimagf(z), &ch, &sh); + /* w = sinf(crealf(z)) * ch + (cosf(crealf(z)) * sh) * I; */ + w = CMPLXF(sinf(crealf(z)) * ch, cosf(crealf(z)) * sh); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex csin(double complex z) +{ + return (double complex) csinf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/csinhf.c b/libm/libmcs/libm/complexf/csinhf.c new file mode 100644 index 00000000..1f1b347f --- /dev/null +++ b/libm/libmcs/libm/complexf/csinhf.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +float complex csinhf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float x, y; + + x = crealf(z); + y = cimagf(z); + /* w = sinhf(x) * cosf(y) + (coshf(x) * sinf(y)) * I; */ + w = CMPLXF(sinhf(x) * cosf(y), coshf(x) * sinf(y)); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex csinh(double complex z) +{ + return (double complex) csinhf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/csqrtf.c b/libm/libmcs/libm/complexf/csqrtf.c new file mode 100644 index 00000000..cadba7a8 --- /dev/null +++ b/libm/libmcs/libm/complexf/csqrtf.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +float complex csqrtf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float x, y, r, t, scale; + + x = crealf(z); + y = cimagf(z); + + if (y == 0.0f) { + if (x < 0.0f) { + w = CMPLXF(0.0f, sqrtf(-x)); + } else if (x == 0.0f) { + w = CMPLXF(0.0f, y); + } else { + w = CMPLXF(sqrtf(x), y); + } + + return w; + } + + if (x == 0.0f) { + r = fabsf(y); + r = sqrtf(0.5f * r); + + if (y > 0) { + w = CMPLXF(r, r); + } else { + w = CMPLXF(r, -r); + } + + return w; + } + + /* Rescale to avoid internal overflow or underflow. */ + if ((fabsf(x) > 4.0f) || (fabsf(y) > 4.0f)) { + x *= 0.25f; + y *= 0.25f; + scale = 2.0f; + } else { + x *= 6.7108864e7f; /* 2^26 */ + y *= 6.7108864e7f; + scale = 1.220703125e-4f; /* 2^-13 */ + } + + w = CMPLXF(x, y); + r = cabsf(w); + + if (x > 0) { + t = sqrtf(0.5f * r + 0.5f * x); + r = scale * fabsf((0.5f * y) / t); + t *= scale; + } else { + r = sqrtf(0.5f * r - 0.5f * x); + t = scale * fabsf((0.5f * y) / r); + r *= scale; + } + + if (y < 0) { + w = CMPLXF(t, -r); + } else { + w = CMPLXF(t, r); + } + + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex csqrt(double complex z) +{ + return (double complex) csqrtf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/ctanf.c b/libm/libmcs/libm/complexf/ctanf.c new file mode 100644 index 00000000..1351a3c4 --- /dev/null +++ b/libm/libmcs/libm/complexf/ctanf.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include +#include "internal/ctrigf.h" + +/* Taylor series expansion for cosh(2y) - cos(2x) */ + +static inline float __ctansf(float complex z) +{ + float f, x, x2, y, y2, rn, t, d; + + x = fabsf(2.0f * crealf(z)); + y = fabsf(2.0f * cimagf(z)); + + x = __redupif(x); + + x = x * x; + y = y * y; + x2 = 1.0f; + y2 = 1.0f; + f = 1.0f; + rn = 0.0f; + d = 0.0f; + + do { + rn += 1.0f; + f *= rn; + rn += 1.0f; + f *= rn; + x2 *= x; + y2 *= y; + t = y2 + x2; + t /= f; + d += t; + + rn += 1.0f; + f *= rn; + rn += 1.0f; + f *= rn; + x2 *= x; + y2 *= y; + t = y2 - x2; + t /= f; + d += t; + } while (fabsf(t / d) > MACHEPF); + + return d; +} + +float complex ctanf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float d; + + d = cosf(2.0f * crealf(z)) + coshf(2.0f * cimagf(z)); + + if (fabsf(d) < 0.25f) { + d = __ctansf(z); + } + + if (d == 0.0f) { + w = CMPLXF(HUGE_VALF, HUGE_VALF); + return w; + } + + /* w = sinf(2.0f * crealf(z)) / d + (sinhf(2.0f * cimagf(z)) / d) * I; */ + w = CMPLXF(sinf(2.0f * crealf(z)) / d, sinhf(2.0f * cimagf(z)) / d); + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex ctan(double complex z) +{ + return (double complex) ctanf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/ctanhf.c b/libm/libmcs/libm/complexf/ctanhf.c new file mode 100644 index 00000000..ce67a824 --- /dev/null +++ b/libm/libmcs/libm/complexf/ctanhf.c @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +float complex ctanhf(float complex z) +{ +#ifdef __LIBMCS_FPU_DAZ + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float complex w; + float x, y, d; + + x = crealf(z); + y = cimagf(z); + d = coshf(2.0f * x) + cosf(2.0f * y); + /* w = sinhf(2.0f * x) / d + (sinf(2.0f * y) / d) * I; */ + w = CMPLXF(sinhf(2.0f * x) / d, sinf(2.0f * y) / d); + + return w; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double complex ctanh(double complex z) +{ + return (double complex) ctanhf((float complex) z); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/complexf/internal/ctrigf.c b/libm/libmcs/libm/complexf/internal/ctrigf.c new file mode 100644 index 00000000..872c28a9 --- /dev/null +++ b/libm/libmcs/libm/complexf/internal/ctrigf.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: NetBSD */ + +#include +#include + +#include "ctrigf.h" + +/* calculate cosh and sinh */ + +void __ccoshsinhf(float x, float *c, float *s) +{ + float e, ei; + + if (fabsf(x) <= 0.5f) { + *c = coshf(x); + *s = sinhf(x); + } else { + e = expf(x); + if (__fpclassifyf(e) != FP_ZERO) { + ei = 0.5f / e; + } else { + ei = HUGE_VALF; + } + e = 0.5f * e; + *s = e - ei; + *c = e + ei; + } +} + +/* Program to subtract nearest integer multiple of PI */ + +/* extended precision value of PI: */ +static const float DP1 = 3.140625; +static const float DP2 = 9.67502593994140625E-4; +static const float DP3 = 1.509957990978376432E-7; + +float __redupif(float x) +{ + float t; + long i; + + t = x / (float)M_PI; + + if (t >= 0.0f) { + t += 0.5f; + } else { + t -= 0.5f; + } + + i = t; /* the multiple */ + t = i; + t = ((x - t * DP1) - t * DP2) - t * DP3; + return t; +} diff --git a/libm/libmcs/libm/complexf/internal/ctrigf.h b/libm/libmcs/libm/complexf/internal/ctrigf.h new file mode 100644 index 00000000..debc58a4 --- /dev/null +++ b/libm/libmcs/libm/complexf/internal/ctrigf.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_CTRIGF_H +#define LIBMCS_CTRIGF_H + +#define MACHEPF 3.0e-8 + +extern void __ccoshsinhf(float x, float *c, float *s); +extern float __redupif(float x); + +#endif /* !LIBMCS_CTRIGF_H */ diff --git a/libm/libmcs/libm/complexfe/internal/.gitkeep b/libm/libmcs/libm/complexfe/internal/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/libm/libmcs/libm/complexl/internal/.gitkeep b/libm/libmcs/libm/complexl/internal/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/libm/libmcs/libm/include/complex.h b/libm/libmcs/libm/include/complex.h new file mode 100644 index 00000000..8e9774e9 --- /dev/null +++ b/libm/libmcs/libm/include/complex.h @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: NetBSD */ +/* Written by Matthias Drochner. */ + +#ifndef LIBMCS_COMPLEX_H +#define LIBMCS_COMPLEX_H + +#ifdef __STDC_NO_COMPLEX__ + #error Your toolchain has defined __STDC_NO_COMPLEX__ which indicates that \ + it does not support complex types as such you should not include \ + complex.h in your software. (Hint: When running configure for the \ + LibmCS choose not to use complex procedures.) +#endif + +#ifdef __cplusplus +extern "C"{ +#endif + +#include "internal_config.h" + +#ifndef __LIBMCS_WANT_COMPLEX + #error During the configure step you have chosen not to compile complex \ + procedures as such you should not include complex.h in your software. +#endif + +#define complex _Complex +#define _Complex_I __extension__ 1.0fi +#define I _Complex_I + +/* 7.3.5 Trigonometric functions */ +/* 7.3.5.1 The cacos functions */ +double complex cacos(double complex); +float complex cacosf(float complex); + +/* 7.3.5.2 The casin functions */ +double complex casin(double complex); +float complex casinf(float complex); + +/* 7.3.5.1 The catan functions */ +double complex catan(double complex); +float complex catanf(float complex); + +/* 7.3.5.1 The ccos functions */ +double complex ccos(double complex); +float complex ccosf(float complex); + +/* 7.3.5.1 The csin functions */ +double complex csin(double complex); +float complex csinf(float complex); + +/* 7.3.5.1 The ctan functions */ +double complex ctan(double complex); +float complex ctanf(float complex); + +/* 7.3.6 Hyperbolic functions */ +/* 7.3.6.1 The cacosh functions */ +double complex cacosh(double complex); +float complex cacoshf(float complex); + +/* 7.3.6.2 The casinh functions */ +double complex casinh(double complex); +float complex casinhf(float complex); + +/* 7.3.6.3 The catanh functions */ +double complex catanh(double complex); +float complex catanhf(float complex); + +/* 7.3.6.4 The ccosh functions */ +double complex ccosh(double complex); +float complex ccoshf(float complex); + +/* 7.3.6.5 The csinh functions */ +double complex csinh(double complex); +float complex csinhf(float complex); + +/* 7.3.6.6 The ctanh functions */ +double complex ctanh(double complex); +float complex ctanhf(float complex); + +/* 7.3.7 Exponential and logarithmic functions */ +/* 7.3.7.1 The cexp functions */ +double complex cexp(double complex); +float complex cexpf(float complex); + +/* 7.3.7.2 The clog functions */ +double complex clog(double complex); +float complex clogf(float complex); + +/* 7.3.8 Power and absolute-value functions */ +/* 7.3.8.1 The cabs functions */ +double cabs(double complex) ; +float cabsf(float complex) ; + +/* 7.3.8.2 The cpow functions */ +double complex cpow(double complex, double complex); +float complex cpowf(float complex, float complex); + +/* 7.3.8.3 The csqrt functions */ +double complex csqrt(double complex); +float complex csqrtf(float complex); + +/* 7.3.9 Manipulation functions */ +/* 7.3.9.1 The carg functions */ +double carg(double complex); +float cargf(float complex); + +/* 7.3.9.2 The cimag functions */ +double cimag(double complex); +float cimagf(float complex); + +/* 7.3.9.3 The conj functions */ +double complex conj(double complex); +float complex conjf(float complex); + +/* 7.3.9.4 The cproj functions */ +double complex cproj(double complex); +float complex cprojf(float complex); + +/* 7.3.9.5 The creal functions */ +double creal(double complex); +float crealf(float complex); + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + + long double complex cacosl(long double complex); + long double complex casinl(long double complex); + long double complex catanl(long double complex); + long double complex ccosl(long double complex); + long double complex csinl(long double complex); + long double complex ctanl(long double complex); + + long double complex cacoshl(long double complex); + long double complex casinhl(long double complex); + long double complex catanhl(long double complex); + long double complex ccoshl(long double complex); + long double complex csinhl(long double complex); + long double complex ctanhl(long double complex); + + long double complex cexpl(long double complex); + long double complex clogl(long double complex); + + long double cabsl(long double complex) ; + long double complex cpowl(long double complex, long double complex); + long double complex csqrtl(long double complex); + + long double cargl(long double complex); + long double cimagl(long double complex); + long double complex conjl(long double complex); + long double complex cprojl(long double complex); + long double creall(long double complex); + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ + +/* The C11 CMPLX macros are compiler dependant and only available starting at + * GCC 4.7+ or with clang! If need be define them yourself. */ +#if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) + #define CMPLX(x, y) __builtin_complex ((double) (x), (double) (y)) + #define CMPLXF(x, y) __builtin_complex ((float) (x), (float) (y)) + #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + #define CMPLXL(x, y) __builtin_complex ((long double) (x), (long double) (y)) + #endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#else + /* Due to the used compiler being too old the library cannot provide fully + * C11 standard compliant macros CMPLX, CMPLXF, CMPLXL. The library + * provides functionally equivalent inline functions with the same symbol + * name with the only limitation in that they cannot be used for static + * initialisation. */ + + static inline float complex CMPLXF(float x, float y) + { + union { + float a[2]; + float complex f; + } z = {{ x, y }}; + + return (z.f); + } + + static inline double complex CMPLX(double x, double y) + { + union { + double a[2]; + double complex f; + } z = {{ x, y }}; + + return (z.f); + } + + #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + static inline long double complex CMPLXL(long double x, long double y) + { + union { + long double a[2]; + long double complex f; + } z = {{ x, y }}; + + return (z.f); + } + #endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !LIBMCS_COMPLEX_H */ diff --git a/libm/libmcs/libm/include/fenv.h b/libm/libmcs/libm/include/fenv.h new file mode 100644 index 00000000..71381734 --- /dev/null +++ b/libm/libmcs/libm/include/fenv.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_FENV_H +#define LIBMCS_FENV_H + +#error fenv.h/fenv.c shall not be used as is. They have no functionality \ + other than returning an error value and providing prototypes. \ + If you, the user, want to use fenv you will have to implement the \ + features yourself (or copy them from somewhere). We can not \ + provide these functionalities for you as their implementation is \ + highly platform dependant. + +#ifdef __cplusplus +extern "C"{ +#endif + +/* Floating-point Exceptions */ +extern int feclearexcept(int); +extern int feraiseexcept(int); +extern int fegetexceptflag(fexcept_t *, int); +extern int fesetexceptflag(const fexcept_t *, int); + +/* Rounding Direction */ +extern int fegetround(void); +extern int fesetround(int); + +/* Entire Environment */ +extern int fegetenv(fenv_t *); +extern int fesetenv(const fenv_t *); +extern int feholdexcept(fenv_t *); +extern int feupdateenv(const fenv_t *); + +/* Other */ +extern int fetestexcept(int); + +#ifdef __cplusplus +} +#endif + +#endif /* !LIBMCS_FENV_H */ diff --git a/libm/libmcs/libm/include/internal_config.h b/libm/libmcs/libm/include/internal_config.h new file mode 100644 index 00000000..9260178e --- /dev/null +++ b/libm/libmcs/libm/include/internal_config.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_INTERNAL_CONFIG_H +#define LIBMCS_INTERNAL_CONFIG_H + +/* If an FPU is not standard compliant for subnormal values, use the define LIBMCS_FPU_DAZ to force + * each procedure to first multiply the input value(s) by 1, therefore using the FPUs defined + * behaviour for subnormal values as follows: + * If the FPU is standard compliant for subnormals, the multiplication does not cause any + * difference in the behaviour of the procedure. + * If the FPU can not handle subnormals at all, it's very likely that a special FPU trap will be + * thrown. This trap can then be handled by the user if so inclined. + * If the FPU has an internal implementation for DAZ (denormals are zero), the input values will be + * reduced to zero and the procedures will then behave as if a zero was used as an input. Usually + * this will also generate an inexact exception. */ +#ifdef LIBMCS_FPU_DAZ + #define __LIBMCS_FPU_DAZ + static volatile double __volatile_one = 1.0; + static volatile float __volatile_onef = 1.0f; +#endif /* LIBMCS_FPU_DAZ */ + +/* Define to tell the libm to not exclude complex procedures. */ +#ifdef LIBMCS_WANT_COMPLEX + #define __LIBMCS_WANT_COMPLEX +#endif /* LIBMCS_WANT_COMPLEX */ + +/* Define to tell the libm to be built for 32bit doubles. */ +#ifdef LIBMCS_DOUBLE_IS_32BITS + #define __LIBMCS_DOUBLE_IS_32BITS +#endif /* LIBMCS_DOUBLE_IS_32BITS */ + +/* Define to tell the libm to be built for 64bit long doubles. */ +#ifdef LIBMCS_LONG_DOUBLE_IS_64BITS + #define __LIBMCS_LONG_DOUBLE_IS_64BITS + #ifdef LIBMCS_DOUBLE_IS_32BITS + #error Cannot define both LIBMCS_DOUBLE_IS_32BITS and LIBMCS_LONG_DOUBLE_IS_64BITS at once. + #endif /* LIBMCS_DOUBLE_IS_32BITS */ +#endif /* LIBMCS_LONG_DOUBLE_IS_64BITS */ + +/* Define to tell the libm to be built for 32bit long int. */ +#define __MAX_LONG_LONG 0x7FFFFFFFFFFFFFFFLL +#define __MIN_LONG_LONG 0x8000000000000000LL +#ifdef LIBMCS_LONG_IS_32BITS + #define __LIBMCS_LONG_IS_32BITS + #define __MAX_LONG 0x7FFFFFFFL + #define __MIN_LONG 0x80000000L +#else + #define __MAX_LONG 0x7FFFFFFFFFFFFFFFL + #define __MIN_LONG 0x8000000000000000L +#endif /* LIBMCS_LONG_IS_32BITS */ + +/* 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. 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) */ + +#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) +#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 __LIBMCS_FPU_DAZ + #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 + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define __IEEE_BIG_ENDIAN +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define __IEEE_LITTLE_ENDIAN +#endif + +#ifndef __IEEE_BIG_ENDIAN + #ifndef __IEEE_LITTLE_ENDIAN + #error Must define endianness + #endif +#endif + +#endif /* !LIBMCS_INTERNAL_CONFIG_H */ diff --git a/libm/libmcs/libm/include/math.h b/libm/libmcs/libm/include/math.h new file mode 100644 index 00000000..4c12ed59 --- /dev/null +++ b/libm/libmcs/libm/include/math.h @@ -0,0 +1,389 @@ +#ifndef LIBMCS_MATH_H +#define LIBMCS_MATH_H + +#ifdef __cplusplus +extern "C"{ +#endif + +#include "internal_config.h" + +/* + * These macros define the errno and exception behaviour of the library. This + * library enforces the use of math_errhandling as MATH_ERREXCEPT. + * See ISO C18 standard §7.12 wrt. math_errhandling. + */ +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 +#define math_errhandling MATH_ERREXCEPT + +typedef float float_t; +typedef double double_t; + +#define MAXFLOAT 3.40282347e+38F + +#define M_E 2.7182818284590452354 +#define M_LOG2E 1.4426950408889634074 +#define M_LOG10E 0.43429448190325182765 +#define M_LN2 0.693147180559945309417 +#define M_LN10 2.30258509299404568402 +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.78539816339744830962 +#define M_1_PI 0.31830988618379067154 +#define M_2_PI 0.63661977236758134308 +#define M_2_SQRTPI 1.12837916709551257390 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT1_2 0.70710678118654752440 + +#define HUGE_VAL (__infd) +#define HUGE_VALF (__inff) +#define HUGE_VALL ((long double) HUGE_VAL) +#define INFINITY HUGE_VALF + +/* Global constants that contain infinities. */ +extern const float __inff; +extern const double __infd; + +#define NAN (nanf("")) + +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 + +#define FP_ILOGB0 (-INT_MAX) +#define FP_ILOGBNAN INT_MAX + +/* Double trigonometric functions */ +extern double acos(double); +extern double asin(double); +extern double atan(double); +extern double atan2(double, double); +extern double cos(double); +extern double sin(double); +extern double tan(double); + +/* Double hyperbolic functions */ +extern double acosh(double); +extern double asinh(double); +extern double atanh(double); +extern double cosh(double); +extern double sinh(double); +extern double tanh(double); + +/* Double exponential and logarithmic functions */ +extern double exp(double); +extern double exp2(double); +extern double expm1(double); +extern double frexp(double, int *); +extern int ilogb(double); +extern double ldexp(double, int); +extern double log(double); +extern double log10(double); +extern double log1p(double); +extern double log2(double); +extern double logb(double); +extern double modf(double, double *); +extern double scalbn(double, int); +extern double scalbln(double, long int); + +/* Double power and absolute-value functions */ +extern double cbrt(double); +extern double fabs(double); +extern double hypot(double, double); +extern double pow(double, double); +extern double sqrt(double); + +/* Double error and gamma functions */ +extern double erf(double); +extern double erfc(double); +extern double lgamma(double); +extern double tgamma(double); + +/* Double nearest integer functions */ +extern double ceil(double); +extern double floor(double); +extern double nearbyint(double); +extern double rint(double); +extern long int lrint(double); +extern long long int llrint(double); +extern double round(double); +extern long int lround(double); +extern long long int llround(double); +extern double trunc(double); + +/* Double remainder functions */ +extern double fmod(double, double); +extern double remainder(double, double); +extern double remquo(double, double, int *); + +/* Double manipulation functions */ +extern double copysign(double, double); +extern double nan(const char *); +extern double nextafter(double, double); + +/* Double maximum, minimum and positive difference functions */ +extern double fdim(double, double); +extern double fmax(double, double); +extern double fmin(double, double); + +/* Double float-multiply-add function */ +extern double fma(double, double, double); + +/* Double Bessel functions */ +extern double y0(double); +extern double y1(double); +extern double yn(int, double); +extern double j0(double); +extern double j1(double); +extern double jn(int, double); + + +/* Float trigonometric functions */ +extern float acosf(float); +extern float asinf(float); +extern float atanf(float); +extern float atan2f(float, float); +extern float cosf(float); +extern float sinf(float); +extern float tanf(float); + +/* Float hyperbolic functions */ +extern float acoshf(float); +extern float asinhf(float); +extern float atanhf(float); +extern float coshf(float); +extern float sinhf(float); +extern float tanhf(float); + +/* Float exponential and logarithmic functions */ +extern float expf(float); +extern float exp2f(float); +extern float expm1f(float); +extern float frexpf(float, int *); +extern int ilogbf(float); +extern float ldexpf(float, int); +extern float logf(float); +extern float log10f(float); +extern float log1pf(float); +extern float log2f(float); +extern float logbf(float); +extern float modff(float, float *); +extern float scalbnf(float, int); +extern float scalblnf(float, long int); + +/* Float power and absolute-value functions */ +extern float cbrtf(float); +extern float fabsf(float); +extern float hypotf(float, float); +extern float powf(float, float); +extern float sqrtf(float); + +/* Float error and gamma functions */ +extern float erff(float); +extern float erfcf(float); +extern float lgammaf(float); +extern float tgammaf(float); + +/* Float nearest integer functions */ +extern float ceilf(float); +extern float floorf(float); +extern float nearbyintf(float); +extern float rintf(float); +extern long int lrintf(float); +extern long long int llrintf(float); +extern float roundf(float); +extern long int lroundf(float); +extern long long int llroundf(float); +extern float truncf(float); + +/* Float remainder functions */ +extern float fmodf(float, float); +extern float remainderf(float, float); +extern float remquof(float, float, int *); + +/* Float manipulation functions */ +extern float copysignf(float, float); +extern float nanf(const char *); +extern float nextafterf(float, float); + +/* Float maximum, minimum and positive difference functions */ +extern float fdimf(float, float); +extern float fmaxf(float, float); +extern float fminf(float, float); + +/* Float float-multiply-add function */ +extern float fmaf(float, float, float); + + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + + /* Long double trigonometric functions */ + extern long double acosl(long double); + extern long double asinl(long double); + extern long double atanl(long double); + extern long double atan2l(long double, long double); + extern long double cosl(long double); + extern long double sinl(long double); + extern long double tanl(long double); + + /* Long double hyperbolic functions */ + extern long double acoshl(long double); + extern long double asinhl(long double); + extern long double atanhl(long double); + extern long double coshl(long double); + extern long double sinhl(long double); + extern long double tanhl(long double); + + /* Long double exponential and logarithmic functions */ + extern long double expl(long double); + extern long double exp2l(long double); + extern long double expm1l(long double); + extern long double frexpl(long double, int *); + extern int ilogbl(long double); + extern long double ldexpl(long double, int); + extern long double logl(long double); + extern long double log10l(long double); + extern long double log1pl(long double); + extern long double log2l(long double); + extern long double logbl(long double); + extern long double modfl(long double, long double *); + extern long double scalbnl(long double, int); + extern long double scalblnl(long double, long); + + /* Long double power and absolute-value functions */ + extern long double cbrtl(long double); + extern long double fabsl(long double); + extern long double hypotl(long double, long double); + extern long double powl(long double, long double); + extern long double sqrtl(long double); + + /* Long double error and gamma functions */ + extern long double erfl(long double); + extern long double erfcl(long double); + extern long double lgammal(long double); + extern long double tgammal(long double); + + /* Long double nearest integer functions */ + extern long double ceill(long double); + extern long double floorl(long double); + extern long double nearbyintl(long double); + extern long double rintl(long double); + extern long int lrintl(long double); + extern long long int llrintl(long double); + extern long double roundl(long double); + extern long lroundl(long double); + extern long long int llroundl(long double); + extern long double truncl(long double); + + /* Long double remainder functions */ + extern long double fmodl(long double, long double); + extern long double remainderl(long double, long double); + extern long double remquol(long double, long double, int *); + + /* Long double manipulation functions */ + extern long double copysignl(long double, long double); + extern long double nanl(const char *); + extern long double nextafterl(long double, long double); + + /* Long double maximum, minimum and positive difference functions */ + extern long double fdiml(long double, long double); + extern long double fmaxl(long double, long double); + extern long double fminl(long double, long double); + + /* Long double float-multiply-add function */ + extern long double fmal(long double, long double, long double); + + /* nexttoward procedures, they're seperated from the manipulation functions + * due to containing long double inputs for all procedures */ + extern float nexttowardf(float, long double); + extern double nexttoward(double, long double); + extern long double nexttowardl(long double, long double); + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ + +/* signgam global variable used by the lgamma procedures to return the sign of gamma */ +#define signgam (__signgam) +extern int __signgam; + +/* Internal procedures used by the classification macros */ +extern int __fpclassifyf(float); +extern int __fpclassifyd(double); +extern int __signbitf(float); +extern int __signbitd(double); + +/* Classification macros */ +#define fpclassify(__x) ((sizeof(__x) == sizeof(float)) ? __fpclassifyf(__x) \ + : __fpclassifyd(__x)) +#define isfinite(__y) (__extension__ \ + ({int __cy = fpclassify(__y); \ + __cy != FP_INFINITE && __cy != FP_NAN;})) + +#define isinf(__x) (fpclassify(__x) == FP_INFINITE) +#define isnan(__x) (fpclassify(__x) == FP_NAN) +#define isnormal(__x) (fpclassify(__x) == FP_NORMAL) + +#define signbit(__x) ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) \ + : __signbitd(__x)) + +/* Comparison macros */ +#define isgreater(x,y) (__extension__ ({ \ + __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + int __result; \ + if (isunordered(__x, __y)) { \ + __result = 0; \ + } else { \ + __result = (__x > __y); \ + } \ + __result; \ + })) +#define isgreaterequal(x,y) (__extension__ ({ \ + __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + int __result; \ + if (isunordered(__x, __y)) { \ + __result = 0; \ + } else { \ + __result = (__x >= __y); \ + } \ + __result; \ + })) +#define isless(x,y) (__extension__ ({ \ + __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + int __result; \ + if (isunordered(__x, __y)) { \ + __result = 0; \ + } else { \ + __result = (__x < __y); \ + } \ + __result; \ + })) +#define islessequal(x,y) (__extension__ ({ \ + __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + int __result; \ + if (isunordered(__x, __y)) { \ + __result = 0; \ + } else { \ + __result = (__x <= __y); \ + } \ + __result; \ + })) +#define islessgreater(x,y) (__extension__ ({ \ + __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + int __result; \ + if (isunordered(__x, __y)) { \ + __result = 0; \ + } else { \ + __result = (__x < __y) || (__x > __y); \ + } \ + __result; \ + })) +#define isunordered(a,b) (__extension__ \ + ({__typeof__(a) __a = (a); __typeof__(b) __b = (b); \ + fpclassify(__a) == FP_NAN || fpclassify(__b) == FP_NAN;})) + +#ifdef __cplusplus +} +#endif + +#endif /* !LIBMCS_MATH_H */ diff --git a/libm/libmcs/libm/include/tgmath.h b/libm/libmcs/libm/include/tgmath.h new file mode 100644 index 00000000..1a43b56b --- /dev/null +++ b/libm/libmcs/libm/include/tgmath.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: NetBSD */ +/* Copyright (c) 2004 Stefan Farfeleder. */ + +#ifndef LIBMCS_TGMATH_H +#define LIBMCS_TGMATH_H + +#error tgmath.h should never be used in critical systems. If you insist on \ + doing it anyway you are on your own. The given tgmath.h implementation \ + is taken from newlib as is and has not been reviewed by us and as such \ + is wholely unqualified. + +#include +#include + +/* + * This implementation of requires two implementation-dependent + * macros to be defined: + * __tg_impl_simple(x, y, z, fn, fnf, fnl, ...) + * Invokes fnl() if the corresponding real type of x, y or z is long + * double, fn() if it is double or any has an integer type, and fnf() + * otherwise. + * __tg_impl_full(x, y, z, fn, fnf, fnl, cfn, cfnf, cfnl, ...) + * Invokes [c]fnl() if the corresponding real type of x, y or z is long + * double, [c]fn() if it is double or any has an integer type, and + * [c]fnf() otherwise. The function with the 'c' prefix is called if + * any of x, y or z is a complex number. + * Both macros call the chosen function with all additional arguments passed + * to them, as given by __VA_ARGS__. + * + * Note that these macros cannot be implemented with C's ?: operator, + * because the return type of the whole expression would incorrectly be long + * double complex regardless of the argument types. + */ + +/* requires GCC >= 3.1 */ +#if !__GNUC_PREREQ (3, 1) + #error " not implemented for this compiler" +#endif + +#define __tg_type(__e, __t) \ + __builtin_types_compatible_p(__typeof__(__e), __t) +#define __tg_type3(__e1, __e2, __e3, __t) \ + (__tg_type(__e1, __t) || __tg_type(__e2, __t) || \ + __tg_type(__e3, __t)) +#define __tg_type_corr(__e1, __e2, __e3, __t) \ + (__tg_type3(__e1, __e2, __e3, __t) || \ + __tg_type3(__e1, __e2, __e3, __t _Complex)) +#define __tg_integer(__e1, __e2, __e3) \ + (((__typeof__(__e1))1.5 == 1) || ((__typeof__(__e2))1.5 == 1) || \ + ((__typeof__(__e3))1.5 == 1)) +#define __tg_is_complex(__e1, __e2, __e3) \ + (__tg_type3(__e1, __e2, __e3, float _Complex) || \ + __tg_type3(__e1, __e2, __e3, double _Complex) || \ + __tg_type3(__e1, __e2, __e3, long double _Complex) || \ + __tg_type3(__e1, __e2, __e3, __typeof__(_Complex_I))) + +#if defined (_LDBL_EQ_DBL) || defined (__CYGWIN__) +#define __tg_impl_simple(x, y, z, fn, fnf, fnl, ...) \ + __builtin_choose_expr(__tg_type_corr(x, y, z, long double), \ + fnl(__VA_ARGS__), __builtin_choose_expr( \ + __tg_type_corr(x, y, z, double) || __tg_integer(x, y, z), \ + fn(__VA_ARGS__), fnf(__VA_ARGS__))) +#else +#define __tg_impl_simple(__x, __y, __z, __fn, __fnf, __fnl, ...) \ + (__tg_type_corr(__x, __y, __z, double) || __tg_integer(__x, __y, __z)) \ + ? __fn(__VA_ARGS__) : __fnf(__VA_ARGS__) +#endif + +#define __tg_impl_full(__x, __y, __z, __fn, __fnf, __fnl, __cfn, __cfnf, __cfnl, ...) \ + __builtin_choose_expr(__tg_is_complex(__x, __y, __z), \ + __tg_impl_simple(__x, __y, __z, __cfn, __cfnf, __cfnl, __VA_ARGS__), \ + __tg_impl_simple(__x, __y, __z, __fn, __fnf, __fnl, __VA_ARGS__)) + +/* Macros to save lots of repetition below */ +#define __tg_simple(__x, __fn) \ + __tg_impl_simple(__x, __x, __x, __fn, __fn##f, __fn##l, __x) +#define __tg_simple2(__x, __y, __fn) \ + __tg_impl_simple(__x, __x, __y, __fn, __fn##f, __fn##l, __x, __y) +#define __tg_simplev(__x, __fn, ...) \ + __tg_impl_simple(__x, __x, __x, __fn, __fn##f, __fn##l, __VA_ARGS__) +#define __tg_full(__x, __fn) \ + __tg_impl_full(__x, __x, __x, __fn, __fn##f, __fn##l, c##__fn, c##__fn##f, c##__fn##l, __x) + +/* 7.22#4 -- These macros expand to real or complex functions, depending on + * the type of their arguments. */ +#define acos(__x) __tg_full(__x, acos) +#define asin(__x) __tg_full(__x, asin) +#define atan(__x) __tg_full(__x, atan) +#define acosh(__x) __tg_full(__x, acosh) +#define asinh(__x) __tg_full(__x, asinh) +#define atanh(__x) __tg_full(__x, atanh) +#define cos(__x) __tg_full(__x, cos) +#define sin(__x) __tg_full(__x, sin) +#define tan(__x) __tg_full(__x, tan) +#define cosh(__x) __tg_full(__x, cosh) +#define sinh(__x) __tg_full(__x, sinh) +#define tanh(__x) __tg_full(__x, tanh) +#define exp(__x) __tg_full(__x, exp) +#define log(__x) __tg_full(__x, log) +#define pow(__x, __y) __tg_impl_full(__x, __x, __y, pow, powf, powl, \ + cpow, cpowf, cpowl, __x, __y) +#define sqrt(__x) __tg_full(__x, sqrt) + +/* "The corresponding type-generic macro for fabs and cabs is fabs." */ +#define fabs(__x) __tg_impl_full(__x, __x, __x, fabs, fabsf, fabsl, cabs, cabsf, \ + cabsl, __x) + +/* 7.22#5 -- These macros are only defined for arguments with real type. */ +#define atan2(__x, __y) __tg_simple2(__x, __y, atan2) +#define cbrt(__x) __tg_simple(__x, cbrt) +#define ceil(__x) __tg_simple(__x, ceil) +#define copysign(__x, __y) __tg_simple2(__x, __y, copysign) +#define erf(__x) __tg_simple(__x, erf) +#define erfc(__x) __tg_simple(__x, erfc) +#define exp2(__x) __tg_simple(__x, exp2) +#define expm1(__x) __tg_simple(__x, expm1) +#define fdim(__x, __y) __tg_simple2(__x, __y, fdim) +#define floor(__x) __tg_simple(__x, floor) +#define fma(__x, __y, __z) __tg_impl_simple(__x, __y, __z, fma, fmaf, fmal, __x, __y, __z) +#define fmax(__x, __y) __tg_simple2(__x, __y, fmax) +#define fmin(__x, __y) __tg_simple2(__x, __y, fmin) +#define fmod(__x, __y) __tg_simple2(__x, __y, fmod) +#define frexp(__x, __y) __tg_simplev(__x, frexp, __x, __y) +#define hypot(__x, __y) __tg_simple2(__x, __y, hypot) +#define ilogb(__x) __tg_simple(__x, ilogb) +#define ldexp(__x, __y) __tg_simplev(__x, ldexp, __x, __y) +#define lgamma(__x) __tg_simple(__x, lgamma) +#define llrint(__x) __tg_simple(__x, llrint) +#define llround(__x) __tg_simple(__x, llround) +#define log10(__x) __tg_simple(__x, log10) +#define log1p(__x) __tg_simple(__x, log1p) +#define log2(__x) __tg_simple(__x, log2) +#define logb(__x) __tg_simple(__x, logb) +#define lrint(__x) __tg_simple(__x, lrint) +#define lround(__x) __tg_simple(__x, lround) +#define nearbyint(__x) __tg_simple(__x, nearbyint) +#define nextafter(__x, __y) __tg_simple2(__x, __y, nextafter) +/* not yet implemented even for _LDBL_EQ_DBL platforms */ +#define nexttoward(__x, __y) __tg_simplev(__x, nexttoward, __x, __y) +#define remainder(__x, __y) __tg_simple2(__x, __y, remainder) +#define remquo(__x, __y, __z) __tg_impl_simple(__x, __x, __y, remquo, remquof, remquol, \ + __x, __y, __z) +#define rint(__x) __tg_simple(__x, rint) +#define round(__x) __tg_simple(__x, round) +#define scalbn(__x, __y) __tg_simplev(__x, scalbn, __x, __y) +#define scalbln(__x, __y) __tg_simplev(__x, scalbln, __x, __y) +#define tgamma(__x) __tg_simple(__x, tgamma) +#define trunc(__x) __tg_simple(__x, trunc) + +/* 7.22#6 -- These macros always expand to complex functions. */ +#define carg(__x) __tg_simple(__x, carg) +#define cimag(__x) __tg_simple(__x, cimag) +#define conj(__x) __tg_simple(__x, conj) +#define cproj(__x) __tg_simple(__x, cproj) +#define creal(__x) __tg_simple(__x, creal) + +#endif /* !LIBMCS_TGMATH_H */ diff --git a/libm/libmcs/libm/machine/sparc_v8/mathd/sqrtd.c b/libm/libmcs/libm/machine/sparc_v8/mathd/sqrtd.c new file mode 100644 index 00000000..3367a5af --- /dev/null +++ b/libm/libmcs/libm/machine/sparc_v8/mathd/sqrtd.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2017-2022 by GTD GmbH. */ + +/** + * + * This family of functions implements the square root of :math:`x` using the + * SPARC V8 hardware instruction directly. + * Use this file (and the float version) to replace the software square root + * when using a SPARC V8 machine. The replacement shall take place in the + * Makefile. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float sqrtf(float x); + * double sqrt(double x); + * long double sqrtl(long double x); + * + * Description + * =========== + * + * ``sqrt`` computes the square root of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * sqrt(x) \approx \sqrt{x} + * + * Returns + * ======= + * + * ``sqrt`` returns the square root of the input value. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when :math:`x` is negative. + * + * Output map + * ========== + * + * +---------------------+--------------+------------------+--------------+--------------+------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================+==============+==============+==================+==============+==============+ + * | **sqrt(x)** | :math:`qNaN` | :math:`qNaN` | :math:`x` | :math:`\sqrt{x}` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+------------------+--------------+--------------+------------------+--------------+--------------+ + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double sqrt(double x) +{ + double root = 0.0; + + __asm__ volatile ("fsqrtd %[x], %[root]" + : [root] "=f" (root) + : [x] "f" (x)); + + return root; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double sqrtl(long double x) +{ + return (long double) sqrt((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/machine/sparc_v8/mathf/sqrtf.c b/libm/libmcs/libm/machine/sparc_v8/mathf/sqrtf.c new file mode 100644 index 00000000..43fa0838 --- /dev/null +++ b/libm/libmcs/libm/machine/sparc_v8/mathf/sqrtf.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2017-2022 by GTD GmbH. */ + +#include + +float sqrtf(float x) +{ + float root = 0.0f; + + __asm__ volatile ("fsqrts %[x], %[root]" + : [root] "=f" (root) + : [x] "f" (x)); + + return root; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double sqrt(double x) +{ + return (double) sqrtf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/acosd.c b/libm/libmcs/libm/mathd/acosd.c new file mode 100644 index 00000000..6b4dc530 --- /dev/null +++ b/libm/libmcs/libm/mathd/acosd.c @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the arc cosine of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float acosf(float x); + * double acos(double x); + * long double acosl(long double x); + * + * Description + * =========== + * + * ``acos`` computes the inverse cosine (*arc cosine*) of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * acos(x) \approx cos^{-1}(x) + * + * Returns + * ======= + * + * ``acos`` returns value in radians, in the range :math:`[0, \pi]`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is not in the + * interval :math:`[-1, 1]`. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------+---------------------+--------------+--------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<-1` | :math:`\in [-1,+1[` | :math:`+1` | :math:`>+1` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==============+=====================+==============+==============+==============+==============+ + * | **acos(x)** | :math:`qNaN` | :math:`qNaN` | :math:`cos^{-1} x` | :math:`+0` | :math:`qNaN` | :math:`qNaN` | :math:`qNaN` | + * +---------------------+--------------+--------------+---------------------+--------------+--------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ +pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ +pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ +pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ +pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ +pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ +pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ +pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ +pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ +qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ +qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ +qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ +qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +double acos(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double z, p, q, r, w, s, c, df; + int32_t hx, ix; + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x3ff00000) { /* |x| >= 1 */ + uint32_t lx; + GET_LOW_WORD(lx, x); + + if (((ix - 0x3ff00000) | lx) == 0) { /* |x|==1 */ + if (hx > 0) { + return 0.0; /* acos(1) = 0 */ + } else { + return __raise_inexact(pi); /* acos(-1)= pi */ + } + } + + if (isnan(x)) { + return x + x; + } + + return __raise_invalid(); /* acos(|x|>1) is NaN */ + } + + if (ix < 0x3fe00000) { /* |x| < 0.5 */ + if (ix <= 0x3c600000) { + return __raise_inexact(pio2_hi); /*if|x|<2**-57*/ + } + + z = x * x; + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + r = p / q; + return pio2_hi - (x - (pio2_lo - x * r)); + } else if (hx < 0) { /* x < -0.5 */ + z = (one + x) * 0.5; + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + s = sqrt(z); + r = p / q; + w = r * s - pio2_lo; + return pi - 2.0 * (s + w); + } else { /* x > 0.5 */ + z = (one - x) * 0.5; + s = sqrt(z); + df = s; + SET_LOW_WORD(df, 0); + c = (z - df * df) / (s + df); + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + r = p / q; + w = r * s + c; + return 2.0 * (df + w); + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double acosl(long double x) +{ + return (long double) acos((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/acoshd.c b/libm/libmcs/libm/mathd/acoshd.c new file mode 100644 index 00000000..f939fc34 --- /dev/null +++ b/libm/libmcs/libm/mathd/acoshd.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the hyperbolic arc cosine of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float acoshf(float x); + * double acosh(double x); + * long double acoshl(long double x); + * + * Description + * =========== + * + * ``acosh`` computes the hyperbolic inverse cosine (*hyperbolic arc cosine*) + * of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * acosh(x) \approx cosh^{-1}(x) = ln \left( x + \sqrt{x^2-1} \right) + * + * Returns + * ======= + * + * ``acosh`` returns the hyperbolic inverse cosine, in the range + * :math:`\mathbb{F}^{+}`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is :math:`<1`. + * + * Output map + * ========== + * + * +---------------------+----------------------+----------------------+----------------------+----------------------+----------------------+----------------------+ + * | **x** | :math:`-Inf` | :math:`<+1` | :math:`+1` | :math:`>+1` | :math:`+Inf` | :math:`NaN` | + * +=====================+======================+======================+======================+======================+======================+======================+ + * | **acosh(x)** | :math:`qNaN` | :math:`qNaN` | :math:`+0` | :math:`cosh^{-1}(x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+----------------------+----------------------+----------------------+----------------------+----------------------+----------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +one = 1.0, +ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ + +double acosh(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double t; + int32_t hx; + uint32_t lx; + EXTRACT_WORDS(hx, lx, x); + + if (hx < 0x3ff00000) { /* x < 1 */ + if (isnan(x)) { + return x + x; + } else { + return __raise_invalid(); + } + } else if (hx >= 0x41b00000) { /* x > 2**28 */ + if (hx >= 0x7ff00000) { /* x is +inf or NaN */ + return x + x; + } else { + return log(x) + ln2; /* acosh(huge)=log(2x) */ + } + } else if (((hx - 0x3ff00000) | lx) == 0) { + return 0.0; /* acosh(1) = 0 */ + } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ + t = x * x; + return log(2.0 * x - one / (x + sqrt(t - one))); + } else { /* 1 + * float asinf(float x); + * double asin(double x); + * long double asinl(long double x); + * + * Description + * =========== + * + * ``asin`` computes the inverse sine (*arc sine*) of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * asin(x) \approx sin^{-1}(x) + * + * Returns + * ======= + * + * ``asin`` returns value in radians, in the range :math:`[-\frac{\pi}{2}, + * \frac{\pi}{2}]`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is not in the + * interval :math:`[-1, 1]`. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------+---------------------+--------------+--------------+---------------------+--------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<-1` | :math:`\in [-1,-0[` | :math:`-0` | :math:`+0` | :math:`\in ]+0,+1]` | :math:`>+1` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==============+=====================+==============+==============+=====================+==============+==============+==============+ + * | **asin(x)** | :math:`qNaN` | :math:`qNaN` | :math:`sin^{-1} x` | :math:`x` | :math:`sin^{-1} x` | :math:`qNaN` | :math:`qNaN` | :math:`qNaN` | + * +---------------------+--------------+--------------+---------------------+--------------+--------------+---------------------+--------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ +pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ +pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ +/* coefficient for R(x^2) */ +pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ +pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ +pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ +pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ +pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ +pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ +qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ +qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ +qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ +qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +double asin(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double t, w, p, q, c, r, s; + int32_t hx, ix; + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x3ff00000) { /* |x|>= 1 */ + uint32_t lx; + GET_LOW_WORD(lx, x); + + if (((ix - 0x3ff00000) | lx) == 0) { + /* asin(1)=+-pi/2 with inexact */ + + return x * pio2_hi + x * pio2_lo; + } + + if (isnan(x)) { + return x + x; + } + + return __raise_invalid(); /* asin(|x|>1) is NaN */ + } else if (ix < 0x3fe00000) { /* |x|<0.5 */ + if (ix < 0x3e500000) { /* if |x| < 2**-26 */ + if (x == 0.0) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexact(x); + } + } else { + t = x * x; + p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5))))); + q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4))); + w = p / q; + return x + x * w; + } + } else { + /* No action required */ + } + + /* 1> |x|>= 0.5 */ + w = one - fabs(x); + t = w * 0.5; + p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5))))); + q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4))); + s = sqrt(t); + + if (ix >= 0x3FEF3333) { /* if |x| > 0.975 */ + w = p / q; + t = pio2_hi - (2.0 * (s + s * w) - pio2_lo); + } else { + w = s; + SET_LOW_WORD(w, 0); + c = (t - w * w) / (s + w); + r = p / q; + p = 2.0 * s * r - (pio2_lo - 2.0 * c); + q = pio4_hi - 2.0 * w; + t = pio4_hi - (p - q); + } + + if (hx > 0) { + return t; + } else { + return -t; + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double asinl(long double x) +{ + return (long double) asin((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/asinhd.c b/libm/libmcs/libm/mathd/asinhd.c new file mode 100644 index 00000000..9a081891 --- /dev/null +++ b/libm/libmcs/libm/mathd/asinhd.c @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the hyperbolic arc sine of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float asinhf(float x); + * double asinh(double x); + * long double asinhl(long double x); + * + * Description + * =========== + * + * ``asinh`` computes the hyperbolic inverse sine (*hyperbolic arc sine*) of + * the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * asinh(x) \approx sinh^{-1}(x) = ln \left( x + \sqrt{x^2+1} \right) + * + * Returns + * ======= + * + * ``asinh`` returns the hyperbolic inverse sine. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+----------------------+----------------------+--------------+--------------+----------------------+----------------------+----------------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+======================+======================+==============+==============+======================+======================+======================+ + * | **asinh(x)** | :math:`-Inf` | :math:`sinh^{-1}(x)` | :math:`x` | :math:`sinh^{-1}(x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+----------------------+----------------------+--------------+--------------+----------------------+----------------------+----------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ + +double asinh(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double t, w; + int32_t hx, ix; + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x7ff00000) { + return x + x; /* x is inf or NaN */ + } + + if (ix < 0x3e300000) { /* |x|<2**-28 */ + if (x == 0.0) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexact(x); + } + } + + if (ix > 0x41b00000) { /* |x| > 2**28 */ + w = log(fabs(x)) + ln2; + } else if (ix > 0x40000000) { /* 2**28 > |x| > 2.0 */ + t = fabs(x); + w = log(2.0 * t + one / (sqrt(x * x + one) + t)); + } else { /* 2.0 > |x| > 2**-28 */ + t = x * x; + w = log1p(fabs(x) + t / (one + sqrt(one + t))); + } + + if (hx > 0) { + return w; + } else { + return -w; + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double asinhl(long double x) +{ + return (long double) asinh((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/atan2d.c b/libm/libmcs/libm/mathd/atan2d.c new file mode 100644 index 00000000..bbfdb011 --- /dev/null +++ b/libm/libmcs/libm/mathd/atan2d.c @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the arc tangent of :math:`\frac{y}{x}`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float atan2f(float y, float x); + * double atan2(double y, double x); + * long double atan2l(long double y, long double x); + * + * Description + * =========== + * + * ``atan2`` computes the inverse tangent (*arc tangent*) of the division of + * the input values. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * atan2(y, x) \approx \left\{\begin{array}{ll} + * tan^{-1}\left(\frac{y}{x}\right), & x > 0 \\ + * tan^{-1}\left(\frac{y}{x}\right) + \pi, & x < 0 \wedge y > 0 \\ + * tan^{-1}\left(\frac{y}{x}\right) - \pi, & x < 0 \wedge y < 0 \end{array}\right. + * + * For the other cases (which do not need formulae) refer to the output map below. + * + * Returns + * ======= + * + * ``atan2`` returns value in radians, in the range :math:`[-\pi, \pi]`. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. Does not raise ``divide-by-zero`` + * exception even if argument :math:`x` is zero. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------+--------------------------+-----------------------------------+--------------+--------------+-----------------------------------+--------------------------+--------------+ + * | atan2(y,x) | y | + * +--------------+--------------------------+-----------------------------------+--------------+--------------+-----------------------------------+--------------------------+--------------+ + * | x | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==============+==========================+===================================+==============+==============+===================================+==========================+==============+ + * | :math:`-Inf` | :math:`-\frac{3}{4} \pi` | :math:`-\pi` | :math:`+\pi` | :math:`+\frac{3}{4} \pi` | :math:`qNaN` | + * +--------------+--------------------------+-----------------------------------+--------------+--------------+-----------------------------------+--------------------------+ + + * | :math:`<0` | :math:`-\frac{\pi}{2}` | :math:`tan^{-1}(\frac{y}{x})-\pi` | :math:`-\pi` | :math:`+\pi` | :math:`tan^{-1}(\frac{y}{x})+\pi` | :math:`+\frac{\pi}{2}` | | + * +--------------+ +-----------------------------------+ + +-----------------------------------+ + + + * | :math:`-0` | | :math:`-\frac{\pi}{2}` | | | :math:`+\frac{\pi}{2}` | | | + * +--------------+ + +--------------+--------------+ + + + + * | :math:`+0` | | | :math:`-0` | :math:`+0` | | | | + * +--------------+ +-----------------------------------+ + +-----------------------------------+ + + + * | :math:`>0` | | :math:`tan^{-1}(\frac{y}{x})` | | | :math:`tan^{-1}(\frac{y}{x})` | | | + * +--------------+--------------------------+-----------------------------------+--------------+--------------+-----------------------------------+--------------------------+ + + * | :math:`+Inf` | :math:`-\frac{\pi}{4}` | :math:`-0` | :math:`+0` | :math:`+\frac{\pi}{4}` | | + * +--------------+--------------------------+-----------------------------------+--------------+--------------+-----------------------------------+--------------------------+--------------+ + * | :math:`NaN` | :math:`qNaN` | + * +--------------+--------------------------+-----------------------------------+--------------+--------------+-----------------------------------+--------------------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +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 */ + +double atan2(double y, double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + 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) { + default: /* FALLTHRU */ + case 0: /* FALLTHRU */ + case 1: + return y; /* atan(+-0,+anything)=+-0 */ + + case 2: + return __raise_inexact(pi); /* atan(+0,-anything) = pi */ + + case 3: + return -__raise_inexact(pi); /* atan(-0,-anything) =-pi */ + } + } + + /* when x = 0 */ + if ((ix | lx) == 0) { + return (hy < 0) ? -__raise_inexact(pi_o_2) : __raise_inexact(pi_o_2); + } + + /* when x is INF */ + if (ix == 0x7ff00000) { + if (iy == 0x7ff00000) { + switch (m) { + default: /* FALLTHRU */ + case 0: + return __raise_inexact(pi_o_4); /* atan(+INF,+INF) */ + + case 1: + return -__raise_inexact(pi_o_4); /* atan(-INF,+INF) */ + + case 2: + return __raise_inexact(3.0 * pi_o_4); /* atan(+INF,-INF) */ + + case 3: + return -__raise_inexact(3.0 * pi_o_4); /* atan(-INF,-INF) */ + } + } else { + switch (m) { + default: /* FALLTHRU */ + case 0: + return zero; /* atan(+...,+INF) */ + + case 1: + return -zero; /* atan(-...,+INF) */ + + case 2: + return __raise_inexact(pi); /* atan(+...,-INF) */ + + case 3: + return -__raise_inexact(pi); /* atan(-...,-INF) */ + } + } + } + + /* when y is INF */ + if (iy == 0x7ff00000) { + return (hy < 0) ? -__raise_inexact(pi_o_2) : __raise_inexact(pi_o_2); + } + + /* compute y/x */ + k = (iy - ix) >> 20; + + if (k > 60) { + z = __raise_inexact(pi_o_2); /* |y/x| > 2**60 */ + m &= 1; + } else if (hx < 0 && k < -60) { + z = 0.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: + return -z; /* atan(-,+) */ + + case 2: + return pi - (z - pi_lo); /* atan(+,-) */ + + default: /* case 3 */ + return (z - pi_lo) - pi; /* atan(-,-) */ + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double atan2l(long double y, long double x) +{ + return (long double) atan2((double) y, (double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/atand.c b/libm/libmcs/libm/mathd/atand.c new file mode 100644 index 00000000..286f0df1 --- /dev/null +++ b/libm/libmcs/libm/mathd/atand.c @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the arc tangent of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float atanf(float x); + * double atan(double x); + * long double atanl(long double x); + * + * Description + * =========== + * + * ``atan`` computes the inverse tangent (*arc tangent*) of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * atan(x) \approx tan^{-1}(x) + * + * Returns + * ======= + * + * ``atan`` returns value in radians, in the range :math:`[-\frac{\pi}{2}, \frac{\pi}{2}]`. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+------------------------+---------------------+--------------+--------------+---------------------+------------------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+========================+=====================+==============+==============+=====================+========================+==============+ + * | **atan(x)** | :math:`-\frac{\pi}{2}` | :math:`tan^{-1} x` | :math:`x` | :math:`tan^{-1} x` | :math:`+\frac{\pi}{2}` | :math:`qNaN` | + * +---------------------+------------------------+---------------------+--------------+--------------+---------------------+------------------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double atanhi[] = { + 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ + 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ + 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ + 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ +}; + +static const double atanlo[] = { + 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ + 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ + 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ + 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ +}; + +static const double aT[] = { + 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ + -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ + 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ + -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ + 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ + -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ + 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ + -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ + 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ + -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ + 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ +}; + +static const double one = 1.0; + +double atan(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double w, s1, s2, z; + int32_t ix, hx, id; + + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x44100000) { /* if |x| >= 2^66 */ + uint32_t low; + GET_LOW_WORD(low, x); + + if (ix > 0x7ff00000 || + (ix == 0x7ff00000 && (low != 0))) { + return x + x; /* NaN */ + } + + if (hx > 0) { + return __raise_inexact(atanhi[3]); + } else { + return -__raise_inexact(atanhi[3]); + } + } + + if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ + if (ix < 0x3e400000) { /* |x| < 2^-27 */ + if (x == 0.0) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexact(x); + } + } + + id = -1; + } else { + x = fabs(x); + + if (ix < 0x3ff30000) { /* |x| < 1.1875 */ + if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ + id = 0; + x = (2.0 * x - one) / (2.0 + x); + } else { /* 11/16<=|x|< 19/16 */ + id = 1; + x = (x - one) / (x + one); + } + } else { + if (ix < 0x40038000) { /* |x| < 2.4375 */ + id = 2; + x = (x - 1.5) / (one + 1.5 * x); + } else { /* 2.4375 <= |x| < 2^66 */ + id = 3; + x = -1.0 / x; + } + } + } + + /* end of argument reduction */ + z = x * x; + w = z * z; + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + s1 = z * (aT[0] + w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10]))))); + s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9])))); + + if (id < 0) { + return x - x * (s1 + s2); + } else { + z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x); + return (hx < 0) ? -z : z; + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double atanl(long double x) +{ + return (long double) atan((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/atanhd.c b/libm/libmcs/libm/mathd/atanhd.c new file mode 100644 index 00000000..62dda470 --- /dev/null +++ b/libm/libmcs/libm/mathd/atanhd.c @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the hyperbolic arc tangent of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float atanhf(float x); + * double atanh(double x); + * long double atanhl(long double x); + * + * Description + * =========== + * + * ``atanh`` computes the hyperbolic inverse tangent (*hyperbolic arc tangent*) + * of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * atanh(x) \approx tanh^{-1}(x) = \frac{1}{2} ln \left( \frac{1+x}{1-x} \right) + * + * Returns + * ======= + * + * ``atanh`` returns the hyperbolic inverse tangent. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is not in the + * interval :math:`[-1, 1]`. + * + * Raise ``divide by zero`` exception when the input value is :math:`-1` or + * :math:`+1`. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------+--------------+---------------------+--------------+--------------+---------------------+--------------+--------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<-1` | :math:`-1` | :math:`\in ]-1,-0[` | :math:`-0` | :math:`+0` | :math:`\in ]+0,+1[` | :math:`+1` | :math:`>+1` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==============+==============+=====================+==============+==============+=====================+==============+==============+==============+==============+ + * | **atanh(x)** | :math:`qNaN` | :math:`qNaN` | :math:`-Inf` | :math:`tanh^{-1} x` | :math:`x` | :math:`tanh^{-1} x` | :math:`+Inf` | :math:`qNaN` | :math:`qNaN` | :math:`qNaN` | + * +---------------------+--------------+--------------+--------------+---------------------+--------------+--------------+---------------------+--------------+--------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double one = 1.0; + +double atanh(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double t; + int32_t hx, ix; + uint32_t lx; + EXTRACT_WORDS(hx, lx, x); + ix = hx & 0x7fffffff; + + if ((ix | ((lx | (-lx)) >> 31)) > 0x3ff00000) { /* |x|>1 */ + if (isnan(x)) { + return x + x; + } else { + return __raise_invalid(); + } + } + + if (ix == 0x3ff00000) { + return __raise_div_by_zero(x); + } + + if (ix < 0x3e300000) { /* x<2**-28 */ + if (x == 0.0) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexact(x); + } + } + + SET_HIGH_WORD(x, ix); + + if (ix < 0x3fe00000) { /* x < 0.5 */ + t = x + x; + t = 0.5 * log1p(t + t * x / (one - x)); + } else { + t = 0.5 * log1p((x + x) / (one - x)); + } + + if (hx >= 0) { + return t; + } else { + return -t; + } +} +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double atanhl(long double x) +{ + return (long double) atanh((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/cbrtd.c b/libm/libmcs/libm/mathd/cbrtd.c new file mode 100644 index 00000000..9736b5d6 --- /dev/null +++ b/libm/libmcs/libm/mathd/cbrtd.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the cubic root of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float cbrtf(float x); + * double cbrt(double x); + * long double cbrtl(long double x); + * + * Description + * =========== + * + * ``cbrt`` computes the cubic root of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cbrt(x) \approx \sqrt[3]{x} + * + * Returns + * ======= + * + * ``cbrt`` returns the cubic root of the input value. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+---------------------+--------------+--------------+---------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=====================+==============+==============+=====================+==============+==============+ + * | **cbrt(x)** | :math:`-Inf` | :math:`\sqrt[3]{x}` | :math:`x` | :math:`\sqrt[3]{x}` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+---------------------+--------------+--------------+---------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const uint32_t +B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */ +B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */ + +static const double +C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */ +D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */ +E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */ +F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */ +G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */ + +double cbrt(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx; + double r, s, t = 0.0, w; + uint32_t sign; + uint32_t high, low; + + GET_HIGH_WORD(hx, x); + sign = hx & 0x80000000U; /* sign= sign(x) */ + hx ^= sign; + + if (hx >= 0x7ff00000) { + return (x + x); /* cbrt(NaN,INF) is itself */ + } + + GET_LOW_WORD(low, x); + + if ((hx | low) == 0) { + return (x); /* cbrt(0) is itself */ + } + + SET_HIGH_WORD(x, hx); /* x <- |x| */ + + /* rough cbrt to 5 bits */ + if (hx < 0x00100000) { /* subnormal number */ + SET_HIGH_WORD(t, 0x43500000); /* set t= 2**54 */ + t *= x; + GET_HIGH_WORD(high, t); + SET_HIGH_WORD(t, high / 3 + B2); + } else { + SET_HIGH_WORD(t, hx / 3 + B1); + } + + + /* new cbrt to 23 bits, may be implemented in single precision */ + r = t * t / x; + s = C + r * t; + t *= G + F / (s + E + D / s); + + /* chopped to 20 bits and make it larger than cbrt(x) */ + GET_HIGH_WORD(high, t); + INSERT_WORDS(t, high + 0x00000001, 0); + + + /* one step newton iteration to 53 bits with error less than 0.667 ulps */ + s = t * t; /* t*t is exact */ + r = x / s; + w = t + t; + r = (r - t) / (w + r); /* r-s is exact */ + t = t + t * r; + + /* retore the sign bit */ + GET_HIGH_WORD(high, t); + SET_HIGH_WORD(t, high | sign); + return (t); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double cbrtl(long double x) +{ + return (long double) cbrt((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/ceild.c b/libm/libmcs/libm/mathd/ceild.c new file mode 100644 index 00000000..6fbc81c4 --- /dev/null +++ b/libm/libmcs/libm/mathd/ceild.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements rounding towards positive infinity of + * :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float ceilf(float x); + * double ceil(double x); + * long double ceill(long double x); + * + * Description + * =========== + * + * ``ceil`` computes the input value rounded towards positive infinity. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * ceil(x) = \lceil x \rceil + * + * Returns + * ======= + * + * ``ceil`` returns the input value rounded towards positive infinity. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+-------------------------+--------------+--------------+-------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=========================+==============+==============+=========================+==============+==============+ + * | **ceil(x)** | :math:`-Inf` | :math:`\lceil x \rceil` | :math:`x` | :math:`\lceil x \rceil` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+-------------------------+--------------+--------------+-------------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double ceil(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t _i0, _i1, _j0; + uint32_t i, j; + EXTRACT_WORDS(_i0, _i1, x); + _j0 = ((_i0 >> 20) & 0x7ff) - 0x3ff; + + if (_j0 < 20) { + if (_j0 < 0) { /* raise inexact if x != 0 */ + if (((_i0 & 0x7fffffff) | _i1) == 0) { + return x; + } + + (void) __raise_inexact(x); + + if (_i0 < 0) { /* return 0*sign(x) if |x|<1 */ + _i0 = (int32_t)0x80000000U; + _i1 = 0; + } else { + _i0 = 0x3ff00000; + _i1 = 0; + } + } else { + i = (0x000fffff) >> _j0; + + if (((_i0 & i) | _i1) == 0) { + return x; /* x is integral */ + } + + (void) __raise_inexact(x); /* raise inexact flag */ + + if (_i0 > 0) { + _i0 += (0x00100000) >> _j0; + } + + _i0 &= (~i); + _i1 = 0; + } + } else if (_j0 > 51) { + if (_j0 == 0x400) { + return x + x; /* inf or NaN */ + } else { + return x; /* x is integral */ + } + } else { + i = ((uint32_t)0xffffffffU) >> (_j0 - 20); + + if ((_i1 & i) == 0) { + return x; /* x is integral */ + } + + (void) __raise_inexact(x); /* raise inexact flag */ + if (_i0 > 0) { + if (_j0 == 20) { + _i0 += 1; + } else { + j = _i1 + (1 << (52 - _j0)); + + if (j < (uint32_t)_i1) { + _i0 += 1; /* got a carry */ + } + + _i1 = j; + } + } + + _i1 &= (~i); + } + + INSERT_WORDS(x, _i0, _i1); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double ceill(long double x) +{ + return (long double) ceil((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/copysignd.c b/libm/libmcs/libm/mathd/copysignd.c new file mode 100644 index 00000000..ec3b4b84 --- /dev/null +++ b/libm/libmcs/libm/mathd/copysignd.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions copies the sign of :math:`y` onto :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float copysignf(float x, float y); + * double copysign(double x, double y); + * long double copysignl(long double x, long double y); + * + * Description + * =========== + * + * ``copysign`` computes the value with the magnitude of :math:`x` and sign of + * :math:`y`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * copysign(x, y) = |x| \cdot sgn\ y + * + * Returns + * ======= + * + * ``copysign`` returns the value with the magnitude of :math:`x` and sign of + * :math:`y`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Does not raise ``invalid operation`` exception on ``sNaN`` input. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+ + * | copysign(x,y) | x | + * +--------------------------+--------------------------+--------------------------+ + * | y | :math:`\neq NaN` | :math:`NaN` | + * +==========================+==========================+==========================+ + * | :math:`-NaN` | :math:`-|x|` | :math:`qNaN` | + * +--------------------------+ + + + * | :math:`-Inf` | | | + * +--------------------------+ + + + * | :math:`<0` | | | + * +--------------------------+ + + + * | :math:`-0` | | | + * +--------------------------+--------------------------+ + + * | :math:`+0` | :math:`|x|` | | + * +--------------------------+ + + + * | :math:`>0` | | | + * +--------------------------+ + + + * | :math:`+Inf` | | | + * +--------------------------+ + + + * | :math:`+NaN` | | | + * +--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double copysign(double x, double y) +{ + uint32_t hx, hy; + GET_HIGH_WORD(hx, x); + GET_HIGH_WORD(hy, y); + SET_HIGH_WORD(x, (hx & 0x7fffffffU) | (hy & 0x80000000U)); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double copysignl(long double x, long double y) +{ + return (long double) copysign((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/cosd.c b/libm/libmcs/libm/mathd/cosd.c new file mode 100644 index 00000000..2a6d9d3f --- /dev/null +++ b/libm/libmcs/libm/mathd/cosd.c @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the cosine of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float cosf(float x); + * double cos(double x); + * long double cosl(long double x); + * + * Description + * =========== + * + * ``cos`` computes the cosine of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cos(x) \approx cos(x) + * + * Returns + * ======= + * + * ``cos`` returns the cosine of the input value, in the range :math:`[-1, 1]`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is infinite. + * + * Output map + * ========== + * + * +---------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+================+================+================+================+================+================+================+ + * | **cos(x)** | :math:`qNaN` | :math:`cos(x)` | :math:`1` | :math:`cos(x)` | :math:`qNaN` | :math:`qNaN` | + * +---------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+ + * + */ + +#include +#include "../common/tools.h" +#include "internal/trigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double cos(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double y[2], z = 0.0; + int32_t n, ix; + + /* High word of x. */ + GET_HIGH_WORD(ix, x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + + if(ix <= 0x3fe921fb) { + if(ix < 0x3e46a09e) { /* if x < 2**-27 * sqrt(2) */ + if (x == 0.0) { /* return 1 inexact except 0 */ + return 1.0; + } else { + return __raise_inexactf(1.0); + } + } + + return __cos(x, z); + } + + /* cos(Inf or NaN) is NaN */ + else if (ix >= 0x7ff00000) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalid(); + } + } + + /* argument reduction needed */ + else { + n = __rem_pio2(x, y); + + switch (n & 3) { + case 0: + return __cos(y[0], y[1]); + + case 1: + return -__sin(y[0], y[1], 1); + + case 2: + return -__cos(y[0], y[1]); + + default: + return __sin(y[0], y[1], 1); + } + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double cosl(long double x) +{ + return (long double) cos((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/coshd.c b/libm/libmcs/libm/mathd/coshd.c new file mode 100644 index 00000000..1ed4033a --- /dev/null +++ b/libm/libmcs/libm/mathd/coshd.c @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the hyperbolic cosine of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float coshf(float x); + * double cosh(double x); + * long double coshl(long double x); + * + * Description + * =========== + * + * ``cosh`` computes the hyperbolic cosine of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * cosh(x) \approx cosh(x) = \frac{e^x+e^{-x}}{2} + * + * Returns + * ======= + * + * ``cosh`` returns the hyperbolic cosine, in the range :math:`\mathbb{F}_{>=1}`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the magnitude of the input value is too large. + * + * Output map + * ========== + * + * +---------------------+--------------+-----------------+--------------+--------------+-----------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=================+==============+==============+=================+==============+==============+ + * | **cosh(x)** | :math:`+Inf` | :math:`cosh(x)` | :math:`1` | :math:`cosh(x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+-----------------+--------------+--------------+-----------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double one = 1.0, half = 0.5; + +double cosh(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + 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)0x8fb9f87dU)) { + w = exp(half * fabs(x)); + t = half * w; + return t * w; + } + + /* |x| > overflowthresold, cosh(x) overflow */ + return __raise_overflow(1.0); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double coshl(long double x) +{ + return (long double) cosh((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/erfcd.c b/libm/libmcs/libm/mathd/erfcd.c new file mode 100644 index 00000000..f201af1f --- /dev/null +++ b/libm/libmcs/libm/mathd/erfcd.c @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the complementary error function of + * :math:`x` and is equal to :math:`1 -` erf(:math:`x`). + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float erfcf(float x); + * double erfc(double x); + * long double erfcl(long double x); + * + * Description + * =========== + * + * ``erfc`` computes the complementary error function of :math:`x`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * erfc(x) \approx 1 - \frac{2}{\sqrt{\pi}}\int_{0}^{x}e^{-t^2}dt + * + * Returns + * ======= + * + * ``erfc`` returns the complementary error function of :math:`x`, in the range + * :math:`[+0.0, 2.0]`. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+------------------------------------------------------+--------------+--------------+------------------------------------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+======================================================+==============+==============+======================================================+==============+==============+ + * | **erfc(x)** | :math:`+2` | :math:`1-\frac{2}{\sqrt{\pi}}\int_{0}^{x}e^{-t^2}dt` | :math:`+1` | :math:`1-\frac{2}{\sqrt{\pi}}\int_{0}^{x}e^{-t^2}dt` | :math:`+0` | :math:`qNaN` | + * +---------------------+--------------+------------------------------------------------------+--------------+--------------+------------------------------------------------------+--------------+--------------+ + * + */ + +/* 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 +#include "../common/tools.h" +#include "internal/errorfunctiond.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ +erx = 8.45062911510467529297e-01; /* 0x3FEB0AC1, 0x60000000 */ + +double erfc(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, ix; + double R, S, P, Q, s, y, z, r; + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x7ff00000) { + if (isnan(x)) { /* erfc(nan) = nan */ + return x + x; + } else if (hx > 0) { /* erfc(+inf) = 0 */ + return 0.0; + } else { /* erfc(-inf) = 2 */ + return two; + } + } + + if (ix < 0x3feb0000) { /* |x|<0.84375 */ + if (ix < 0x3c700000) { /* |x|<2**-56 */ + return __raise_inexact(one); + } + + y = __erf_y(x); + + 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 = __erf_P(s); + Q = __erf_Q(s); + + 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 = __erf_Ra(s); + S = __erf_Sa(s); + } else { /* |x| >= 1/.35 ~ 2.857143 */ + if (hx < 0 && ix >= 0x40180000) { + return __raise_inexact(two); /* x < -6 */ + } + + R = __erf_Rb(s); + S = __erf_Sb(s); + } + + z = x; + SET_LOW_WORD(z, 0); + r = exp(-z * z - 0.5625) * exp((z - x) * (z + x) + R / S); + + if (hx > 0) { + return r / x; + } else { + return two - r / x; + } + } else { + if (hx > 0) { + return __raise_underflow(0.0); + } else { + return __raise_inexact(two); + } + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double erfcl(long double x) +{ + return (long double) erfc((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/erfd.c b/libm/libmcs/libm/mathd/erfd.c new file mode 100644 index 00000000..7b5ff4aa --- /dev/null +++ b/libm/libmcs/libm/mathd/erfd.c @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the error function of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float erff(float x); + * double erf(double x); + * long double erfl(long double x); + * + * Description + * =========== + * + * ``erf`` computes the error function of :math:`x`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * erf(x) \approx \frac{2}{\sqrt{\pi}}\int_{0}^{x}e^{-t^2}dt + * + * Returns + * ======= + * + * ``erf`` returns the error function of :math:`x`, in the range + * :math:`[-1.0, +1.0]`. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+-----------------------------------------------------+--------------+--------------+-----------------------------------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=====================================================+==============+==============+=====================================================+==============+==============+ + * | **erf(x)** | :math:`-Inf` | :math:`\frac{2}{\sqrt{\pi}}\int_{0}^{x}e^{-t^2}dt` | :math:`x` | :math:`\frac{2}{\sqrt{\pi}}\int_{0}^{x}e^{-t^2}dt` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+-----------------------------------------------------+--------------+--------------+-----------------------------------------------------+--------------+--------------+ + * + */ + +/* 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 +#include "../common/tools.h" +#include "internal/errorfunctiond.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ +efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */ +efx8 = 1.02703333676410069053e+00; /* 0x3FF06EBA, 0x8214DB69 */ + +double erf(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, ix; + double R, S, P, Q, s, z, r; + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x7ff00000) { + if (isnan(x)) { /* erf(nan) = nan */ + return x + x; + } else if (hx > 0) { /* erf(+inf) = +1 */ + return 1.0; + } else { /* erf(-inf) = -1 */ + return -1.0; + } + } + + 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; + } + + return x + x * __erf_y(x); + } + + if (ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ + s = fabs(x) - one; + P = __erf_P(s); + Q = __erf_Q(s); + + if (hx >= 0) { + return erx + P / Q; + } else { + return -erx - P / Q; + } + } + + if (ix >= 0x40180000) { /* inf>|x|>=6 */ + if (hx >= 0) { + return __raise_inexact(one); + } else { + return -__raise_inexact(one); + } + } + + x = fabs(x); + s = one / (x * x); + + if (ix < 0x4006DB6E) { /* |x| < 1/0.35 */ + R = __erf_Ra(s); + S = __erf_Sa(s); + } else { /* |x| >= 1/0.35 */ + R = __erf_Rb(s); + S = __erf_Sb(s); + } + + z = x; + SET_LOW_WORD(z, 0); + r = exp(-z * z - 0.5625) * exp((z - x) * (z + x) + R / S); + + if (hx >= 0) { + return one - r / x; + } else { + return r / x - one; + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double erfl(long double x) +{ + return (long double) erf((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/exp2d.c b/libm/libmcs/libm/mathd/exp2d.c new file mode 100644 index 00000000..dbe51eee --- /dev/null +++ b/libm/libmcs/libm/mathd/exp2d.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements :math:`2` powered by :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float exp2f(float x); + * double exp2(double x); + * long double exp2l(long double x); + * + * Description + * =========== + * + * ``exp2`` computes :math:`2` powered by the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * exp2(x) \approx 2^x + * + * Returns + * ======= + * + * ``exp2`` returns :math:`2` powered by :math:`x`, in the range + * :math:`\mathbb{F}^{+}_0`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the magnitude of the input value is too + * large. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==============+==============+==============+==============+==============+==============+ + * | **exp2(x)** | :math:`+0` | :math:`2^x` | :math:`+1` | :math:`2^x` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double exp2(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return pow(2.0, x); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double exp2l(long double x) +{ + return (long double) exp2((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/expd.c b/libm/libmcs/libm/mathd/expd.c new file mode 100644 index 00000000..e7af6ae1 --- /dev/null +++ b/libm/libmcs/libm/mathd/expd.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the exponential function, that is + * :math:`e` powered by :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float expf(float x); + * double exp(double x); + * long double expl(long double x); + * + * Description + * =========== + * + * ``exp`` computes :math:`e` powered by the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * exp(x) \approx e^x + * + * Returns + * ======= + * + * ``exp`` returns :math:`e` powered by :math:`x`, in the range + * :math:`\mathbb{F}^{+}_0`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the magnitude of the input value is too + * large. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==============+==============+==============+==============+==============+==============+ + * | **exp(x)** | :math:`+0` | :math:`e^x` | :math:`+1` | :math:`e^x` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +one = 1.0, +zero = 0.0, +halF[2] = {0.5, -0.5,}, +twom1000 = 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/ +o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ +u_threshold = -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */ +ln2HI[2] = { + 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ + -6.93147180369123816490e-01, /* 0xbfe62e42, 0xfee00000 */ +}, +ln2LO[2] = { + 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ + -1.90821492927058770002e-10, /* 0xbdea39ef, 0x35793c76 */ +}, +invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ + +double exp(double x) /* default IEEE double exp */ +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double y, c, t; + double hi = 0.0; + double lo = 0.0; + int32_t k = 0; + int32_t xsb; + uint32_t hx; + + GET_HIGH_WORD(hx, x); + xsb = (hx >> 31) & 1; /* sign bit of x */ + hx &= 0x7fffffff; /* high word of |x| */ + + /* filter out non-finite argument */ + if (hx >= 0x40862E42) { /* if |x|>=709.78... */ + if (hx >= 0x7ff00000) { + uint32_t lx; + GET_LOW_WORD(lx, x); + + if (((hx & 0xfffff) | lx) != 0) { + return x + x; /* NaN */ + } else { /* exp(+-inf)={inf,0} */ + return (xsb == 0) ? x : zero; + } + } + + if (x > o_threshold) { + return __raise_overflow(one); /* overflow */ + } + + if (x < u_threshold) { + return __raise_underflow(zero); /* underflow */ + } + } + + /* argument reduction */ + if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ + if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ + hi = x - ln2HI[xsb]; + lo = ln2LO[xsb]; + k = 1 - xsb - xsb; + } else { + k = invln2 * x + halF[xsb]; + t = k; + hi = x - t * ln2HI[0]; /* t*ln2HI is exact here */ + lo = t * ln2LO[0]; + } + + x = hi - lo; + } else if (hx < 0x3df00000) { /* when |x|<2**-32 */ + if (x == 0.0) { /* return 1 inexact except 0 */ + return one; + } else { + return __raise_inexact(one + x); + } + } else { + /* No action required */ + } + + /* x is now in primary range */ + t = x * x; + c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + + if (k == 0) { + return one - ((x * c) / (c - 2.0) - x); + } else { + y = one - ((lo - (x * c) / (2.0 - c)) - hi); + } + + if (k >= -1021) { + uint32_t hy; + GET_HIGH_WORD(hy, y); + SET_HIGH_WORD(y, hy + (((uint32_t)k) << 20)); /* add k to y's exponent */ + return y; + } else { + uint32_t hy; + GET_HIGH_WORD(hy, y); + SET_HIGH_WORD(y, hy + (((uint32_t)k + 1000U) << 20)); /* add k to y's exponent */ + return y * twom1000; + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double expl(long double x) +{ + return (long double) exp((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/expm1d.c b/libm/libmcs/libm/mathd/expm1d.c new file mode 100644 index 00000000..afade950 --- /dev/null +++ b/libm/libmcs/libm/mathd/expm1d.c @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the exponential function minus + * :math:`1`, that is :math:`e` powered by :math:`x` before subtracting + * :math:`1`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float expm1f(float x); + * double expm1(double x); + * long double expm1l(long double x); + * + * Description + * =========== + * + * ``expm1`` computes :math:`e` powered by the input value subtracted by + * :math:`1`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * expm1(x) \approx e^x - 1 + * + * Returns + * ======= + * + * ``expm1`` returns :math:`e` powered by :math:`x` subtracted by :math:`1`, in + * the range :math:`\mathbb{F}_{>=-1}`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the magnitude of the input value is too + * large. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+===============+===============+===============+===============+===============+===============+===============+ + * | **expm1(x)** | :math:`-1` | :math:`e^x-1` | :math:`+0` | :math:`e^x-1` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ + * + */ + +/* expm1(x) + * Returns exp(x)-1, the exponential of x minus 1. + * + * Method + * 1. Argument reduction: + * Given x, find r and integer k such that + * + * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 + * + * Here a correction term c will be computed to compensate + * the error in r when rounded to a floating-point number. + * + * 2. Approximating expm1(r) by a special rational function on + * the interval [0,0.34658]: + * Since + * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... + * we define R1(r*r) by + * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) + * That is, + * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) + * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) + * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... + * We use a special Remez algorithm on [0,0.347] to generate + * a polynomial of degree 5 in r*r to approximate R1. The + * maximum error of this polynomial approximation is bounded + * by 2**-61. In other words, + * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 + * where Q1 = -1.6666666666666567384E-2, + * Q2 = 3.9682539681370365873E-4, + * Q3 = -9.9206344733435987357E-6, + * Q4 = 2.5051361420808517002E-7, + * Q5 = -6.2843505682382617102E-9; + * (where z=r*r, and the values of Q1 to Q5 are listed below) + * with error bounded by + * | 5 | -61 + * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 + * | | + * + * expm1(r) = exp(r)-1 is then computed by the following + * specific way which minimize the accumulation rounding error: + * 2 3 + * r r [ 3 - (R1 + R1*r/2) ] + * expm1(r) = r + --- + --- * [--------------------] + * 2 2 [ 6 - r*(3 - R1*r/2) ] + * + * To compensate the error in the argument reduction, we use + * expm1(r+c) = expm1(r) + c + expm1(r)*c + * ~ expm1(r) + c + r*c + * Thus c+r*c will be added in as the correction terms for + * expm1(r+c). Now rearrange the term to avoid optimization + * screw up: + * ( 2 2 ) + * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) + * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) + * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) + * ( ) + * + * = r - E + * 3. Scale back to obtain expm1(x): + * From step 1, we have + * expm1(x) = either 2^k*[expm1(r)+1] - 1 + * = or 2^k*[expm1(r) + (1-2^-k)] + * 4. Implementation notes: + * (A). To save one multiplication, we scale the coefficient Qi + * to Qi*2^i, and replace z by (x^2)/2. + * (B). To achieve maximum accuracy, we compute expm1(x) by + * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) + * (ii) if k=0, return r-E + * (iii) if k=-1, return 0.5*(r-E)-0.5 + * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) + * else return 1.0+2.0*(r-E); + * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) + * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else + * (vii) return 2^k(1-((E+2^-k)-r)) + * + * Special cases: + * expm1(INF) is INF, expm1(NaN) is NaN; + * expm1(-INF) is -1, and + * for finite argument, only expm1(0)=0 is exact. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Misc. info. + * For IEEE double + * if x > 7.09782712893383973096e+02 then expm1(x) overflow + * + * 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 +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +one = 1.0, +o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ +ln2_hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ +ln2_lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ +invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ +/* scaled coefficients related to expm1 */ +Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ +Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ +Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ +Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ +Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ + +double expm1(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double y, hi, lo, c, t, e, hxs, hfx, r1; + int32_t k, xsb; + uint32_t hx; + + c = NAN; /* initial value of c is never actually used */ + + GET_HIGH_WORD(hx, x); + xsb = hx & 0x80000000U; /* sign bit of x */ + + hx &= 0x7fffffff; /* high word of |x| */ + + /* filter out huge and non-finite argument */ + if (hx >= 0x4043687A) { /* if |x|>=56*ln2 */ + if (hx >= 0x40862E42) { /* if |x|>=709.78... */ + if (hx >= 0x7ff00000) { + uint32_t low; + GET_LOW_WORD(low, x); + + if (((hx & 0xfffff) | low) != 0) { + return x + x; /* NaN */ + } else { /* exp(+-inf)={inf,-1} */ + return (xsb == 0) ? x : -1.0; + } + } + + if (x > o_threshold) { + return __raise_overflow(one); /* overflow */ + } + } + + if (xsb != 0) { /* x < -56*ln2, return -1.0 with inexact */ + return -__raise_inexact(one); /* return -1 */ + } + } + + /* argument reduction */ + if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ + if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ + if (xsb == 0) { + hi = x - ln2_hi; + lo = ln2_lo; + k = 1; + } else { + hi = x + ln2_hi; + lo = -ln2_lo; + k = -1; + } + } else { + k = invln2 * x + ((xsb == 0) ? 0.5 : -0.5); + t = k; + hi = x - t * ln2_hi; /* t*ln2_hi is exact here */ + lo = t * ln2_lo; + } + + x = hi - lo; + c = (hi - x) - lo; + } else if (hx < 0x3c900000) { /* when |x|<2**-54, return x */ + if (x == 0.0) { + return x; + } else { /* return x with inexact flags when x!=0 */ + return __raise_inexact(x); + } + } else { + k = 0; + } + + /* x is now in primary range */ + hfx = 0.5 * x; + hxs = x * hfx; + r1 = one + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5)))); + t = 3.0 - r1 * hfx; + e = hxs * ((r1 - t) / (6.0 - x * t)); + + if (k == 0) { + return x - (x * e - hxs); /* c is 0 */ + } else { + e = (x * (e - c) - c); + e -= hxs; + + if (k == -1) { + return 0.5 * (x - e) - 0.5; + } + + if (k == 1) { + if (x < -0.25) { + return -2.0 * (e - (x + 0.5)); + } else { + return one + 2.0 * (x - e); + } + } + + if (k <= -2 || k > 56) { /* suffice to return exp(x)-1 */ + uint32_t high; + y = one - (e - x); + GET_HIGH_WORD(high, y); + SET_HIGH_WORD(y, high + (((uint32_t)k) << 20)); /* add k to y's exponent */ + return y - one; + } + + t = one; + + if (k < 20) { + uint32_t high; + SET_HIGH_WORD(t, 0x3ff00000 - (0x200000 >> k)); /* t=1-2^-k */ + y = t - (e - x); + GET_HIGH_WORD(high, y); + SET_HIGH_WORD(y, high + (k << 20)); /* add k to y's exponent */ + } else { + uint32_t high; + SET_HIGH_WORD(t, ((0x3ff - k) << 20)); /* 2^-k */ + y = x - (e + t); + y += one; + GET_HIGH_WORD(high, y); + SET_HIGH_WORD(y, high + (k << 20)); /* add k to y's exponent */ + } + } + + return y; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double expm1l(long double x) +{ + return (long double) expm1((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/fabsd.c b/libm/libmcs/libm/mathd/fabsd.c new file mode 100644 index 00000000..b6d6740d --- /dev/null +++ b/libm/libmcs/libm/mathd/fabsd.c @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the absolute value of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float fabsf(float x); + * double fabs(double x); + * long double fabsl(long double x); + * + * Description + * =========== + * + * ``fabs`` computes the absolute value of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * fabs(x) = |x| + * + * Returns + * ======= + * + * ``fabs`` returns the absolute value of the input value. + * + * ``fabs`` does not differentiate between different types of ``NaN``, as such + * if the input is ``sNaN`` so will the output, only the sign bit may change. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Does not raise ``invalid operation`` exception on ``sNaN`` input. + * + * Output map + * ========== + * + * +---------------------+--------------+---------------------+--------------+--------------+---------------------+--------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`qNaN` | :math:`sNaN` | + * +=====================+==============+=====================+==============+==============+=====================+==============+==============+==============+ + * | **fabs(x)** | :math:`+Inf` | :math:`-x` | :math:`+0` | :math:`x` | :math:`+Inf` | :math:`qNaN` | :math:`sNaN` | + * +---------------------+--------------+---------------------+--------------+--------------+---------------------+--------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double fabs(double x) +{ + uint32_t high; + GET_HIGH_WORD(high, x); + SET_HIGH_WORD(x, high & 0x7fffffff); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double fabsl(long double x) +{ + return (long double) fabs((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/fdimd.c b/libm/libmcs/libm/mathd/fdimd.c new file mode 100644 index 00000000..2ddd1b44 --- /dev/null +++ b/libm/libmcs/libm/mathd/fdimd.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. */ + +/** + * + * This family of functions implements the positive difference value of + * :math:`x` subtracted by :math:`y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float fdimf(float x, float y); + * double fdim(double x, double y); + * long double fdiml(long double x, long double y); + * + * Description + * =========== + * + * ``fdim`` computes the positive difference value of :math:`x` subtracted by + * :math:`y`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * fdim(x, y) \approx \left\{\begin{array}{ll} x - y, & x > y \\ 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``fdim`` returns the positive difference value of :math:`x` subtracted by + * :math:`y`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the result overflows. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | fdim(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`+0` | :math:`+Inf` | :math:`qNaN` | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | :math:`<0` | | :math:`fdim(x, y)` | :math:`x - y` | :math:`x - y` | :math:`+Inf` | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+ + + + + * | :math:`-0` | | :math:`+0` | :math:`+0` | | | | + * +--------------------------+ + + + + + + + * | :math:`+0` | | | | | | | + * +--------------------------+ + + +--------------------------+ + + + * | :math:`>0` | | | | :math:`fdim(x, y)` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`+Inf` | | :math:`+0` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double fdim(double x, double y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + if (isnan(x) || isnan(y)) { + return x * y; + } + + return x > y ? x - y : 0.0; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double fdiml(long double x, long double y) +{ + return (long double) fdim((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/floord.c b/libm/libmcs/libm/mathd/floord.c new file mode 100644 index 00000000..c09662ba --- /dev/null +++ b/libm/libmcs/libm/mathd/floord.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements rounding towards negative infinity of + * :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float floorf(float x); + * double floor(double x); + * long double floorl(long double x); + * + * Description + * =========== + * + * ``floor`` computes the input value rounded towards negative infinity. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * floor(x) = \lfloor x \rfloor + * + * Returns + * ======= + * + * ``floor`` returns the input value rounded towards negative infinity. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+---------------------------+--------------+--------------+---------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+===========================+==============+==============+===========================+==============+==============+ + * | **floor(x)** | :math:`-Inf` | :math:`\lfloor x \rfloor` | :math:`x` | :math:`\lfloor x \rfloor` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+---------------------------+--------------+--------------+---------------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double floor(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t _i0, _i1, _j0; + uint32_t i, j; + EXTRACT_WORDS(_i0, _i1, x); + _j0 = ((_i0 >> 20) & 0x7ff) - 0x3ff; + + if (_j0 < 20) { + if (_j0 < 0) { /* raise inexact if x != 0 */ + if (((_i0 & 0x7fffffff) | _i1) == 0) { + return x; + } + + (void) __raise_inexact(x); + + if (_i0 >= 0) { + _i0 = _i1 = 0; + } else { + _i0 = (int32_t)0xbff00000U; + _i1 = 0; + } + } else { + i = (0x000fffff) >> _j0; + + if (((_i0 & i) | _i1) == 0) { + return x; /* x is integral */ + } + + (void) __raise_inexact(x); + + if (_i0 < 0) { + _i0 += (0x00100000) >> _j0; + } + + _i0 &= (~i); + _i1 = 0; + } + } else if (_j0 > 51) { + if (_j0 == 0x400) { + return x + x; /* inf or NaN */ + } else { + return x; /* x is integral */ + } + } else { + i = ((uint32_t)0xffffffffU) >> (_j0 - 20); + + if ((_i1 & i) == 0) { + return x; /* x is integral */ + } + + (void) __raise_inexact(x); + + if (_i0 < 0) { + if (_j0 == 20) { + _i0 += 1; + } else { + j = _i1 + (1 << (52 - _j0)); + + if (j < (uint32_t)_i1) { + _i0 += 1 ; /* got a carry */ + } + + _i1 = j; + } + } + + _i1 &= (~i); + } + + INSERT_WORDS(x, _i0, _i1); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double floorl(long double x) +{ + return (long double) floor((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/fmad.c b/libm/libmcs/libm/mathd/fmad.c new file mode 100644 index 00000000..07ce138b --- /dev/null +++ b/libm/libmcs/libm/mathd/fmad.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This family of functions fuses the multiplication of :math:`x` and :math:`y` + * with the addition of :math:`z`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float fmaf(float x, float y, float z); + * double fma(double x, double y, double z); + * long double fmal(long double x, long double y, long double z); + * + * Description + * =========== + * + * ``fma`` computes the multiplication of :math:`x` and :math:`y` with the + * addition of :math:`z`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * fma(x, y, z) = x \cdot y + z + * + * Returns + * ======= + * + * ``fma`` returns the multiplication of :math:`x` and :math:`y` with the + * addition of :math:`z`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when either :math:`x` or :math:`y` is + * zero and the other is infinity (regardless of the value in :math:`z`), or + * when :math:`x \cdot y` is infinity and :math:`z` is infinity with the + * opposite sign. + * + * Raise ``overflow`` exception if the result overflows. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | :math:`x \cdot y` | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`+Inf` | :math:`+Inf` | :math:`qNaN` | :math:`+Inf` | :math:`+Inf` | :math:`qNaN` | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`<0` | | :math:`x \cdot y` | :math:`+0` | :math:`-0` | :math:`x \cdot y` | | | + * +--------------------------+--------------------------+--------------------------+ + +--------------------------+--------------------------+ + + * | :math:`-0` | :math:`qNaN` | :math:`+0` | | | :math:`-0` | :math:`qNaN` | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`+0` | | :math:`-0` | :math:`-0` | :math:`+0` | :math:`+0` | | | + * +--------------------------+--------------------------+--------------------------+ + +--------------------------+--------------------------+ + + * | :math:`>0` | | :math:`x \cdot y` | | | :math:`x \cdot y` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`+Inf` | :math:`-Inf` | :math:`-Inf` | :math:`qNaN` | :math:`-Inf` | :math:`-Inf` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | fma(x,y,z) | z | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | :math:`x \cdot y` | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`-Inf` | :math:`-Inf` | :math:`qNaN` | :math:`qNaN` | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`<0` | | :math:`x \cdot y + z` | :math:`x \cdot y` | :math:`x \cdot y + z` | :math:`+Inf` | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`-0` | | :math:`z` | :math:`-0` | :math:`+0` | :math:`z` | | | + * +--------------------------+ + +--------------------------+--------------------------+ + + + + * | :math:`+0` | | | :math:`+0` | :math:`+0` | | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`>0` | | :math:`x \cdot y + z` | :math:`x \cdot y` | :math:`x \cdot y + z` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`+Inf` | :math:`qNaN` | :math:`+Inf` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | :math:`NaN` | :math:`qNaN` | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double fma(double x, double y, double z) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; + z *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return x * y + z; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double fmal(long double x, long double y, long double z) +{ + return (long double) fma((double) x, (double) y, (double) z); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/fmaxd.c b/libm/libmcs/libm/mathd/fmaxd.c new file mode 100644 index 00000000..85cc08eb --- /dev/null +++ b/libm/libmcs/libm/mathd/fmaxd.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. */ + +/** + * + * This family of functions determines the maximum numerical value of :math:`x` and :math:`y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float fmaxf(float x, float y); + * double fmax(double x, double y); + * long double fmaxl(long double x, long double y); + * + * Description + * =========== + * + * ``fmax`` computes the maximum numerical value of :math:`x` and :math:`y`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * fmax(x, y) = \left\{\begin{array}{ll} x, & x > y \\ y, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``fmax`` returns the maximum numerical value of :math:`x` and :math:`y`. + * + * Exceptions + * ========== + * + * Does raise invalid exception in case one of the parameters is :math:`sNaN`. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | fmax(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`qNaN` | :math:`sNaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`y` | :math:`x` | :math:`x` | :math:`x` | :math:`x` | :math:`y` | :math:`qNaN` | + * +--------------------------+ +--------------------------+ + + + + + + * | :math:`<0` | | :math:`fmax(x, y)` | | | | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+ + + + + + * | :math:`-0` | | :math:`y` | | | | | + * +--------------------------+ + + + + + + + * | :math:`+0` | | | | | | | + * +--------------------------+ + +--------------------------+ + + + + * | :math:`>0` | | | :math:`fmax(x, y)` | | | | + * +--------------------------+ + +--------------------------+--------------------------+ + + + * | :math:`+Inf` | | | :math:`y` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`qNaN` | :math:`x` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`sNaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double fmax(double x, double y) +{ + if (isnan(x)) { + if (__issignaling(x) != 0 || __issignaling(y) != 0) { + return x * y; + } +#ifdef __LIBMCS_FPU_DAZ + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return y; + } + + if (isnan(y)) { + if (__issignaling(y) != 0) { + return x * y; + } +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return x; + } + +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return x > y ? x : y; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double fmaxl(long double x, long double y) +{ + return (long double) fmax((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/fmind.c b/libm/libmcs/libm/mathd/fmind.c new file mode 100644 index 00000000..4c446cee --- /dev/null +++ b/libm/libmcs/libm/mathd/fmind.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. */ + +/** + * + * This family of functions determines the minimum numerical value of :math:`x` and :math:`y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float fminf(float x, float y); + * double fmin(double x, double y); + * long double fminl(long double x, long double y); + * + * Description + * =========== + * + * ``fmin`` computes the minimum numerical value of :math:`x` and :math:`y`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * fmin(x, y) = \left\{\begin{array}{ll} x, & x < y \\ y, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``fmin`` returns the minimum numerical value of :math:`x` and :math:`y`. + * + * Exceptions + * ========== + * + * Does raise invalid exception in case one of the parameters is :math:`sNaN`. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | fmin(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`qNaN` | :math:`sNaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`y` | :math:`y` | :math:`y` | :math:`y` | :math:`qNaN` | + * +--------------------------+--------------------------+--------------------------+ + + + + + * | :math:`<0` | :math:`x` | :math:`fmin(x, y)` | | | | | + * +--------------------------+ +--------------------------+ + + + + + * | :math:`-0` | | :math:`x` | | | | | + * +--------------------------+ + + + + + + + * | :math:`+0` | | | | | | | + * +--------------------------+ + +--------------------------+--------------------------+--------------------------+ + + + + * | :math:`>0` | | | :math:`x` | :math:`fmin(x, y)` | | | | + * +--------------------------+ + + +--------------------------+ + + + + * | :math:`+Inf` | | | | :math:`x` | | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`qNaN` | :math:`x` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`sNaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double fmin(double x, double y) +{ + if (isnan(x)) { + if (__issignaling(x) != 0 || __issignaling(y) != 0) { + return x * y; + } +#ifdef __LIBMCS_FPU_DAZ + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return y; + } + + if (isnan(y)) { + if (__issignaling(y) != 0) { + return x * y; + } +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return x; + } + +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return x < y ? x : y; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double fminl(long double x, long double y) +{ + return (long double) fmin((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/fmodd.c b/libm/libmcs/libm/mathd/fmodd.c new file mode 100644 index 00000000..9ea0e5f2 --- /dev/null +++ b/libm/libmcs/libm/mathd/fmodd.c @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the floating-point remainder of + * :math:`x` divided by :math:`y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float fmodf(float x, float y); + * double fmod(double x, double y); + * long double fmodl(long double x, long double y); + * + * Description + * =========== + * + * ``fmod`` computes the floating-point remainder of :math:`x` divided by + * :math:`y`. + * + * The ``fmod`` and ``remainder`` procedures are rather similar, but not the + * same, see examples: + * + * +----------------+----------------+----------------+----------------+ + * | x | y | fmod | remainder | + * +================+================+================+================+ + * | :math:`+2.456` | :math:`+2.0` | :math:`+0.456` | :math:`+0.456` | + * +----------------+----------------+----------------+----------------+ + * | :math:`+3.456` | :math:`+2.0` | :math:`+1.456` | :math:`-0.544` | + * +----------------+----------------+----------------+----------------+ + * | :math:`-2.456` | :math:`+2.0` | :math:`-0.456` | :math:`-0.456` | + * +----------------+----------------+----------------+----------------+ + * | :math:`-3.456` | :math:`+2.0` | :math:`-1.456` | :math:`+0.544` | + * +----------------+----------------+----------------+----------------+ + * | :math:`+2.456` | :math:`-2.0` | :math:`+0.456` | :math:`+0.456` | + * +----------------+----------------+----------------+----------------+ + * | :math:`+3.456` | :math:`-2.0` | :math:`+1.456` | :math:`-0.544` | + * +----------------+----------------+----------------+----------------+ + * | :math:`-2.456` | :math:`-2.0` | :math:`-0.456` | :math:`-0.456` | + * +----------------+----------------+----------------+----------------+ + * | :math:`-3.456` | :math:`-2.0` | :math:`-1.456` | :math:`+0.544` | + * +----------------+----------------+----------------+----------------+ + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * fmod(x, y) = x - n \cdot y \wedge n \in \mathbb{Z} \wedge |fmod(x, y)| < |y| \wedge \frac{f(x, y)}{|f(x, y)|} = \frac{x}{|x|} + * + * Returns + * ======= + * + * ``fmod`` returns the floating-point remainder of :math:`x` divided by :math:`y`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when :math:`x` is infinite or + * :math:`y` is zero. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | fmod(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`qNaN` | :math:`x` | :math:`qNaN` | :math:`qNaN` | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`<0` | | :math:`fmod(x, y)` | :math:`x` | :math:`fmod(x, y)` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`-0` | | :math:`qNaN` | | | + * +--------------------------+ + + + + + * | :math:`+0` | | | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`>0` | | :math:`fmod(x, y)` | :math:`x` | :math:`fmod(x, y)` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`+Inf` | | :math:`x` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double Zero[] = {0.0, -0.0,}; + +double fmod(double x, double y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t n, hx, hy, hz, ix, iy, sx, i; + uint32_t lx, ly, lz; + + EXTRACT_WORDS(hx, lx, x); + EXTRACT_WORDS(hy, ly, y); + sx = hx & 0x80000000U; /* sign of x */ + hx ^= sx; /* |x| */ + hy &= 0x7fffffff; /* |y| */ + + /* purge off exception values */ + if (hx >= 0x7ff00000 || hy >= 0x7ff00000) { /* x or y is +-Inf/NaN */ + if (hx == 0x7ff00000 && lx == 0) { /* x is +-Inf */ + return __raise_invalid(); + } else if (isnan(x) || isnan(y)) { /* x or y is NaN */ + return x + y; + } else { + /* No action required */ + } + } else if ((hy | ly) == 0) { /* y is +-0 */ + return __raise_invalid(); + } else { + /* No action required */ + } + + if (hx <= hy) { + if ((hx < hy) || (lx < ly)) { + return x; /* |x|<|y| return x */ + } + + if (lx == ly) { + return Zero[(uint32_t)sx >> 31]; /* |x|=|y| return x*0*/ + } + } + + /* determine ix = ilogb(x) */ + if (hx < 0x00100000) { /* subnormal x */ + if (hx == 0) { + for (ix = -1043, i = lx; i > 0; i <<= 1) { + ix -= 1; + } + } else { + for (ix = -1022, i = (hx << 11); i > 0; i <<= 1) { + ix -= 1; + } + } + } else { + ix = (hx >> 20) - 1023; + } + + /* determine iy = ilogb(y) */ + if (hy < 0x00100000) { /* subnormal y */ + if (hy == 0) { + for (iy = -1043, i = ly; i > 0; i <<= 1) { + iy -= 1; + } + } else { + for (iy = -1022, i = (hy << 11); i > 0; i <<= 1) { + iy -= 1; + } + } + } else { + iy = (hy >> 20) - 1023; + } + + /* set up {hx,lx}, {hy,ly} and align y to x */ + if (ix >= -1022) { + hx = 0x00100000 | (0x000fffff & hx); + } else { /* subnormal x, shift x to normal */ + n = -1022 - ix; + + if (n <= 31) { + hx = (hx << n) | (lx >> (32 - n)); + lx <<= n; + } else { + hx = lx << (n - 32); + lx = 0; + } + } + + if (iy >= -1022) { + hy = 0x00100000 | (0x000fffff & hy); + } else { /* subnormal y, shift y to normal */ + n = -1022 - iy; + + if (n <= 31) { + hy = (hy << n) | (ly >> (32 - n)); + ly <<= n; + } else { + hy = ly << (n - 32); + ly = 0; + } + } + + /* fix point fmod */ + n = ix - iy; + + while (n-- > 0) { + hz = hx - hy; + lz = lx - ly; + + if (lx < ly) { + hz -= 1; + } + + if (hz < 0) { + hx = hx + hx + (lx >> 31); + lx = lx + lx; + } else { + if ((hz | lz) == 0) { /* return sign(x)*0 */ + return Zero[(uint32_t)sx >> 31]; + } + + hx = hz + hz + (lz >> 31); + lx = lz + lz; + } + } + + hz = hx - hy; + lz = lx - ly; + + if (lx < ly) { + hz -= 1; + } + + if (hz >= 0) { + hx = hz; + lx = lz; + } + + /* convert back to floating value and restore the sign */ + if ((hx | lx) == 0) { /* return sign(x)*0 */ + return Zero[(uint32_t)sx >> 31]; + } + + while (hx < 0x00100000) { /* normalize x */ + hx = hx + hx + (lx >> 31); + lx = lx + lx; + iy -= 1; + } + + if (iy >= -1022) { /* normalize output */ + hx = ((hx - 0x00100000) | ((iy + 1023) << 20)); + INSERT_WORDS(x, hx | sx, lx); + } else { /* subnormal output */ + n = -1022 - iy; + + if (n <= 20) { + lx = (lx >> n) | ((uint32_t)hx << (32 - n)); + hx >>= n; + } else if (n <= 31) { + lx = (hx << (32 - n)) | (lx >> n); + hx = sx; + } else { + lx = hx >> (n - 32); + hx = sx; + } + + INSERT_WORDS(x, hx | sx, lx); +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + } + + return x; /* exact output */ +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double fmodl(long double x, long double y) +{ + return (long double) fmod((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/frexpd.c b/libm/libmcs/libm/mathd/frexpd.c new file mode 100644 index 00000000..40dada40 --- /dev/null +++ b/libm/libmcs/libm/mathd/frexpd.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions splits the input value into mantissa and exponent. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float frexpf(float x, int *eptr); + * double frexp(double x, int *eptr); + * long double frexpl(long double x, int *eptr); + * + * Description + * =========== + * + * ``frexp`` splits the input value into the normalized fraction of :math:`x` + * and its integral power of :math:`2`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * frexp(x) = \frac{x}{2^{eptr}} \wedge frexp(x) \in [0.5,1[ + * + * Returns + * ======= + * + * ``frexp`` returns the normalized fraction of :math:`x` in the range + * :math:`[0.5,1[` and puts the integral power of :math:`2` into the output + * pointer :math:`*eptr`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+----------------------------------+--------------+--------------+----------------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================================+==============+==============+==================================+==============+==============+ + * | **frexp(x)** | :math:`qNaN` | :math:`\frac{x}{2^{eptr}}` | :math:`x` | :math:`\frac{x}{2^{eptr}}` | :math:`qNaN` | :math:`qNaN` | + * +---------------------+--------------+----------------------------------+--------------+--------------+----------------------------------+--------------+--------------+ + * | :math:`*eptr` | :math:`0` | :math:`log_2 \frac{x}{frexp(x)}` | :math:`0` | :math:`log_2 \frac{x}{frexp(x)}` | :math:`0` | :math:`0` | + * +---------------------+--------------+----------------------------------+--------------+--------------+----------------------------------+--------------+--------------+ + * + */ + +/* + * for non-zero x + * x = frexp(arg,&exp); + * return a double fp quantity x such that 0.5 <= |x| <1.0 + * and the corresponding binary exponent "exp". That is + * arg = x*2^exp. + * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg + * with *exp=0. + */ + +#include +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ + +double frexp(double x, int *eptr) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int _xexp = 0; + int32_t hx, ix, lx; + + assert(eptr != (void*)0); + if(eptr == (void*)0) { + eptr = &_xexp; + } + + EXTRACT_WORDS(hx, lx, x); + ix = 0x7fffffff & hx; + *eptr = 0; + + if (ix >= 0x7ff00000 || ((ix | lx) == 0)) { + return x + x; /* 0,inf,nan */ + } + + if (ix < 0x00100000) { /* subnormal */ + x *= two54; + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + *eptr = -54; + } + + *eptr += (ix >> 20) - 1022; + hx = (hx & 0x800fffffU) | 0x3fe00000U; + SET_HIGH_WORD(x, hx); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double frexpl(long double x, int *eptr) +{ + return (long double) frexp((double) x, eptr); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/hypotd.c b/libm/libmcs/libm/mathd/hypotd.c new file mode 100644 index 00000000..d676a9bc --- /dev/null +++ b/libm/libmcs/libm/mathd/hypotd.c @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the hypotenuse of a right-angled triangle. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float hypotf(float x, float y); + * double hypot(double x, double y); + * long double hypotl(long double x, long double y); + * + * Description + * =========== + * + * ``hypot`` computes the length of the hypotenuse of a right-angled triangle + * where the legs have the lengths :math:`x` and :math:`y`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * hypot(x, y) \approx \sqrt{x^2 + y^2} + * + * Returns + * ======= + * + * ``hypot`` returns the length of the hypotenuse of a right-angled triangle. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the magnitude of the input values is too + * large. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | hypot(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`\in \mathbb{F}` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`+Inf` | :math:`+Inf` | :math:`+Inf` | :math:`+Inf` | + * +--------------------------+ +--------------------------+ +--------------------------+ + * | :math:`\in \mathbb{F}` | | :math:`\sqrt{x^2 + y^2}` | | :math:`qNaN` | + * +--------------------------+ +--------------------------+ +--------------------------+ + * | :math:`+Inf` | | :math:`+Inf` | | :math:`+Inf` | + * +--------------------------+ +--------------------------+ +--------------------------+ + * | :math:`NaN` | | :math:`qNaN` | | :math:`qNaN` | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double hypot(double x, double y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double a = x; + double b = y; + double t1, t2; + double _y1, _y2; + double 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) { + t1 = 0.0; + SET_HIGH_WORD(t1, (0x3FF + k) << 20); + return t1 * w; + } else { + return w; + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double hypotl(long double x, long double y) +{ + return (long double) hypot((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/ilogbd.c b/libm/libmcs/libm/mathd/ilogbd.c new file mode 100644 index 00000000..e19bd7f9 --- /dev/null +++ b/libm/libmcs/libm/mathd/ilogbd.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions computes the binary exponent of the input value as + * a signed integer. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int ilogbf(float x); + * int ilogb(double x); + * int ilogbl(long double x); + * + * Description + * =========== + * + * ``ilogb`` computes the binary exponent of the input value as a signed integer. + * + * ``ilogb`` and :ref:`logb` have the same functionality, but ``ilogb`` returns + * the binary exponent as a signed integer while :ref:`logb` returns a + * floating-point value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * ilogb(x) \approx \lfloor {\log_2 |x|} \rfloor + * + * Returns + * ======= + * + * ``ilogb`` returns the binary exponent of the input value, in the range + * :math:`\mathbb{I}`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the correct result is not + * representable as an integer. This is the case when the input value is zero, + * infinite or :math:`NaN`, or the magnitude of the result is too large to be + * represented as an integer. + * + * Output map + * ========== + * + * +---------------------+------------------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0 \wedge \lfloor {\log_2 |x|} \rfloor \notin \mathbb{I} \wedge \lfloor {\log_2 |x|} \rfloor > 0` | :math:`<0 \wedge \lfloor {\log_2 |x|} \rfloor \in \mathbb{I}` | :math:`<0 \wedge \lfloor {\log_2 |x|} \rfloor \notin \mathbb{I} \wedge \lfloor {\log_2 |x|} \rfloor < 0` | :math:`-0` | :math:`+0` | + * +=====================+========================+==========================================================================================================+==================================================================+==========================================================================================================+==============+==============+ + * | **ilogb(x)** | max :math:`\mathbb{I}` | max :math:`\mathbb{I}` | :math:`\lfloor {\log_2 |x|} \rfloor` | min :math:`\mathbb{I}` | min :math:`\mathbb{I}` | + * +---------------------+------------------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------+--------------+--------------+ + * + * +---------------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------+--------------+--------------+ + * | **x** | :math:`>0 \wedge \lfloor {\log_2 |x|} \rfloor \notin \mathbb{I} \wedge \lfloor {\log_2 |x|} \rfloor < 0` | :math:`<0 \wedge \lfloor {\log_2 |x|} \rfloor \in \mathbb{I}` | :math:`>0 \wedge \lfloor {\log_2 |x|} \rfloor \notin \mathbb{I} \wedge \lfloor {\log_2 |x|} \rfloor > 0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==========================================================================================================+==================================================================+==========================================================================================================+==============+==============+ + * | **ilogb(x)** | min :math:`\mathbb{I}` | :math:`\lfloor {\log_2 |x|} \rfloor` | max :math:`\mathbb{I}` | max :math:`\mathbb{I}` | + * +---------------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------+--------------+--------------+ + * + * .. raw:: html + * + * + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +int ilogb(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, lx, ix; + + EXTRACT_WORDS(hx, lx, x); + hx &= 0x7fffffff; + + if (hx < 0x00100000) { + if ((hx | lx) == 0) { + (void) __raise_invalid(); + return FP_ILOGB0; /* ilogb(0) = special case error */ + } else { /* subnormal x */ + if (hx == 0) { + for (ix = -1043; lx > 0; lx <<= 1) { + ix -= 1; + } + } else { + for (ix = -1022, hx <<= 11; hx > 0; hx <<= 1) { + ix -= 1; + } + } + } + + return ix; + } else if (hx < 0x7ff00000) { + return (hx >> 20) - 1023; + } else if (hx > 0x7ff00000) { + (void) __raise_invalid(); + return FP_ILOGBNAN; /* NAN */ + } else { + (void) __raise_invalid(); + return INT_MAX; /* infinite */ + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +int ilogbl(long double x) +{ + return ilogb((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/internal/besseld.h b/libm/libmcs/libm/mathd/internal/besseld.h new file mode 100644 index 00000000..4e74b771 --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/besseld.h @@ -0,0 +1,444 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_BESSELD_H +#define LIBMCS_BESSELD_H + +#include +#include "../../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double one = 1.0, zero = 0.0, two = 2.0; + +static const double +invsqrtpi = 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +tpi = 6.36619772367581382433e-01; /* 0x3FE45F30, 0x6DC9C883 */ + +/* The asymptotic expansions of __j0_p is + * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. + * For x >= 2, We approximate __j0_p by + * __j0_p(x) = 1 + (R/S) + * where R = __j0_pr0 + __j0_pr1*s^2 + __j0_pr2*s^4 + ... + __j0_pr5*s^10 + * S = 1 + __j0_ps0*s^2 + ... + __j0_ps4*s^10 + * and + * | __j0_p(x)-1-R/S | <= 2 ** ( -60.26) + */ +static const double __j0_pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ + -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ + -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ + -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ + -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ +}; +static const double __j0_ps8[5] = { + 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ + 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ + 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ + 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ + 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ +}; + +static const double __j0_pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ + -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ + -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ + -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ + -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ + -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ +}; +static const double __j0_ps5[5] = { + 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ + 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ + 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ + 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ + 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ +}; + +static const double __j0_pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ + -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ + -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ + -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ + -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ + -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ +}; +static const double __j0_ps3[5] = { + 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ + 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ + 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ + 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ + 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ +}; + +static const double __j0_pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ + -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ + -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ + -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ + -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ + -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ +}; +static const double __j0_ps2[5] = { + 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ + 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ + 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ + 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ + 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ +}; + +static inline double __j0_p(double x) +{ + const double *p, *q; + double z, r, s; + int32_t ix; + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + if (ix >= 0x41b00000) { + return one; + } else if (ix >= 0x40200000) { + p = __j0_pr8; + q = __j0_ps8; + } else if (ix >= 0x40122E8B) { + p = __j0_pr5; + q = __j0_ps5; + } else if (ix >= 0x4006DB6D) { + p = __j0_pr3; + q = __j0_ps3; + } else { + p = __j0_pr2; + q = __j0_ps2; + } + + z = one / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = one + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4])))); + return one + r / s; +} + + +/* For x >= 8, the asymptotic expansions of __j0_q is + * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. + * We approximate __j0_q by + * __j0_q(x) = s*(-1.25 + (R/S)) + * where R = __j0_qr0 + __j0_qr1*s^2 + __j0_qr2*s^4 + ... + __j0_qr5*s^10 + * S = 1 + __j0_qs0*s^2 + ... + __j0_qs5*s^12 + * and + * | __j0_q(x)/s +1.25-R/S | <= 2 ** ( -61.22) + */ +static const double __j0_qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ + 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ + 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ + 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ + 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ +}; +static const double __j0_qs8[6] = { + 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ + 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ + 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ + 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ + 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ + -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ +}; + +static const double __j0_qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ + 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ + 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ + 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ + 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ + 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ +}; +static const double __j0_qs5[6] = { + 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ + 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ + 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ + 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ + 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ + -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ +}; + +static const double __j0_qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ + 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ + 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ + 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ + 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ + 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ +}; +static const double __j0_qs3[6] = { + 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ + 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ + 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ + 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ + 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ + -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ +}; + +static const double __j0_qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ + 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ + 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ + 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ + 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ + 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ +}; +static const double __j0_qs2[6] = { + 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ + 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ + 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ + 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ + 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ + -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ +}; + +static inline double __j0_q(double x) +{ + const double *p, *q; + double s, r, z; + int32_t ix; + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + if (ix >= 0x41b00000) { + return -.125 / x; + } else if (ix >= 0x40200000) { + p = __j0_qr8; + q = __j0_qs8; + } else if (ix >= 0x40122E8B) { + p = __j0_qr5; + q = __j0_qs5; + } else if (ix >= 0x4006DB6D) { + p = __j0_qr3; + q = __j0_qs3; + } else { + p = __j0_qr2; + q = __j0_qs2; + } + + z = one / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = one + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5]))))); + return (-.125 + r / s) / x; +} + +/* For x >= 8, the asymptotic expansions of __j1_p is + * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. + * We approximate __j1_p by + * __j1_p(x) = 1 + (R/S) + * where R = __j1_pr0 + __j1_pr1*s^2 + __j1_pr2*s^4 + ... + __j1_pr5*s^10 + * S = 1 + __j1_ps0*s^2 + ... + __j1_ps4*s^10 + * and + * | __j1_p(x)-1-R/S | <= 2 ** ( -60.06) + */ + +static const double __j1_pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ + 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ + 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ + 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ + 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ +}; +static const double __j1_ps8[5] = { + 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ + 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ + 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ + 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ + 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ +}; + +static const double __j1_pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ + 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ + 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ + 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ + 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ + 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ +}; +static const double __j1_ps5[5] = { + 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ + 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ + 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ + 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ + 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ +}; + +static const double __j1_pr3[6] = { + 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ + 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ + 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ + 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ + 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ + 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ +}; +static const double __j1_ps3[5] = { + 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ + 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ + 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ + 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ + 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ +}; + +static const double __j1_pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ + 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ + 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ + 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ + 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ + 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ +}; +static const double __j1_ps2[5] = { + 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ + 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ + 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ + 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ + 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ +}; + +static inline double __j1_p(double x) +{ + const double *p, *q; + double z, r, s; + int32_t ix; + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + if (ix >= 0x41b00000) { + return one; + } else if (ix >= 0x40200000) { + p = __j1_pr8; + q = __j1_ps8; + } else if (ix >= 0x40122E8B) { + p = __j1_pr5; + q = __j1_ps5; + } else if (ix >= 0x4006DB6D) { + p = __j1_pr3; + q = __j1_ps3; + } else { + p = __j1_pr2; + q = __j1_ps2; + } + + z = one / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = one + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4])))); + return one + r / s; +} + + +/* For x >= 8, the asymptotic expansions of __j1_q is + * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. + * We approximate __j1_q by + * __j1_q(x) = s*(0.375 + (R/S)) + * where R = __j1_qr1*s^2 + __j1_qr2*s^4 + ... + __j1_qr5*s^10 + * S = 1 + __j1_qs1*s^2 + ... + __j1_qs6*s^12 + * and + * | __j1_q(x)/s -0.375-R/S | <= 2 ** ( -61.13) + */ + +static const double __j1_qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ + -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ + -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ + -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ + -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ +}; +static const double __j1_qs8[6] = { + 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ + 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ + 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ + 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ + 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ + -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ +}; + +static const double __j1_qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ + -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ + -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ + -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ + -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ + -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ +}; +static const double __j1_qs5[6] = { + 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ + 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ + 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ + 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ + 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ + -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ +}; + +static const double __j1_qr3[6] = { + -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ + -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ + -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ + -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ + -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ + -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ +}; +static const double __j1_qs3[6] = { + 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ + 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ + 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ + 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ + 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ + -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ +}; + +static const double __j1_qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ + -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ + -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ + -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ + -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ + -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ +}; +static const double __j1_qs2[6] = { + 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ + 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ + 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ + 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ + 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ + -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ +}; + +static inline double __j1_q(double x) +{ + const double *p, *q; + double s, r, z; + int32_t ix; + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + if (ix >= 0x41b00000) { + return .375 / x; + } else if (ix >= 0x40200000) { + p = __j1_qr8; + q = __j1_qs8; + } else if (ix >= 0x40122E8B) { + p = __j1_qr5; + q = __j1_qs5; + } else if (ix >= 0x4006DB6D) { + p = __j1_qr3; + q = __j1_qs3; + } else { + p = __j1_qr2; + q = __j1_qs2; + } + + z = one / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = one + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5]))))); + return (.375 + r / s) / x; +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ + +#endif /* !LIBMCS_BESSELD_H */ diff --git a/libm/libmcs/libm/mathd/internal/errorfunctiond.h b/libm/libmcs/libm/mathd/internal/errorfunctiond.h new file mode 100644 index 00000000..a2180147 --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/errorfunctiond.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +#ifndef LIBMCS_ERRORFUNCTIOND_H +#define LIBMCS_ERRORFUNCTIOND_H + +#include +#include "../../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +/* + * Coefficients for approximation to erf on [0,0.84375] + */ +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 */ + +static inline double __erf_y(double x) +{ + double s, z, r; + 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)))); + return r / s; +} + +static inline double __erf_P(double s) +{ + return pa0 + s * (pa1 + s * (pa2 + s * (pa3 + s * (pa4 + s * (pa5 + s * pa6))))); +} + +static inline double __erf_Q(double s) +{ + return one + s * (qa1 + s * (qa2 + s * (qa3 + s * (qa4 + s * (qa5 + s * qa6))))); +} + +static inline double __erf_Ra(double s) +{ + return ra0 + s * (ra1 + s * (ra2 + s * (ra3 + s * (ra4 + s * (ra5 + s * (ra6 + s * ra7)))))); +} + +static inline double __erf_Sa(double s) +{ + return one + s * (sa1 + s * (sa2 + s * (sa3 + s * (sa4 + s * (sa5 + s * (sa6 + s * (sa7 + s * sa8))))))); +} + +static inline double __erf_Rb(double s) +{ + return rb0 + s * (rb1 + s * (rb2 + s * (rb3 + s * (rb4 + s * (rb5 + s * rb6))))); +} + +static inline double __erf_Sb(double s) +{ + return one + s * (sb1 + s * (sb2 + s * (sb3 + s * (sb4 + s * (sb5 + s * (sb6 + s * sb7)))))); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ + +#endif /* !LIBMCS_ERRORFUNCTIOND_H */ diff --git a/libm/libmcs/libm/mathd/internal/fpclassifyd.c b/libm/libmcs/libm/mathd/internal/fpclassifyd.c new file mode 100644 index 00000000..0540368f --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/fpclassifyd.c @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002,2007 by Red Hat, Incorporated. All rights reserved. */ + +/** + * + * This macro is used to classify :math:`x`. It can be called with ``float``, + * ``double`` or ``long double`` input. This macro is implemented in + * ``math.h``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int fpclassify(x); + * + * Description + * =========== + * + * ``fpclassify`` returns different constants depending on whether the input is + * subnormal, normal, zero, infinite or :math:`NaN`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * fpclassify(x) = \left\{\begin{array}{ll} FP\_ZERO, & x = \pm 0.0 \\ + * FP\_SUBNORMAL, & x \in \mathbb{S} \\ + * FP\_INFINITE, & x = \pm Inf \\ + * FP\_NAN, & x = NaN \\ + * FP\_NORMAL, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``fpclassify`` returns constant values, see ``math.h`` for their specific values. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+-----------------+------------------------------+------------------------------+-------------+------------------------------+------------------------------+-----------------+-------------+ + * | **x** | :math:`-Inf` | :math:`<0 \notin \mathbb{S}` | :math:`<0 \in \mathbb{S}` | :math:`±0` | :math:`>0 \in \mathbb{S}` | :math:`>0 \notin \mathbb{S}` | :math:`+Inf` | :math:`NaN` | + * +=====================+=================+==============================+==============================+=============+==============================+==============================+=================+=============+ + * | **fpclassify(x)** | ``FP_INFINITE`` | ``FP_NORMAL`` | ``FP_SUBNORMAL`` | ``FP_ZERO`` | ``FP_SUBNORMAL`` | ``FP_NORMAL`` | ``FP_INFINITE`` | ``FP_NAN`` | + * +---------------------+-----------------+------------------------------+------------------------------+-------------+------------------------------+------------------------------+-----------------+-------------+ + * + */ + +#include +#include "../../common/tools.h" + +int __fpclassifyd(double x) +{ + uint32_t msw, lsw; + + EXTRACT_WORDS(msw, lsw, x); + msw &= 0x7fffffffU; + + if (msw == 0x00000000U && lsw == 0x00000000U) { + return FP_ZERO; + } else if (msw >= 0x00100000U && msw <= 0x7fefffffU) { + return FP_NORMAL; + } else if (msw <= 0x000fffffU) { /* zero is already handled above */ + return FP_SUBNORMAL; + } else if (msw == 0x7ff00000U && lsw == 0x00000000U) { + return FP_INFINITE; + } else { + return FP_NAN; + } +} diff --git a/libm/libmcs/libm/mathd/internal/gammad.c b/libm/libmcs/libm/mathd/internal/gammad.c new file mode 100644 index 00000000..7022e1ea --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/gammad.c @@ -0,0 +1,428 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions is a set of functions used by the gamma function + * procedures as internal functions. Only ``__lgamma`` is accessible via + * ``gammad.h`` (``gammaf.h``), but should not be accessed directly by a user. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float __sin_pif(float x) + * double __sin_pi(double x) + * float __lgammaf(float x, int *signgamp) + * double __lgamma(double x, int *signgamp) + * + * Description + * =========== + * + * ``__lgamma`` computes the natural logarithm of the gamma function of + * :math:`x` and places the sign of the gamma function in the out-pointer + * :math:`signgamp`. + * + * ``__sin_pi`` computes the sine of the input value after it was multiplied by + * :math:`\pi`. The procedure is only called in the range + * :math:`[-2^{52},-2^{-70}]`, calling it outside of this range may result in + * unexpected results. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * \_\_sin\_pi(x) &\approx sin(\pi \cdot x) \\ + * \_\_lgamma(x) &\approx \ln{|\Gamma(x)|} = \ln{\left|\int_{0}^{\infty}e^{-t}t^{x-1}dt\right|} \\ + * \_\_lgamma\_signgamp(x) &= \left\{\begin{array}{ll} +1, & +0 \leq \Gamma(x) \\ -1, & -0 \geq \Gamma(x) \end{array}\right. + * + * Returns + * ======= + * + * ``__lgamma`` returns the natural logarithm of the gamma function of + * :math:`x` and places the sign of the gamma function in the out-pointer + * :math:`signgamp`. + * + * ``__sin_pi`` returns the sine of :math:`\pi \cdot x`. + * + * Exceptions + * ========== + * + * Do not raise useful exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * The output maps are in the respective external functions :ref:`lgamma` and + * :ref:`tgamma`. + * + */ + +/* __lgamma_r(x, signgamp) + * Reentrant version of the logarithm of the Gamma function + * with user provide pointer for the sign of Gamma(x). + * + * Method: + * 1. Argument Reduction for 0 < x <= 8 + * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may + * reduce x to a number in [1.5,2.5] by + * lgamma(1+s) = log(s) + lgamma(s) + * for example, + * lgamma(7.3) = log(6.3) + lgamma(6.3) + * = log(6.3*5.3) + lgamma(5.3) + * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) + * 2. Polynomial approximation of lgamma around its + * minimum ymin=1.461632144968362245 to maintain monotonicity. + * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use + * Let z = x-ymin; + * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) + * where + * poly(z) is a 14 degree polynomial. + * 2. Rational approximation in the primary interval [2,3] + * We use the following approximation: + * s = x-2.0; + * lgamma(x) = 0.5*s + s*P(s)/Q(s) + * with accuracy + * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 + * Our algorithms are based on the following observation + * + * zeta(2)-1 2 zeta(3)-1 3 + * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... + * 2 3 + * + * where Euler = 0.5771... is the Euler constant, which is very + * close to 0.5. + * + * 3. For x>=8, we have + * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... + * (better formula: + * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) + * Let z = 1/x, then we approximation + * f(z) = lgamma(x) - (x-0.5)(log(x)-1) + * by + * 3 5 11 + * w = w0 + w1*z + w2*z + w3*z + ... + w6*z + * where + * |w - f(z)| < 2**-58.74 + * + * 4. For negative x, since (G is gamma function) + * -x*G(-x)*G(x) = pi/sin(pi*x), + * we have + * G(x) = pi/(sin(pi*x)*(-x)*G(-x)) + * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 + * Hence, for x<0, signgam = sign(sin(pi*x)) and + * lgamma(x) = log(|Gamma(x)|) + * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); + * Note: one should avoid compute pi*(-x) directly in the + * computation of sin(pi*(-x)). + * + * 5. Special Cases + * lgamma(2+s) ~ s*(1-Euler) for tiny s + * lgamma(1)=lgamma(2)=0 + * lgamma(x) ~ -log(x) for tiny x + * lgamma(0) = lgamma(inf) = inf + * lgamma(-integer) = +-inf + * + */ + +#include +#include "../../common/tools.h" +#include "gammad.h" +#include "trigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +two52 = 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ +a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ +a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ +a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ +a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ +a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ +a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ +a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ +a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ +a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ +a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ +a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ +a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ +tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ +tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ +/* tt = -(tail of tf) */ +tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ +t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ +t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ +t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ +t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ +t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ +t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ +t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ +t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ +t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ +t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ +t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ +t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ +t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ +t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ +t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ +u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ +u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ +u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ +u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ +u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ +u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ +v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ +v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ +v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ +v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ +v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ +s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ +s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ +s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ +s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ +s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ +s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ +s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ +r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ +r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ +r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ +r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ +r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ +r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ +w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ +w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ +w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ +w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ +w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ +w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ +w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ + +static const double zero = 0.00000000000000000000e+00; + +static double __sin_pi(double x) +{ + double y, z; + int32_t n, ix; + + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + if (ix < 0x3fd00000) { + return __sin(pi * x, zero, 0); + } + + y = -x; /* x is assume negative */ + + /* + * argument reduction, make sure inexact flag not raised if input + * is an integer + */ + z = floor(y); + + if (z != y) { /* inexact anyway */ + y *= 0.5; + y = 2.0 * (y - floor(y)); /* y = |x| mod 2.0 */ + n = (int32_t)(y * 4.0); + } else { + z = y + two52; /* exact */ + + GET_LOW_WORD(n, z); + n &= 1; + y = n; + n <<= 2; + } + + switch (n) { + case 0: + y = __sin(pi * y, zero, 0); + break; + + case 1: /* FALLTHRU */ + case 2: + y = __cos(pi * (0.5 - y), zero); + break; + + case 3: /* FALLTHRU */ + case 4: + y = __sin(pi * (one - y), zero, 0); + break; + + case 5: /* FALLTHRU */ + case 6: + y = -__cos(pi * (y - 1.5), zero); + break; + + default: + y = __sin(pi * (y - 2.0), zero, 0); + break; + } + + return -y; +} + +double __lgamma(double x, int *signgamp) +{ + double t, y, z, nadj = 0.0, p, p1, p2, p3, q, r, w; + int32_t i, hx, lx, ix; + + EXTRACT_WORDS(hx, lx, x); + + /* purge off +-inf, NaN, +-0, and negative arguments */ + *signgamp = 1; + ix = hx & 0x7fffffff; + + if (ix >= 0x7ff00000) { + return x * x; + } + + if ((ix | lx) == 0) { + if(hx < 0) { + *signgamp = -1; + } + return __raise_div_by_zero(zero); + } + + if (ix < 0x3b900000) { /* |x|<2**-70, return -log(|x|) */ + if (hx < 0) { + *signgamp = -1; + return -log(-x); + } else { + return -log(x); + } + } + + if (hx < 0) { + if (ix >= 0x43300000) { /* |x|>=2**52, must be -integer */ + return __raise_div_by_zero(zero); + } + + t = __sin_pi(x); + + if (t == zero) { /* -integer */ + return __raise_div_by_zero(zero); + } + + nadj = log(pi / fabs(t * x)); + + if (t < zero) { + *signgamp = -1; + } + + x = -x; + } + + /* purge off 1 and 2 */ + if ((((ix - 0x3ff00000) | lx) == 0) || (((ix - 0x40000000) | lx) == 0)) { + r = 0; + } + /* for x < 2.0 */ + else if (ix < 0x40000000) { + if (ix <= 0x3feccccc) { /* lgamma(x) = lgamma(x+1)-log(x) */ + r = -log(x); + + if (ix >= 0x3FE76944) { + y = one - x; + i = 0; + } else if (ix >= 0x3FCDA661) { + y = x - (tc - one); + i = 1; + } else { + y = x; + i = 2; + } + } else { + r = zero; + + if (ix >= 0x3FFBB4C3) { + y = 2.0 - x; /* [1.7316,2] */ + i = 0; + } else if (ix >= 0x3FF3B4C4) { + y = x - tc; /* [1.23,1.73] */ + i = 1; + } else { + y = x - one; + i = 2; + } + } + + switch (i) { + default: /* FALLTHRU */ + case 0: + z = y * y; + p1 = a0 + z * (a2 + z * (a4 + z * (a6 + z * (a8 + z * a10)))); + p2 = z * (a1 + z * (a3 + z * (a5 + z * (a7 + z * (a9 + z * a11))))); + p = y * p1 + p2; + r += (p - 0.5 * y); + break; + + case 1: + z = y * y; + w = z * y; + p1 = t0 + w * (t3 + w * (t6 + w * (t9 + w * t12))); /* parallel comp */ + p2 = t1 + w * (t4 + w * (t7 + w * (t10 + w * t13))); + p3 = t2 + w * (t5 + w * (t8 + w * (t11 + w * t14))); + p = z * p1 - (tt - w * (p2 + y * p3)); + r += (tf + p); + break; + + case 2: + p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * u5))))); + p2 = one + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * v5)))); + r += (-0.5 * y + p1 / p2); + break; + } + } else if (ix < 0x40200000) { /* x < 8.0 */ + i = (int32_t)x; + y = x - (double)i; + p = y * (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6)))))); + q = one + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * r6))))); + r = half * y + p / q; + z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ + + switch (i) { + case 7: + z *= (y + 6.0); /* FALLTHRU */ + + case 6: + z *= (y + 5.0); /* FALLTHRU */ + + case 5: + z *= (y + 4.0); /* FALLTHRU */ + + case 4: + z *= (y + 3.0); /* FALLTHRU */ + + case 3: + z *= (y + 2.0); /* FALLTHRU */ + + default: + r += log(z); + break; + } + + } else if (ix < 0x43900000) { /* 8.0 <= x < 2**58 */ + t = log(x); + z = one / x; + y = z * z; + w = w0 + z * (w1 + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * w6))))); + r = (x - half) * (t - one) + w; + } else { /* 2**58 <= x <= inf */ + r = x * (log(x) - one); + } + + if (hx < 0) { + r = nadj - r; + } + + return r; +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/internal/gammad.h b/libm/libmcs/libm/mathd/internal/gammad.h new file mode 100644 index 00000000..dbaa229c --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/gammad.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_GAMMAD_H +#define LIBMCS_GAMMAD_H + +extern double __lgamma(double x, int *signgamp); + +#endif /* !LIBMCS_GAMMAD_H */ diff --git a/libm/libmcs/libm/mathd/internal/log1pmfd.h b/libm/libmcs/libm/mathd/internal/log1pmfd.h new file mode 100644 index 00000000..89d14d3b --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/log1pmfd.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/* + * __log1pmf(f): + * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)]. + */ + +#ifndef LIBMCS_LOG1PMFD_H +#define LIBMCS_LOG1PMFD_H + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +Lg1 = 6.666666666666735130e-01, /* 0x3FE5555555555593 */ +Lg2 = 3.999999999940941908e-01, /* 0x3FD999999997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 0x3FD2492494229359 */ +Lg4 = 2.222219843214978396e-01, /* 0x3FCC71C51D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 0x3FC7466496CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 0x3FC39A09D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 0x3FC2F112DF3E5244 */ + +/* + * We always inline __log1pmf(), since doing so produces a substantial + * performance improvement (~40% on amd64). + */ +static inline double __log1pmf(double f) +{ + double hfsq, s, z, R, w, t1, t2; + + s = f / (2.0 + f); + z = s * s; + w = z * z; + t1 = w * (Lg2 + w * (Lg4 + w * Lg6)); + t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7))); + R = t2 + t1; + hfsq = 0.5 * f * f; + return s * (hfsq + R); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ + +#endif /* !LIBMCS_LOG1PMFD_H */ diff --git a/libm/libmcs/libm/mathd/internal/signbitd.c b/libm/libmcs/libm/mathd/internal/signbitd.c new file mode 100644 index 00000000..b8e5cb03 --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/signbitd.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. */ + +/** + * + * This macro returns a non-zero value if the sign bit of :math:`x` is set. It + * can be called with ``float``, ``double`` or ``long double`` input. This + * macro is implemented in ``math.h``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * int signbit(x); + * + * Description + * =========== + * + * ``signbit`` returns a non-zero value if the sign bit of :math:`x` is set. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * signbit(x) = \left\{\begin{array}{ll} 1, & x \in \mathbb{F}^{-} \\ + * 0, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``signbit`` returns :math:`1` if the sign bit of :math:`x` is set, otherwise + * :math:`0`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * | **x** | :math:`-NaN` | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`+NaN` | + * +=====================+==============+==============+==============+==============+==============+==============+==============+==============+ + * | **signbit(x)** | :math:`1` | :math:`0` | + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * + */ + +#include +#include "../../common/tools.h" + +int __signbitd(double x) +{ + uint32_t msw; + + GET_HIGH_WORD(msw, x); + + return (msw & 0x80000000U) != 0; +} diff --git a/libm/libmcs/libm/mathd/internal/trigd.c b/libm/libmcs/libm/mathd/internal/trigd.c new file mode 100644 index 00000000..62dcc951 --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/trigd.c @@ -0,0 +1,627 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions is a set of functions used by multiple + * trigonometric procedures as internal functions. Except for the internal + * range reduction the other functions are accessible via ``trigd.h`` + * (``trigf.h``), but should not be accessed directly by a user. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * float __cosf(float x, float y) + * double __cos(double x, double y) + * float __sinf(float x, float y, int iy) + * double __sin(double x, double y, int iy) + * int32_t __rem_pio2f(float x, float *y) + * int32_t __rem_pio2(double x, double *y) + * int __rem_pio2_internalf(float *x, float *y, int e0, int nx) + * int __rem_pio2_internal(double *x, double *y, int e0, int nx) + * + * Description + * =========== + * + * ``__cos`` computes the cosine of the input value. The sum of both input + * parameters :math:`x` and :math:`y` is bounded to [:math:`-\frac{\pi}{4}`, + * :math:`\frac{\pi}{4}`]. The first parameter :math:`x` is the requested value + * in raw precision while the second parameter :math:`y` contains a tail for + * higher precision. + * + * ``__sin`` computes the sine of the input value. The sum of both input + * parameters :math:`x` and :math:`y` is bounded to [:math:`-\frac{\pi}{4}`, + * :math:`\frac{\pi}{4}`]. The first parameter :math:`x` is the requested value + * in raw precision while the second parameter :math:`y` contains a tail for + * higher precision. The third parameter :math:`iy` signals if the parameter + * :math:`y` is :math:`0`. + * + * ``__rem_pio2`` returns the quadrant the input angle lies in, and place the + * remainder of :math:`x` divided by :math:`\frac{\pi}{4}` in the output array + * :math:`*y` (which consists of two values, the remainder and its tail, + * hereafter called :math:`y_0` and :math:`y_1`). The return value can be + * converted to the angle quadrant by taking just its last two bits. If the + * last two bits are :math:`00`, the input value is represented in + * [:math:`-45^{\circ}`, :math:`45^{\circ}`], if they are :math:`01`, it is in + * [:math:`45^{\circ}`, :math:`135^{\circ}`], if they are :math:`10`, it is in + * [:math:`135^{\circ}`, :math:`225^{\circ}`], and if they are :math:`11`, it + * is in [:math:`225^{\circ}`, :math:`315^{\circ}`]. The last two bits of the + * return value are the only relevant part. In some cases the return value also + * equals the number of reductions (by :math:`\frac{\pi}{2}`) necessary to + * reduce the value - this is not always the case, as the return value would + * often overflow due to the limited size of ``int32_t``. + * + * ``__rem_pio2_internal`` returns the quadrant the input angle lies in (see + * ``__rem_pio2`` on how to convert the return value into the quadrant), and + * place the remainder of :math:`x` (scaled :math:`x` which consists of up to + * three values, hereafter called :math:`x_0`, :math:`x_1` and :math:`x_2`, + * original :math:`x = x_0 \cdot 2^{e0} + x_1 \cdot 2^{e0-24} + x_2 \cdot + * 2^{e0-48}`) divided by :math:`\frac{\pi}{4}` in the output array (which + * consists of two values, the remainder and its tail, :math:`y_0` and + * :math:`y_1`). The variable :math:`nx` needs to be provided with the size of + * the array for :math:`x`. + * + * Although ``__rem_pio2`` and ``__rem_pio2_internal`` seem to do the same, + * they work on different ranges. ``__rem_pio2`` first checks if the input is + * rather close to the target interval, if it isn't it calls + * ``__rem_pio2_internal``. + * + * *Note:* The variables ``prec`` and ``*ipio2`` are to be removed during the + * rework and are therefore not part of the description. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * \_\_cos(x) &\approx cos(x) \\ + * \_\_sin(x) &\approx sin(x) \\ + * \_\_rem\_pio2_y(x) &\approx x - n \cdot \frac{\pi}{2} \wedge n \in \mathbb{Z} \wedge \_\_rem\_pio2_y(x) \in \left[-\frac{\pi}{4},\frac{\pi}{4}\right] \\ + * \_\_rem\_pio2(x) &= n + * + * Returns + * ======= + * + * ``__cos`` returns the cosine of :math:`x + y`. + * + * ``__sin`` returns the sine of :math:`x + y`. + * + * ``__rem_pio2`` returns the quadrant the input angle lies in, and place the + * remainder of :math:`x` divided by :math:`\frac{\pi}{4}` in the output array + * :math:`*y`. See description above. + * + * ``__rem_pio2_internal`` returns the quadrant the input angle lies in, and + * place the remainder of :math:`x` divided by :math:`\frac{\pi}{4}` in the + * output array :math:`*y`. See description above. + * + * Exceptions + * ========== + * + * Do not raise useful exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * The output maps are in the respective external functions :ref:`cos` and :ref:`sin`. + * + */ + +#include +#include "../../common/tools.h" +#include "trigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +/* + * 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. + */ + +/* + * Double precision array, obtained by cutting pi/2 + * into 24 bits chunks. + */ +static const double PIo2[] = { + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +}; + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + * + * The integer array contains the (24*i)-th to (24*i+23)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * ipio2[i] * 2^(-24(i+1)). + */ +static const int32_t ipio2[] = { + 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163, + 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, + 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, + 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, + 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, + 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, + 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, + 0x73A8C9, 0x60E27B, 0xC08C6B, +}; + +static const double zero = 0.0; +static const double one = 1.0; +static const double two24 = 0x1p+24; /* 1.6777216000000000000e+07 0x41700000, 0x00000000 */ +static const double twon24 = 0x1p-24; /* 5.9604644775390625000e-08 0x3E700000, 0x00000000 */ + +static inline int __rem_pio2_internal(double *x, double *y, int e0, int nx) +{ + int32_t jk = 4; /* precision setting: + 2 for up to 32 bits single precision + 3 for up to 64 bits double precision + 4 for up to 80 bits extended precision + 6 for up to 128 bit quad precision + + jk+1 is the initial number of terms of ipio2[] needed in the computation. */ + int32_t jp = jk; /* stores the initial value of jk until the final result computation */ + + int32_t k; /* number of additional ipio2 terms needed for recomputation */ + int32_t i, j, m; /* general purpose indices and variables */ + int32_t jz, jx, jv; /* other specific indices */ + int32_t carry; /* indicates whether there is a contribution of q when computing the complementary angle */ + int32_t ih; /* variable that indicates the position of the angle within the resulting quadrant. + If ih is positive then q[] is >= 0.5, hence it acts as the "signbit" of the result, + which will be positive for negative angles within the quadrant. */ + + + double q[20] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /* value of q = x/(pi/2) = x*(2/pi) */ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + int32_t q0; /* the corresponding exponent of q[0]. Note that the exponent for q[i] would be q0-24*i */ + + int32_t n; /* indicates the octant where the angle falls into; it is used to get the quadrant */ + double z; /* high order fractional part of q, down to the q0 bit */ + int32_t iq[20] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* lower order 24 bit chunks of fractional part of q in inverted order. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* iq starts after the q0 bits which are in z */ + + /* For an example angle of x = 900000.0 we would have that q = x/(pi/2) = x*(2/pi) = 572957.79513082320876798154814105170332405472466564321549160243861 + q = 1.00010111110000111011100101110001101101100011001000110111001001001001011001101001100000110011101110000100110100110000100001011101111001001000000000 + The q[] array will represent q = 153802180800000*2^−28 + 104097542400000*2^−52 + 19972857600000*2^-76 + 37128744000000*2^-100 + 231405883200000*2^-124 + where q0 = -28. + This value of q will be split in (after removing the integer part 572957 and storing 572957 mod 8 = 5 in n): + n = 5 (101) -> quadrant 1 + z = 0.7951308228075504 (0.1100101110001101101100011001) + q = 1100101110001101101100011001 000110111001001001001011 001101101101110010110110 011010110101000001100001 011101111001001000000000 + z iq[3] iq[2] iq[1] iq[0] + (Note that z contains 28 bits, because of q0 = -28) + To obtain the end result, the complementary to 1 of z and iq are computed, as the result will be a negative angle within the quadrant 2. + x = 900000.0 radians is equivalent to 2.81978... radians which will result in an angle of -0.321807... radians in quadrant 2 [3*pi/4, 5*pi/4]. + */ + + double fw; /* temporary variable to compute q, iq, and fq */ + double f[20] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /* ipio2[] terms taken fro computation in floating point */ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + double fq[20] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /* final product of q*pi/2 in fq[0],..,fq[jk]; */ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; /* computing the fractional value [0,1] within the quadrant back into radians */ + + + + bool recompute; /* variable used to signalize that a recomputation is needed as the current selection of ipio2[] terms has led to loss of significance. + The recomputation will take more terms of ipio2[]. */ + bool exhausted; /* variable used to signalize that the available ipio2 precision has been exhausted making no further recomputing possible */ + + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx - 1; + jv = (e0 - 3) / 24; + + q0 = e0 - 24 * (jv + 1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv - jx; + m = jx + jk; + + for (i = 0; i <= m; i++, j++) { + f[i] = (j < 0) ? zero : (double) ipio2[j]; + } + + /* compute q[0],q[1],...q[jk] */ + for (i = 0; i <= jk; i++) { + for (j = 0, fw = 0.0; j <= jx; j++) { + fw += x[j] * f[jx + i - j]; + } + + q[i] = fw; + } + + jz = jk; + + do { + recompute = false; + exhausted = false; + + /* distill the lower part of q[] into iq[] reversingly and leave the higher part in z */ + for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) { + fw = (double)((int32_t)(twon24 * z)); + iq[i] = (int32_t)(z - two24 * fw); + z = q[j - 1] + fw; + } + + /* compute n */ + z = scalbn(z, (int32_t)q0); /* actual value of z */ + z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */ + n = (int32_t) z; + z -= (double)n; + ih = 0; + + if (q0 > 0) { /* need iq[jz-1] to determine n */ + i = (iq[jz - 1] >> (24 - q0)); + n += i; + iq[jz - 1] -= i << (24 - q0); + ih = iq[jz - 1] >> (23 - q0); + } else if (q0 == 0) { + ih = iq[jz - 1] >> 23; + } else if (z >= 0.5) { + ih = 2; + } else { + /* No action required */ + } + + /* for the cases that the angle is in the upper side of the quadrant, the complementary is computed */ + if (ih > 0) { /* q > 0.5 */ + n += 1; + carry = 0; + + for (i = 0; i < jz ; i++) { /* compute 1-q by computing the complementary of iq */ + j = iq[i]; + + if (carry == 0) { + if (j != 0) { + carry = 1; + iq[i] = 0x1000000 - j; + } + } else { + iq[i] = 0xffffff - j; + } + } + + if (q0 > 0) { /* rare case: chance is 1 in 12 */ + switch (q0) { + default: /* FALLTHRU */ + case 1: + iq[jz - 1] &= 0x7fffff; + break; + + case 2: + iq[jz - 1] &= 0x3fffff; + break; + } + } + + if (ih == 2) { /* compute the complementary of z */ + z = one - z; + + /* in case that iq[] does have a contribution, subtract the order of magnitude + of this contribution from the complement of z so that z + iq can be computed. */ + if (carry != 0) { + z -= scalbn(one, (int32_t)q0); + /* Given the following decimal example of: z = 0.7 and iq = 0.01 for the angle z + iq = 0.71 + the complements would be z = 1 - z = 0.3 and iq = 0.1 - iq = 0.09 + now, z needs to be decremented by 0.1; z = z - 0.1 so that z + iq = 0.2 + 0.09 = 0.29 + which is the correct complement of the original angle 0.71 */ + } + } + } + + /* check if recomputation is needed in case of loss of significance in z and iq[] */ + if (z == zero) { + j = 0; + + for (i = jz - 1; i >= jk; i--) { + j |= iq[i]; + } + + if (j == 0) { /* need recomputation */ + for (k = 1; (jk - k >= 0) && (iq[jk - k] == 0); k++) { /* k = no. of terms needed */ + } + + /* add q[jz+1] to q[jz+k] + don't pull more terms of ipio2[] than available + and don't overflow f[] */ + for (i = jz + 1; i <= jz + k; i++) { + if ((jv + i < 66) && + (jx + i < 20)) { + f[jx + i] = (double) ipio2[jv + i]; + } else { + exhausted = true; + } + + for (j = 0, fw = 0.0; j <= jx; j++) { + fw += x[j] * f[jx + i - j]; + } + + q[i] = fw; + } + + jz += k; + recompute = true; + } + } + /* The original authors of the algorithm Payne and Hanek estimate the + amount of needed recomputing to be low. Currently only 2 recomputes + are observed at most */ + } while (recompute && !exhausted); + + /* chop off zero terms */ + if (z == 0.0) { + q0 -= 24; + + for (jz -= 1; jz>=0; --jz) { + if (iq[jz]!=0) { + break; + } + q0 -= 24; + } + } else { /* break z into 24-bit if necessary */ + z = scalbn(z, -(int32_t)q0); + + if (z >= two24) { + fw = (double)((int32_t)(twon24 * z)); + iq[jz] = (int32_t)(z - two24 * fw); + jz += 1; + q0 += 24; + iq[jz] = (int32_t) fw; + } else { + iq[jz] = (int32_t) z ; + } + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbn(one, (int32_t)q0); + + for (i = jz; i >= 0; i--) { + q[i] = fw * (double)iq[i]; + fw *= twon24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for (i = jz; i >= 0; i--) { + for (fw = 0.0, k = 0; k <= jp && k <= jz - i; k++) { + fw += PIo2[k] * q[i + k]; + } + + fq[jz - i] = fw; + } + + /* compress fq[] into y[] */ + fw = 0.0; + + for (i = jz; i >= 0; i--) { + fw += fq[i]; + } + + y[0] = (ih == 0) ? fw : -fw; + fw = fq[0] - fw; + + for (i = 1; i <= jz; i++) { + fw += fq[i]; + } + + y[1] = (ih == 0) ? fw : -fw; + + return n & 7; +} + +/* __rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __rem_pio2_internal() + */ + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ +static const double +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ +pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ +pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ +pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ +pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ +pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ +pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +int32_t __rem_pio2(double x, double *y) +{ + double z = 0.0, w, t, r, fn; + double tx[3]; + int32_t i, j, n, ix, hx; + int32_t e0, nx; + uint32_t low; + + GET_HIGH_WORD(hx, x); /* high word of x */ + ix = hx & 0x7fffffff; + + if (ix <= 0x3fe921fb) { /* |x| ~<= pi/4 , no need for reduction */ + y[0] = x; + y[1] = 0; + return 0; + } + + if (ix < 0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ + if (hx > 0) { + z = x - pio2_1; + + if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z - pio2_1t; + y[1] = (z - y[0]) - pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z - y[0]) - pio2_2t; + } + + return 1; + } else { /* negative x */ + z = x + pio2_1; + + if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z + pio2_1t; + y[1] = (z - y[0]) + pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z - y[0]) + pio2_2t; + } + + return -1; + } + } + + if (ix <= 0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ + t = fabs(x); + n = (int32_t)(t * invpio2 + half); + fn = (double)n; + r = t - fn * pio2_1; + w = fn * pio2_1t; /* 1st round good to 85 bit */ + + { + uint32_t high; + j = ix >> 20; + y[0] = r - w; + GET_HIGH_WORD(high, y[0]); + i = j - ((high >> 20) & 0x7ff); + + if (i > 16) { /* 2nd iteration needed, good to 118 */ + t = r; + w = fn * pio2_2; + r = t - w; + w = fn * pio2_2t - ((t - r) - w); + y[0] = r - w; + GET_HIGH_WORD(high, y[0]); + i = j - ((high >> 20) & 0x7ff); + + if (i > 49) { /* 3rd iteration need, 151 bits acc */ + t = r; /* will cover all possible cases */ + w = fn * pio2_3; + r = t - w; + w = fn * pio2_3t - ((t - r) - w); + y[0] = r - w; + } + } + } + + y[1] = (r - y[0]) - w; + + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } else { + return n; + } + } + + /* + * all other (large) arguments + */ + if (ix >= 0x7ff00000) { /* x is inf or NaN */ + if (isnan(x)) { + y[1] = x - x; + y[0] = y[1]; + } else { + y[1] = __raise_invalid(); + y[0] = y[1]; + } + return 0; + } + + /* set z = scalbn(|x|,ilogb(x)-23) */ + GET_LOW_WORD(low, x); + SET_LOW_WORD(z, low); + e0 = (int32_t)((ix >> 20) - 1046); /* e0 = ilogb(z)-23; */ + SET_HIGH_WORD(z, ix - ((int32_t)e0 << 20)); + + for (i = 0; i < 2; i++) { + tx[i] = (double)((int32_t)(z)); + z = (z - tx[i]) * two24; + } + + tx[2] = z; + + for (nx = 3; nx>1; --nx) { /* skip zero term */ + if (tx[nx-1]!=zero) { + break; + } + } + + n = __rem_pio2_internal(tx, y, e0, nx); + + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } + + return n; +} + +static const double +C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ +C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ +C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ +C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ +C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ +C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +double __cos(double x, double y) +{ + double hz, z, r, w; + + z = x * x; + r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6))))); + hz = 0.5 * z; + w = one - hz; + return w + (((one - w) - hz) + (z * r - x * y)); +} + +static const double +S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ +S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ +S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ +S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ +S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ +S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +double __sin(double x, double y, int iy) +{ + double z, r, v; + + z = x * x; + v = z * x; + r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); + + if (iy == 0) { + return x + v * (S1 + z * r); + } else { + return x - ((z * (half * y - v * r) - y) - v * S1); + } +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/internal/trigd.h b/libm/libmcs/libm/mathd/internal/trigd.h new file mode 100644 index 00000000..1ff33be8 --- /dev/null +++ b/libm/libmcs/libm/mathd/internal/trigd.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_TRIGD_H +#define LIBMCS_TRIGD_H + +#include "../../common/tools.h" + +extern double __sin(double x, double y, int iy); +extern double __cos(double x, double y); +extern int32_t __rem_pio2(double x, double *y); + +#endif /* !LIBMCS_TRIGD_H */ diff --git a/libm/libmcs/libm/mathd/j0d.c b/libm/libmcs/libm/mathd/j0d.c new file mode 100644 index 00000000..58d263f3 --- /dev/null +++ b/libm/libmcs/libm/mathd/j0d.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This function implements the Bessel function of the first kind of + * order 0. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * double j0(double x); + * + * Description + * =========== + * + * ``j0`` computes the Bessel value of :math:`x` of the first kind of order 0. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * j0(x) = J_{0}(x) + * + * Notice that the mathematical function represented by the procedure ``j0`` is + * not :math:`j_0` (which is the spherical version of the Bessel function) but + * :math:`J_0`. See `WolframAlpha + * `_ for what it looks like + * and `Wikipedia `_ for more + * information. + * + * Returns + * ======= + * + * ``j0`` returns the Bessel value of :math:`x` of the first kind of order 0. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==============+==============+==============+==============+==============+==============+ + * | **j0(x)** | :math:`+0` | :math:`J_{0}(x)` | :math:`+0` | :math:`qNaN` | + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * + */ + +#include +#include "internal/besseld.h" +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +/* R0/S0 on [0, 2.00] */ +R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */ +R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */ +R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */ +R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */ +S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */ +S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */ +S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ +S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ + +double j0(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double z, s, c, ss, cc, r, u, v; + int32_t hx, ix; + + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x7ff00000) { + return one / (x * x); + } + + x = fabs(x); + + if (ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(x); + c = cos(x); + ss = s - c; + cc = s + c; + + if (ix < 0x7fe00000) { /* make sure x+x not overflow */ + z = -cos(x + x); + + if ((s * c) < zero) { + cc = z / ss; + } else { + ss = z / cc; + } + } + + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + if (ix > 0x48000000) { + z = (invsqrtpi * cc) / sqrt(x); + } else { + u = __j0_p(x); + v = __j0_q(x); + z = invsqrtpi * (u * cc - v * ss) / sqrt(x); + } + + return z; + } + + if (ix < 0x3f200000) { /* |x| < 2**-13 */ + if (x != 0.0) { + (void)__raise_inexact(x); /* raise inexact if x != 0 */ + } + if (ix < 0x3e400000) { + return one; /* |x|<2**-27 */ + } else { + return one - 0.25 * x * x; + } + } + + z = x * x; + r = z * (R02 + z * (R03 + z * (R04 + z * R05))); + s = one + z * (S01 + z * (S02 + z * (S03 + z * S04))); + + if (ix < 0x3FF00000) { /* |x| < 1.00 */ + return one + z * (-0.25 + (r / s)); + } else { + u = 0.5 * x; + return ((one + u) * (one - u) + z * (r / s)); + } +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/j1d.c b/libm/libmcs/libm/mathd/j1d.c new file mode 100644 index 00000000..321255a9 --- /dev/null +++ b/libm/libmcs/libm/mathd/j1d.c @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This function implements the Bessel function of the first kind of + * order 1. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * double j1(double x); + * + * Description + * =========== + * + * ``j1`` computes the Bessel value of :math:`x` of the first kind of order 1. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * j1(x) = J_{1}(x) + * + * Notice that the mathematical function represented by the procedure ``j1`` is + * not :math:`j_1` (which is the spherical version of the Bessel function) but + * :math:`J_1`. See `WolframAlpha J1(x) + * `_ for what it looks like + * and `Wikipedia `_ for more + * information. + * + * Returns + * ======= + * + * ``j1`` returns the Bessel value of :math:`x` of the first kind of order 1. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==============+==============+==============+==============+==============+==============+ + * | **j1(x)** | :math:`+0` | :math:`J_{1}(x)` | :math:`+0` | :math:`qNaN` | + * +---------------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ + * + */ + +#include +#include "internal/besseld.h" +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +/* R0/S0 on [0,2] */ +r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */ +r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */ +r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */ +r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */ +s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */ +s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */ +s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */ +s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ +s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ + +double j1(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double z, s, c, ss, cc, r, u, v, y; + int32_t hx, ix; + + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x7ff00000) { + return one / x; + } + + y = fabs(x); + + if (ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(y); + c = cos(y); + ss = -s - c; + cc = s - c; + + if (ix < 0x7fe00000) { /* make sure y+y not overflow */ + z = cos(y + y); + + if ((s * c) > zero) { + cc = z / ss; + } else { + ss = z / cc; + } + } + + /* + * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) + * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) + */ + if (ix > 0x48000000) { + z = (invsqrtpi * cc) / sqrt(y); + } else { + u = __j1_p(y); + v = __j1_q(y); + z = invsqrtpi * (u * cc - v * ss) / sqrt(y); + } + + if (hx < 0) { + return -z; + } else { + return z; + } + } + + if (ix < 0x3e400000) { /* |x|<2**-27 */ + if (x != 0.0) { + (void)__raise_inexact(x); /* raise inexact if x != 0 */ + } + return 0.5 * x; + } + + z = x * x; + r = z * (r00 + z * (r01 + z * (r02 + z * r03))); + s = one + z * (s01 + z * (s02 + z * (s03 + z * (s04 + z * s05)))); + r *= x; + return (x * 0.5 + r / s); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/jnd.c b/libm/libmcs/libm/mathd/jnd.c new file mode 100644 index 00000000..e9b681fa --- /dev/null +++ b/libm/libmcs/libm/mathd/jnd.c @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This function implements the Bessel function of the first kind of + * order :math:`n`. + * + * .. warning:: + * The implementation contains a potentially unbounded while loop. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * double jn(int n, double x); + * + * Description + * =========== + * + * ``jn`` computes the Bessel value of :math:`x` of the first kind of order + * :math:`n`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * jn(n, x) = J_{n}(x) + * + * Notice that the mathematical function represented by the procedure ``jn`` is + * not :math:`j_n` (which is the spherical version of the Bessel function) but + * :math:`J_n`. See `WolframAlpha Jn(x) + * `_ for what it looks like + * (it shows the different :math:`n` quite nicely in a 3D plot) and `Wikipedia + * `_ for more information. + * + * Returns + * ======= + * + * ``jn`` returns the Bessel value of :math:`x` of the first kind of order + * :math:`n`. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+ + * | jn(n,x) | n | + * +--------------------------+--------------------------+--------------------------+ + * | x | :math:`<0` | :math:`>0` | + * +==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`+0` | + * +--------------------------+--------------------------+--------------------------+ + * | :math:`<0` | :math:`J_{-n}(-x)` | :math:`J_{n}(x)` | + * +--------------------------+ + + + * | :math:`-0` | | | + * +--------------------------+ + + + * | :math:`+0` | | | + * +--------------------------+ + + + * | :math:`>0` | | | + * +--------------------------+--------------------------+--------------------------+ + * | :math:`+Inf` | :math:`+0` | + * +--------------------------+--------------------------+--------------------------+ + * | :math:`NaN` | :math:`qNaN` | + * +--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "internal/besseld.h" +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double jn(int n, double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t i, hx, ix, lx, sgn; + double a, b, temp, di; + double z, w; + + /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) + * Thus, J(-n,x) = J(n,-x) + */ + EXTRACT_WORDS(hx, lx, x); + ix = 0x7fffffff & hx; + + /* if J(n,NaN) is NaN */ + if ((ix | ((uint32_t)(lx | -lx)) >> 31) > 0x7ff00000) { + return x + x; + } + + if (n < 0) { + n = -n; + x = -x; + hx ^= 0x80000000U; + } + + if (n == 0) { + return (j0(x)); + } + + if (n == 1) { + return (j1(x)); + } + + sgn = (n & 1) & (hx >> 31); /* even n -- 0, odd n -- sign(x) */ + x = fabs(x); + + if ((ix | lx) == 0 || ix >= 0x7ff00000) { /* if x is 0 or inf */ + b = zero; + } else if ((double)n <= x) { + /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ + if (ix >= 0x52D00000) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + switch (n & 3) { + default: /* FALLTHRU */ + case 0: + temp = cos(x) + sin(x); + break; + + case 1: + temp = -cos(x) + sin(x); + break; + + case 2: + temp = -cos(x) - sin(x); + break; + + case 3: + temp = cos(x) - sin(x); + break; + } + + b = invsqrtpi * temp / sqrt(x); + } else { + a = j0(x); + b = j1(x); + + for (i = 1; i < n; i++) { + temp = b; + b = b * ((double)(i + i) / x) - a; /* avoid underflow */ + a = temp; + } + } + } else { + if (ix < 0x3e100000) { /* x < 2**-29 */ + /* x is tiny, return the first Taylor expansion of J(n,x) + * J(n,x) = 1/n!*(x/2)^n - ... + */ + if (n > 33) { /* underflow */ + b = zero; + } else { + temp = x * 0.5; + b = temp; + + for (a = one, i = 2; i <= n; i++) { + a *= (double)i; /* a = n! */ + b *= temp; /* b = (x/2)^n */ + } + + b = b / a; + } + } else { + /* use backward recurrence */ + /* x x^2 x^2 + * J(n,x)/J(n-1,x) = ---- ------ ------ ..... + * 2n - 2(n+1) - 2(n+2) + * + * 1 1 1 + * (for large x) = ---- ------ ------ ..... + * 2n 2(n+1) 2(n+2) + * -- - ------ - ------ - + * x x x + * + * Let w = 2n/x and h=2/x, then the above quotient + * is equal to the continued fraction: + * 1 + * = ----------------------- + * 1 + * w - ----------------- + * 1 + * w+h - --------- + * w+2h - ... + * + * To determine how many terms needed, let + * Q(0) = w, Q(1) = w(w+h) - 1, + * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), + * When Q(k) > 1e4 good for single + * When Q(k) > 1e9 good for double + * When Q(k) > 1e17 good for quadruple + */ + /* determine k */ + double t, v; + double q0, q1, h, tmp; + int32_t k, m; + w = (n + n) / (double)x; + h = 2.0 / (double)x; + q0 = w; + z = w + h; + q1 = w * z - 1.0; + k = 1; + + while (q1 < 1.0e9) { + k += 1; + z += h; + tmp = z * q1 - q0; + q0 = q1; + q1 = tmp; + } + + m = n + n; + + for (t = zero, i = 2 * (n + k); i >= m; i -= 2) { + t = one / (i / x - t); + } + + a = t; + b = one; + /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) + * Hence, if n*(log(2n/x)) > ... + * single 8.8722839355e+01 + * double 7.09782712893383973096e+02 + * long double 1.1356523406294143949491931077970765006170e+04 + * then recurrent value may overflow and the result is + * likely underflow to zero + */ + tmp = n; + v = two / x; + tmp = tmp * log(fabs(v * tmp)); + + if (tmp < 7.09782712893383973096e+02) { + for (i = n - 1, di = (double)(i + i); i > 0; i--) { + temp = b; + b *= di; + b = b / x - a; + a = temp; + di -= two; + } + } else { + for (i = n - 1, di = (double)(i + i); i > 0; i--) { + temp = b; + b *= di; + b = b / x - a; + a = temp; + di -= two; + + /* scale b to avoid spurious overflow */ + if (b > 1e100) { + a /= b; + t /= b; + b = one; + } + } + } + + b = (t * j0(x) / b); + } + } + + if (sgn != 0) { + return -b; + } else { + return b; + } +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/ldexpd.c b/libm/libmcs/libm/mathd/ldexpd.c new file mode 100644 index 00000000..046d68f7 --- /dev/null +++ b/libm/libmcs/libm/mathd/ldexpd.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions multiplies the input value :math:`x` by an integral + * power of :math:`2`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float ldexpf(float x, int exp); + * double ldexp(double x, int exp); + * long double ldexpl(long double x, int exp); + * + * Description + * =========== + * + * ``ldexp`` multiplies the input value :math:`x` by an integral power of :math:`2`. + * + * ``ldexp`` and :ref:`scalbn` have the same functionality. In theory their + * definition could be different, but this only applies to architectures which + * do not use a binary system, which by now are assumed to be an obscurity. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * ldexp(x, exp) \approx x \cdot 2^{exp} + * + * Returns + * ======= + * + * ``ldexp`` returns the input value :math:`x` multiplied by :math:`2` powered + * by the input value :math:`exp`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception if the result overflows. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | ldexp(x,exp) | exp | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | x | :math:`<0` | :math:`0` | :math:`>0` | + * +=====================+=========================+=========================+=========================+ + * | :math:`-Inf` | :math:`x` | :math:`x` | :math:`x` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`<0` | :math:`x \cdot 2^{exp}` | | :math:`x \cdot 2^{exp}` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`-0` | :math:`x` | | :math:`x` | + * +---------------------+ + + + + * | :math:`+0` | | | | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`>0` | :math:`x \cdot 2^{exp}` | | :math:`x \cdot 2^{exp}` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`+Inf` | :math:`x` | | :math:`x` | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | :math:`NaN` | :math:`qNaN` | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double ldexp(double x, int exp) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + if ((isfinite(x) == 0) || (x == 0.0)) { + return x + x; + } + + return scalbn(x, exp); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double ldexpl(long double x, int exp) +{ + return (long double) ldexp((double) x, exp); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/lgammad.c b/libm/libmcs/libm/mathd/lgammad.c new file mode 100644 index 00000000..c5a63618 --- /dev/null +++ b/libm/libmcs/libm/mathd/lgammad.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the natural logarithm of the gamma + * function of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float lgammaf(float x); + * double lgamma(double x); + * long double lgammal(long double x); + * + * Description + * =========== + * + * ``lgamma`` computes the natural logarithm of the gamma function of :math:`x`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * lgamma(x) \approx \ln{|\Gamma(x)|} = \ln{\left|\int_{0}^{\infty}e^{-t}t^{x-1}dt\right|} + * + * Returns + * ======= + * + * ``lgamma`` returns the natural logarithm of the gamma function of :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``divide by zero`` exception when the input value is a negative + * integer or zero. + * + * Raise ``overflow`` exception when the magnitude of the input value is too + * large. + * + * Output map + * ========== + * + * +---------------------+--------------+---------------------------------------+-----------------------------+--------------+--------------+--------------------------+--------------+--------------------------+--------------+--------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0\ \wedge\ \notin \mathbb{Z}` | :math:`\in \mathbb{Z}_{<0}` | :math:`-0` | :math:`+0` | :math:`]0,1[` | :math:`+1` | :math:`]1,2[` | :math:`+2` | :math:`>2` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=======================================+=============================+==============+==============+==========================+==============+==========================+==============+==========================+==============+==============+ + * | **lgamma(x)** | :math:`+Inf` | :math:`\ln{|\Gamma(x)|}` | :math:`+Inf` | :math:`+Inf` | :math:`\ln{|\Gamma(x)|}` | :math:`+0` | :math:`\ln{|\Gamma(x)|}` | :math:`+0` | :math:`\ln{|\Gamma(x)|}` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+---------------------------------------+-----------------------------+--------------+--------------+--------------------------+--------------+--------------------------+--------------+--------------------------+--------------+--------------+ + * + */ + +#include +#include "internal/gammad.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double lgamma(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return __lgamma(x, &__signgam); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double lgammal(long double x) +{ + return (long double) lgamma((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/llrintd.c b/libm/libmcs/libm/mathd/llrintd.c new file mode 100644 index 00000000..d756ecc1 --- /dev/null +++ b/libm/libmcs/libm/mathd/llrintd.c @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* lrint adapted to be llrint for Newlib, 2009 by Craig Howland. */ + +/** + * + * This family of functions implements the nearest integer value to :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * long long int llrintf(float x); + * long long int llrint(double x); + * long long int llrintl(long double x); + * + * Description + * =========== + * + * ``llrint`` computes the nearest integer value to :math:`x`. Functionally the + * same procedure as :ref:`lrint` but returns ``long long int`` instead of + * ``long int``. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * llrint(x) = \lfloor x \rceil + * + * Returns + * ======= + * + * ``llrint`` returns the nearest integer value to :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the correct result is not + * representable as the output type. This is the case when the input value is + * infinite or :math:`NaN`, or the magnitude of the result is too large to be + * represented. + * + * Output map + * ========== + * + * +---------------------+--------------------------+---------------------------------------+--------------------------+--------------+--------------+--------------------------+---------------------------------------+--------------------------+--------------------------+ + * | **x** | :math:`-Inf` | :math:`<` min :math:`\mathbb{I}_{ll}` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`>` max :math:`\mathbb{I}_{ll}` | :math:`+Inf` | :math:`NaN` | + * +=====================+==========================+=======================================+==========================+==============+==============+==========================+=======================================+==========================+==========================+ + * | **llrint(x)** | min :math:`\mathbb{I}_{ll}` | :math:`\lfloor x \rceil` | :math:`x` | :math:`\lfloor x \rceil` | max :math:`\mathbb{I}_{ll}` | :math:`llrint(±Inf)` | + * +---------------------+--------------------------+---------------------------------------+--------------------------+--------------+--------------+--------------------------+---------------------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +/* Adding a double, x, to 2^52 will cause the result to be rounded based on + the fractional part of x, according to the implementation's current rounding + mode. 2^52 is the smallest double that can be represented using all 52 significant + digits. */ +static const double TWO52[2] = { + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +long long int llrint(double x) +{ + int32_t _i0, _j0, sx; + uint32_t _i1; + double t; + volatile double w; + long long int result; + + EXTRACT_WORDS(_i0, _i1, x); + + /* Extract sign bit. */ + sx = (_i0 >> 31) & 1; + + /* Extract exponent field. */ + _j0 = ((_i0 & 0x7ff00000) >> 20) - 1023; + /* _j0 in [-1023,1024] */ + + if (_j0 < 20) { + /* _j0 in [-1023,19] */ + if (_j0 < -1) { + return 0; + } else { + /* _j0 in [0,19] */ + /* shift amt in [0,19] */ + w = TWO52[sx] + x; + t = w - TWO52[sx]; + GET_HIGH_WORD(_i0, t); + + /* Detect the all-zeros representation of plus and + minus zero, which fails the calculation below. */ + if ((_i0 & ~((int32_t)1 << 31)) == 0) { + return 0; + } + + /* After round: _j0 in [0,20] */ + _j0 = ((_i0 & 0x7ff00000) >> 20) - 1023; + _i0 &= 0x000fffff; + _i0 |= 0x00100000; + /* shift amt in [20,0] */ + result = _i0 >> (20 - _j0); + } + } else if ((uint32_t)_j0 < (8 * sizeof(long long int)) - 1) { + /* 64bit return: _j0 in [20,62] */ + if (_j0 >= 52) { + /* 64bit return: _j0 in [52,62] */ + /* 64bit return: left shift amt in [32,42] */ + result = ((long long int)((_i0 & 0x000fffff) | 0x00100000) << (_j0 - 20)) | + /* 64bit return: right shift amt in [0,10] */ + ((long long int) _i1 << (_j0 - 52)); + } else { + /* 64bit return: _j0 in [20,51] */ + w = TWO52[sx] + x; + t = w - TWO52[sx]; + EXTRACT_WORDS(_i0, _i1, t); + _j0 = ((_i0 & 0x7ff00000) >> 20) - 1023; + _i0 &= 0x000fffff; + _i0 |= 0x00100000; + /* After round: + * 64bit return: _j0 in [20,52] */ + /* 64bit return: left shift amt in [0,32] */ + /* ***64bit return: right shift amt in [32,0] */ + result = ((long long int) _i0 << (_j0 - 20)) | SAFE_RIGHT_SHIFT(_i1, (uint32_t)(52 - _j0)); + } + } else { + (void) __raise_invalid(); + if (sx != 0) { + return __MIN_LONG_LONG; + } + else { + return __MAX_LONG_LONG; + } + } + + return (sx != 0) ? -result : result; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long long int llrintl(long double x) +{ + return llrint((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/llroundd.c b/libm/libmcs/libm/mathd/llroundd.c new file mode 100644 index 00000000..ec106a18 --- /dev/null +++ b/libm/libmcs/libm/mathd/llroundd.c @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* lround adapted to be llround for Newlib, 2009 by Craig Howland. */ + +/** + * + * This family of functions implements the nearest integer value to :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * long long int llroundf(float x); + * long long int llround(double x); + * long long int llroundl(long double x); + * + * Description + * =========== + * + * ``llround`` computes the nearest integer value to :math:`x`. Functionally + * the same procedure as :ref:`lround` but returns ``long long int`` instead of + * ``long int``. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * llround(x) = \lfloor x \rceil + * + * Returns + * ======= + * + * ``llround`` returns the nearest integer value to :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the correct result is not + * representable as the output type. This is the case when the input value is + * infinite or :math:`NaN`, or the magnitude of the result is too large to be + * represented. + * + * Output map + * ========== + * + * +---------------------+--------------------------+---------------------------------------+--------------------------+--------------+--------------+--------------------------+---------------------------------------+--------------------------+--------------------------+ + * | **x** | :math:`-Inf` | :math:`<` min :math:`\mathbb{I}_{ll}` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`>` max :math:`\mathbb{I}_{ll}` | :math:`+Inf` | :math:`NaN` | + * +=====================+==========================+=======================================+==========================+==============+==============+==========================+=======================================+==========================+==========================+ + * | **llround(x)** | min :math:`\mathbb{I}_{ll}` | :math:`\lfloor x \rceil` | :math:`x` | :math:`\lfloor x \rceil` | max :math:`\mathbb{I}_{ll}` | :math:`llround(±Inf)` | + * +---------------------+--------------------------+---------------------------------------+--------------------------+--------------+--------------+--------------------------+---------------------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +long long int llround(double x) +{ + int32_t sign, exponent_less_1023; + /* Most significant word, least significant word. */ + uint32_t msw, lsw; + long long int result; + + EXTRACT_WORDS(msw, lsw, x); + + /* Extract sign. */ + sign = ((msw & 0x80000000U) ? -1 : 1); + /* Extract exponent field. */ + exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023; + msw &= 0x000fffff; + msw |= 0x00100000; + + /* exponent_less_1023 in [-1023,1024] */ + if (exponent_less_1023 < 20) { + /* exponent_less_1023 in [-1023,19] */ + if (exponent_less_1023 < 0) { + if (exponent_less_1023 < -1) { + return 0; + } else { + return sign; + } + } else { + /* exponent_less_1023 in [0,19] */ + /* shift amt in [0,19] */ + msw += 0x80000 >> exponent_less_1023; + /* shift amt in [20,1] */ + result = msw >> (20 - exponent_less_1023); + } + } else if ((uint32_t)exponent_less_1023 < (8 * sizeof(long long int)) - 1) { + /* 64bit longlong: exponent_less_1023 in [20,62] */ + if (exponent_less_1023 >= 52) { + /* 64bit longlong: exponent_less_1023 in [52,62] */ + /* 64bit longlong: shift amt in [32,42] */ + result = ((long long int) msw << (exponent_less_1023 - 20)) + /* 64bit longlong: shift amt in [0,10] */ + | ((long long int) lsw << (exponent_less_1023 - 52)); + } else { + /* 64bit longlong: exponent_less_1023 in [20,51] */ + /* 64bit longlong: shift amt in [0,31] */ + uint32_t tmp = lsw + (0x80000000U >> (exponent_less_1023 - 20)); + + if (tmp < lsw) { + ++msw; + } + + /* 64bit longlong: shift amt in [0,31] */ + result = ((long long int) msw << (exponent_less_1023 - 20)) + /* ***64bit longlong: shift amt in [32,1] */ + | SAFE_RIGHT_SHIFT(tmp, (uint32_t)(52 - exponent_less_1023)); + } + } else { /* Result is too large to be represented by a long long int. */ + (void) __raise_invalid(); + if (sign == -1) { + return __MIN_LONG_LONG; + } + else { + return __MAX_LONG_LONG; + } + } + + return sign * result; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long long int llroundl(long double x) +{ + return llround((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/log10d.c b/libm/libmcs/libm/mathd/log10d.c new file mode 100644 index 00000000..572ab37b --- /dev/null +++ b/libm/libmcs/libm/mathd/log10d.c @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the base :math:`10` logarithm. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float log10f(float x); + * double log10(double x); + * long double logl(long double x); + * + * Description + * =========== + * + * ``log10`` computes the base :math:`10` logarithm of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * log10(x) \approx log_{10}(x) + * + * Returns + * ======= + * + * ``log10`` returns the base :math:`10` logarithm of :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is negative. + * + * Raise ``divide by zero`` exception when the input value is zero. + * + * Output map + * ========== + * + * +---------------------+---------------+---------------+---------------+---------------+---------------------+---------------+---------------------+---------------+---------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`]0,1[` | :math:`1` | :math:`>1` | :math:`+Inf` | :math:`NaN` | + * +=====================+===============+===============+===============+===============+=====================+===============+=====================+===============+===============+ + * | **log10(x)** | :math:`qNaN` | :math:`qNaN` | :math:`-Inf` | :math:`log_{10}(x)` | :math:`+0` | :math:`log_{10}(x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+---------------+---------------+---------------+---------------+---------------------+---------------+---------------------+---------------+---------------+ + * + */ + +#include +#include "../common/tools.h" +#include "internal/log1pmfd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +ivln10hi = 4.34294481878168880939e-01, /* 0x3FDBCB7B, 0x15200000 */ +ivln10lo = 2.50829467116452752298e-11, /* 0x3DBB9438, 0xCA9AADD5 */ +log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ +log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ + +static const double zero = 0.0; + +double log10(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double f, hfsq, hi, lo, r, val_hi, val_lo, w, y, y2; + int32_t i, k, hx; + uint32_t lx; + + EXTRACT_WORDS(hx, lx, x); + + k = 0; + + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx & 0x7fffffff) | lx) == 0) { + return __raise_div_by_zero(-1.0); /* log(+-0)=-inf */ + } + + if (hx < 0) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalid(); /* log(-#) = NaN */ + } + } + + k -= 54; + x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx, x); + } + + if (hx >= 0x7ff00000) { /* x = NaN/+-Inf */ + return x + x; + } + + if (hx == 0x3ff00000 && lx == 0) { /* log(1) = +0 */ + return zero; + } + + k += (hx >> 20) - 1023; + hx &= 0x000fffff; + i = (hx + 0x95f64) & 0x100000; + SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */ + k += (i >> 20); + y = (double)k; + f = x - 1.0; + hfsq = 0.5 * f * f; + r = __log1pmf(f); + + hi = f - hfsq; + SET_LOW_WORD(hi, 0); + lo = (f - hi) - hfsq + r; + val_hi = hi * ivln10hi; + y2 = y * log10_2hi; + val_lo = y * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi; + + /* + * Extra precision in for adding y*log10_2hi is not strictly needed + * since there is no very large cancellation near x = sqrt(2) or + * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs + * with some parallelism and it reduces the error for many args. + */ + w = y2 + val_hi; + val_lo += (y2 - w) + val_hi; + val_hi = w; + + return val_lo + val_hi; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double log10l(long double x) +{ + return (long double) log10((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/log1pd.c b/libm/libmcs/libm/mathd/log1pd.c new file mode 100644 index 00000000..5bd3e331 --- /dev/null +++ b/libm/libmcs/libm/mathd/log1pd.c @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the natural logarithm of :math:`1 + x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float log1pf(float x); + * double log1p(double x); + * long double logl(long double x); + * + * Description + * =========== + * + * ``log1p`` computes the natural logarithm of :math:`1 + x`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * log1p(x) \approx ln(1 + x) + * + * Returns + * ======= + * + * ``log1p`` returns the natural logarithm of :math:`1 + x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is less than :math:`-1`. + * + * Raise ``divide by zero`` exception when the input value is :math:`-1`. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+---------------+---------------+---------------+-------------------+---------------+---------------+-------------------+---------------+---------------+ + * | **x** | :math:`-Inf` | :math:`<-1` | :math:`-1` | :math:`]-1,0[` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+===============+===============+===============+===================+===============+===============+===================+===============+===============+ + * | **log1p(x)** | :math:`qNaN` | :math:`qNaN` | :math:`-Inf` | :math:`ln(1 + x)` | :math:`x` | :math:`ln(1 + x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+---------------+---------------+---------------+-------------------+---------------+---------------+-------------------+---------------+---------------+ + * + */ + +/* double log1p(double x) + * + * Method : + * 1. Argument Reduction: find k and f such that + * 1+x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * Note. If k=0, then f=x is exact. However, if k!=0, then f + * may not be representable exactly. In that case, a correction + * term is need. Let u=1+x rounded. Let c = (1+x)-u, then + * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), + * and add back the correction term c/u. + * (Note: when x > 2**53, one can simply return log(x)) + * + * 2. Approximation of log1p(f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Remez algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s + * (the values of Lp1 to Lp7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lp1*s +...+Lp7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log1p(f) = f - (hfsq - s*(hfsq+R)). + * + * 3. Finally, log1p(x) = k*ln2 + log1p(f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log1p(x) is NaN with signal if x < -1 (including -INF) ; + * log1p(+INF) is +INF; log1p(-1) is -INF with signal; + * log1p(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + * + * Note: Assuming log() return accurate answer, the following + * algorithm can be used to compute log1p(x) to within a few ULP: + * + * u = 1+x; + * if(u==1.0) return x ; else + * return log(u)*(x/(u-1.0)); + * + * See HP-15C Advanced Functions Handbook, p.193. + */ + +#include +#include "../common/tools.h" +#include "internal/log1pmfd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ +ln2_lo = 1.90821492927058770002e-10; /* 3dea39ef 35793c76 */ + +static const double zero = 0.0; + +double log1p(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double hfsq, f, c, R, u; + int32_t k, hx, hu, ax; + + c = NAN; /* initial value of c is never actually used */ + f = NAN; /* initial value of f is never actually used */ + hu = INT_MAX; /* initial value of hu is never actually used */ + + GET_HIGH_WORD(hx, x); + ax = hx & 0x7fffffff; + + k = 1; + + if (hx >= 0x7ff00000) { /* x = NaN/+-Inf */ + return x + x; + } + + if (hx < 0x3FDA827A) { /* x < 0.41422 */ + if (ax >= 0x3ff00000) { /* x <= -1.0 */ + if (isnan(x)) { + return x + x; + } else if (x == -1.0) { + return __raise_div_by_zero(-1.0); /* log1p(-1)=-inf */ + } else { + return __raise_invalid(); /* log1p(x<-1)=NaN */ + } + } + + if (ax < 0x3e200000) { /* |x| < 2**-29 */ + if (ax < 0x3c900000) { /* |x| < 2**-54 */ + return __raise_inexact(x); + } else { + return __raise_inexact(x - x * x * 0.5); + } + } + + if (hx > 0 || hx <= ((int32_t)0xbfd2bec3U)) { + k = 0; + f = x; + hu = 1; + } /* -0.2929> 20) - 1023; + c = (k > 0) ? 1.0 - (u - x) : x - (u - 1.0); /* correction term */ + c /= u; + } else { + u = x; + GET_HIGH_WORD(hu, u); + k = (hu >> 20) - 1023; + c = 0; + } + + hu &= 0x000fffff; + + if (hu < 0x6a09e) { + SET_HIGH_WORD(u, hu | 0x3ff00000); /* normalize u */ + } else { + k += 1; + SET_HIGH_WORD(u, hu | 0x3fe00000); /* normalize u/2 */ + hu = (0x00100000 - hu) >> 2; + } + + f = u - 1.0; + } + + hfsq = 0.5 * f * f; + + if (hu == 0) { /* |f| < 2**-20 */ + if (f == zero) { + c += k * ln2_lo; + return k * ln2_hi + c; + } + + R = hfsq * (1.0 - 0.66666666666666666 * f); + + return k * ln2_hi - ((R - (k * ln2_lo + c)) - f); + } + + if (k == 0) { + return f - (hfsq - __log1pmf(f)); + } else { + return k * ln2_hi - ((hfsq - (__log1pmf(f) + (k * ln2_lo + c))) - f); + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double log1pl(long double x) +{ + return (long double) log1p((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/log2d.c b/libm/libmcs/libm/mathd/log2d.c new file mode 100644 index 00000000..a9741149 --- /dev/null +++ b/libm/libmcs/libm/mathd/log2d.c @@ -0,0 +1,167 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the base :math:`2` logarithm. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float log2f(float x); + * double log2(double x); + * long double logl(long double x); + * + * Description + * =========== + * + * ``log2`` computes the base :math:`2` logarithm of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * log2(x) \approx log_{2}(x) + * + * Returns + * ======= + * + * ``log2`` returns the base :math:`2` logarithm of :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is negative. + * + * Raise ``divide by zero`` exception when the input value is zero. + * + * Output map + * ========== + * + * +---------------------+---------------+---------------+---------------+---------------+---------------------+---------------+---------------------+---------------+---------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`]0,1[` | :math:`1` | :math:`>1` | :math:`+Inf` | :math:`NaN` | + * +=====================+===============+===============+===============+===============+=====================+===============+=====================+===============+===============+ + * | **log2(x)** | :math:`qNaN` | :math:`qNaN` | :math:`-Inf` | :math:`log_{2}(x)` | :math:`+0` | :math:`log_{2}(x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+---------------+---------------+---------------+---------------+---------------------+---------------+---------------------+---------------+---------------+ + * + */ + +#include +#include "../common/tools.h" +#include "internal/log1pmfd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */ +ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */ + +static const double zero = 0.0; + +double log2(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double f, hfsq, hi, lo, r, val_hi, val_lo, w, y; + int32_t i, k, hx; + uint32_t lx; + + EXTRACT_WORDS(hx, lx, x); + + k = 0; + + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx & 0x7fffffff) | lx) == 0) { + return __raise_div_by_zero(-1.0); /* log(+-0)=-inf */ + } + + if (hx < 0) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalid(); /* log(-#) = NaN */ + } + } + + k -= 54; + x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx, x); + } + + if (hx >= 0x7ff00000) { /* x = NaN/+-Inf */ + return x + x; + } + + if (hx == 0x3ff00000 && lx == 0) { /* log(1) = +0 */ + return zero; + } + + k += (hx >> 20) - 1023; + hx &= 0x000fffff; + i = (hx + 0x95f64) & 0x100000; + SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */ + k += (i >> 20); + y = (double)k; + f = x - 1.0; + hfsq = 0.5 * f * f; + r = __log1pmf(f); + + /* + * f-hfsq must (for args near 1) be evaluated in extra precision + * to avoid a large cancellation when x is near sqrt(2) or 1/sqrt(2). + * This is fairly efficient since f-hfsq only depends on f, so can + * be evaluated in parallel with R. Not combining hfsq with R also + * keeps R small (though not as small as a true `lo' term would be), + * so that extra precision is not needed for terms involving R. + * + * Compiler bugs involving extra precision used to break Dekker's + * theorem for spitting f-hfsq as hi+lo, unless double_t was used + * or the multi-precision calculations were avoided when double_t + * has extra precision. These problems are now automatically + * avoided as a side effect of the optimization of combining the + * Dekker splitting step with the clear-low-bits step. + * + * y must (for args near sqrt(2) and 1/sqrt(2)) be added in extra + * precision to avoid a very large cancellation when x is very near + * these values. Unlike the above cancellations, this problem is + * specific to base 2. It is strange that adding +-1 is so much + * harder than adding +-ln2 or +-log10_2. + * + * This uses Dekker's theorem to normalize y+val_hi, so the + * compiler bugs are back in some configurations, sigh. And I + * don't want to used double_t to avoid them, since that gives a + * pessimization and the support for avoiding the pessimization + * is not yet available. + * + * The multi-precision calculations for the multiplications are + * routine. + */ + hi = f - hfsq; + SET_LOW_WORD(hi, 0); + lo = (f - hi) - hfsq + r; + val_hi = hi * ivln2hi; + val_lo = (lo + hi) * ivln2lo + lo * ivln2hi; + + w = y + val_hi; + val_lo += (y - w) + val_hi; + val_hi = w; + + return val_lo + val_hi; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double log2l(long double x) +{ + return (long double) log2((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/logbd.c b/libm/libmcs/libm/mathd/logbd.c new file mode 100644 index 00000000..92cc1cae --- /dev/null +++ b/libm/libmcs/libm/mathd/logbd.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions computes the binary exponent of the input value. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float logbf(float x); + * double logb(double x); + * long double logbl(long double x); + * + * Description + * =========== + * + * ``logb`` computes the binary exponent of the input value. + * + * ``logb`` and :ref:`ilogb` have the same functionality, but ``logb`` returns + * the binary exponent as a floating-point value while :ref:`ilogb` returns a + * signed integer. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * logb(x) \approx \lfloor {\log_2 |x|} \rfloor + * + * Returns + * ======= + * + * ``logb`` returns the binary exponent of the input value. + * + * Exceptions + * ========== + * + * Raise ``divide by zero`` exception when the input value is zero. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------------------------------+--------------+--------------+--------------------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+======================================+==============+==============+======================================+==============+==============+ + * | **logb(x)** | :math:`+Inf` | :math:`\lfloor {\log_2 |x|} \rfloor` | :math:`-Inf` | :math:`\lfloor {\log_2 |x|} \rfloor` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+--------------------------------------+--------------+--------------+--------------------------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double logb(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, lx, ix; + + EXTRACT_WORDS(hx, lx, x); + hx &= 0x7fffffff; /* high |x| */ + + if (hx < 0x00100000) { /* 0 or subnormal */ + if ((hx | lx) == 0) { + return __raise_div_by_zero(-1.0); /* logb(0) = -inf */ + } else { /* subnormal x */ + if (hx == 0) { + for (ix = -1043; lx > 0; lx <<= 1) { + ix -= 1; + } + } else { + for (ix = -1022, hx <<= 11; hx > 0; hx <<= 1) { + ix -= 1; + } + } + } + + return (double) ix; + } else if (hx < 0x7ff00000) { + return (hx >> 20) - 1023; /* normal # */ + } else { + return x * x; /* x = NaN/+-Inf */ + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double logbl(long double x) +{ + return (long double) logb((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/logd.c b/libm/libmcs/libm/mathd/logd.c new file mode 100644 index 00000000..0ceb571e --- /dev/null +++ b/libm/libmcs/libm/mathd/logd.c @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the natural logarithm. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float logf(float x); + * double log(double x); + * long double logl(long double x); + * + * Description + * =========== + * + * ``log`` computes the natural logarithm of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * log(x) \approx ln(x) + * + * Returns + * ======= + * + * ``log`` returns the natural logarithm of :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is negative. + * + * Raise ``divide by zero`` exception when the input value is zero. + * + * Output map + * ========== + * + * +---------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`]0,1[` | :math:`1` | :math:`>1` | :math:`+Inf` | :math:`NaN` | + * +=====================+===============+===============+===============+===============+===============+===============+===============+===============+===============+ + * | **log(x)** | :math:`qNaN` | :math:`qNaN` | :math:`-Inf` | :math:`ln(x)` | :math:`+0` | :math:`ln(x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ +ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ +two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +static const double zero = 0.0; + +double log(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double hfsq, f, s, z, R, w, t1, t2, dk; + int32_t k, hx, i, j; + uint32_t lx; + + EXTRACT_WORDS(hx, lx, x); + + k = 0; + + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx & 0x7fffffff) | lx) == 0) { + return __raise_div_by_zero(-1.0); /* log(+-0)=-inf */ + } + + if (hx < 0) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalid(); /* log(-#) = NaN */ + } + } + + k -= 54; + x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx, x); + } + + if (hx >= 0x7ff00000) { /* x = NaN/+-Inf */ + return x + x; + } + + k += (hx >> 20) - 1023; + hx &= 0x000fffff; + i = (hx + 0x95f64) & 0x100000; + SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */ + k += (i >> 20); + f = x - 1.0; + + if ((0x000fffff & (2 + hx)) < 3) { /* |f| < 2**-20 */ + if (f == zero) { + if (k == 0) { + return zero; + } else { + dk = (double)k; + return dk * ln2_hi + dk * ln2_lo; + } + } + + R = f * f * (0.5 - 0.33333333333333333 * f); + + if (k == 0) { + return f - R; + } else { + dk = (double)k; + return dk * ln2_hi - ((R - dk * ln2_lo) - f); + } + } + + s = f / (2.0 + f); + dk = (double)k; + z = s * s; + i = hx - 0x6147a; + w = z * z; + j = 0x6b851 - hx; + t1 = w * (Lg2 + w * (Lg4 + w * Lg6)); + t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7))); + i |= j; + R = t2 + t1; + + if (i > 0) { + hfsq = 0.5 * f * f; + + if (k == 0) { + return f - (hfsq - s * (hfsq + R)); + } else { + return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f); + } + } else { + if (k == 0) { + return f - s * (f - R); + } else { + return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f); + } + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double logl(long double x) +{ + return (long double) log((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/lrintd.c b/libm/libmcs/libm/mathd/lrintd.c new file mode 100644 index 00000000..c65a715a --- /dev/null +++ b/libm/libmcs/libm/mathd/lrintd.c @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the nearest integer value to :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * long int lrintf(float x); + * long int lrint(double x); + * long int lrintl(long double x); + * + * Description + * =========== + * + * ``lrint`` computes the nearest integer value to :math:`x`. Functionally the + * same procedure as :ref:`rint` but returns ``long int`` instead of a floating + * point value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * lrint(x) = \lfloor x \rceil + * + * Returns + * ======= + * + * ``lrint`` returns the nearest integer value to :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the correct result is not + * representable as the output type. This is the case when the input value is + * infinite or :math:`NaN`, or the magnitude of the result is too large to be + * represented. + * + * Output map + * ========== + * + * +---------------------+--------------------------+------------------------------------+--------------------------+--------------+--------------+--------------------------+------------------------------------+--------------------------+--------------------------+ + * | **x** | :math:`-Inf` | :math:`<` min :math:`\mathbb{I}_l` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`>` max :math:`\mathbb{I}_l` | :math:`+Inf` | :math:`NaN` | + * +=====================+==========================+====================================+==========================+==============+==============+==========================+====================================+==========================+==========================+ + * | **lrint(x)** | min :math:`\mathbb{I}_l` | :math:`\lfloor x \rceil` | :math:`x` | :math:`\lfloor x \rceil` | max :math:`\mathbb{I}_l` | :math:`lrint(±Inf)` | + * +---------------------+--------------------------+------------------------------------+--------------------------+--------------+--------------+--------------------------+------------------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +/* Adding a double, x, to 2^52 will cause the result to be rounded based on + the fractional part of x, according to the implementation's current rounding + mode. 2^52 is the smallest double that can be represented using all 52 significant + digits. */ +static const double TWO52[2] = { + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +long int lrint(double x) +{ + int32_t _i0, _j0, sx; + uint32_t i1; + double t; + volatile double w; + long int result; + + EXTRACT_WORDS(_i0, i1, x); + + /* Extract sign bit. */ + sx = (_i0 >> 31) & 1; + + /* Extract exponent field. */ + _j0 = ((_i0 & 0x7ff00000) >> 20) - 1023; + /* _j0 in [-1023,1024] */ + + if (_j0 < 20) { + /* _j0 in [-1023,19] */ + if (_j0 < -1) { + return 0; + } else { + /* _j0 in [0,19] */ + /* shift amt in [0,19] */ + w = TWO52[sx] + x; + t = w - TWO52[sx]; + GET_HIGH_WORD(_i0, t); + + /* Detect the all-zeros representation of plus and + minus zero, which fails the calculation below. */ + if ((_i0 & ~(1U << 31)) == 0) { + return 0; + } + + /* After round: _j0 in [0,20] */ + _j0 = ((_i0 & 0x7ff00000) >> 20) - 1023; + _i0 &= 0x000fffff; + _i0 |= 0x00100000; + /* shift amt in [20,0] */ + result = _i0 >> (20 - _j0); + } + } else if ((uint32_t)_j0 < (8 * sizeof(long int)) - 1) { + /* 32bit return: _j0 in [20,30] */ + /* 64bit return: _j0 in [20,62] */ + if (_j0 >= 52) { + /* 64bit return: _j0 in [52,62] */ + /* 64bit return: left shift amt in [32,42] */ + result = ((long int)((_i0 & 0x000fffff) | 0x00100000) << (_j0 - 20)) | + /* 64bit return: right shift amt in [0,10] */ + ((long int) i1 << (_j0 - 52)); + } else { + /* 32bit return: _j0 in [20,30] */ + /* 64bit return: _j0 in [20,51] */ + w = TWO52[sx] + x; + t = w - TWO52[sx]; + EXTRACT_WORDS(_i0, i1, t); + _j0 = ((_i0 & 0x7ff00000) >> 20) - 1023; + _i0 &= 0x000fffff; + _i0 |= 0x00100000; + /* After round: + * 32bit return: _j0 in [20,31]; + * 64bit return: _j0 in [20,52] */ + /* 32bit return: left shift amt in [0,11] */ + /* 64bit return: left shift amt in [0,32] */ + /* ***32bit return: right shift amt in [32,21] */ + /* ***64bit return: right shift amt in [32,0] */ + result = ((long int) _i0 << (_j0 - 20)) | SAFE_RIGHT_SHIFT(i1, (uint32_t)(52 - _j0)); + } + } else { + (void) __raise_invalid(); + if (sx != 0) { + return __MIN_LONG; + } + else { + return __MAX_LONG; + } + } + + return (sx != 0) ? -result : result; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long int lrintl(long double x) +{ + return lrint((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/lroundd.c b/libm/libmcs/libm/mathd/lroundd.c new file mode 100644 index 00000000..a0eecff0 --- /dev/null +++ b/libm/libmcs/libm/mathd/lroundd.c @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the nearest integer value to :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * long int lroundf(float x); + * long int lround(double x); + * long int lroundl(long double x); + * + * Description + * =========== + * + * ``lround`` computes the nearest integer value to :math:`x`. Functionally the + * same procedure as :ref:`round` but returns ``long int`` instead of a + * floating point value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * lround(x) = \lfloor x \rceil + * + * Returns + * ======= + * + * ``lround`` returns the nearest integer value to :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the correct result is not + * representable as the output type. This is the case when the input value is + * infinite or :math:`NaN`, or the magnitude of the result is too large to be + * represented. + * + * Output map + * ========== + * + * +---------------------+--------------------------+------------------------------------+--------------------------+--------------+--------------+--------------------------+------------------------------------+--------------------------+--------------------------+ + * | **x** | :math:`-Inf` | :math:`<` min :math:`\mathbb{I}_l` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`>` max :math:`\mathbb{I}_l` | :math:`+Inf` | :math:`NaN` | + * +=====================+==========================+====================================+==========================+==============+==============+==========================+====================================+==========================+==========================+ + * | **lround(x)** | min :math:`\mathbb{I}_l` | :math:`\lfloor x \rceil` | :math:`x` | :math:`\lfloor x \rceil` | max :math:`\mathbb{I}_l` | :math:`lround(±Inf)` | + * +---------------------+--------------------------+------------------------------------+--------------------------+--------------+--------------+--------------------------+------------------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +long int lround(double x) +{ + int32_t sign, exponent_less_1023; + /* Most significant word, least significant word. */ + uint32_t msw, lsw; + long int result; + + EXTRACT_WORDS(msw, lsw, x); + + /* Extract sign. */ + sign = ((msw & 0x80000000U) != 0) ? -1 : 1; + /* Extract exponent field. */ + exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023; + msw &= 0x000fffff; + msw |= 0x00100000; + + /* exponent_less_1023 in [-1023,1024] */ + if (exponent_less_1023 < 20) { + /* exponent_less_1023 in [-1023,19] */ + if (exponent_less_1023 < 0) { + if (exponent_less_1023 < -1) { + return 0; + } else { + return sign; + } + } else { + /* exponent_less_1023 in [0,19] */ + /* shift amt in [0,19] */ + msw += 0x80000 >> exponent_less_1023; + /* shift amt in [20,1] */ + result = msw >> (20 - exponent_less_1023); + } + } else if ((uint32_t)exponent_less_1023 < (8 * sizeof(long int)) - 1) { + /* 32bit long: exponent_less_1023 in [20,30] */ + /* 64bit long: exponent_less_1023 in [20,62] */ + if (exponent_less_1023 >= 52) { + /* 64bit long: exponent_less_1023 in [52,62] */ + /* 64bit long: shift amt in [32,42] */ + result = ((long int) msw << (exponent_less_1023 - 20)) + /* 64bit long: shift amt in [0,10] */ + | ((long int) lsw << (exponent_less_1023 - 52)); + } else { + /* 32bit long: exponent_less_1023 in [20,30] */ + /* 64bit long: exponent_less_1023 in [20,51] */ + /* 32bit long: shift amt in [0,10] */ + /* 64bit long: shift amt in [0,31] */ + uint32_t tmp = lsw + (0x80000000U >> (exponent_less_1023 - 20)); + + if (tmp < lsw) { + ++msw; + } + + /* 32bit long: shift amt in [0,10] */ + /* 64bit long: shift amt in [0,31] */ + result = ((long int) msw << (exponent_less_1023 - 20)) + /* ***32bit long: shift amt in [32,22] */ + /* ***64bit long: shift amt in [32,1] */ + | SAFE_RIGHT_SHIFT(tmp, (uint32_t)(52 - exponent_less_1023)); + } + } else { /* Result is too large to be represented by a long int. */ + (void) __raise_invalid(); + if (sign == -1) { + return __MIN_LONG; + } + else { + return __MAX_LONG; + } + } + + return sign * result; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long int lroundl(long double x) +{ + return lround((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/modfd.c b/libm/libmcs/libm/mathd/modfd.c new file mode 100644 index 00000000..cb94c9c8 --- /dev/null +++ b/libm/libmcs/libm/mathd/modfd.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions splits the input value into integral and fractional + * part. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float modff(float x, float *iptr); + * double modf(double x, double *iptr); + * long double modfl(long double x, long double *iptr); + * + * Description + * =========== + * + * ``modf`` splits the input value into integral and fractional part, each of + * which have the same sign. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * modf(x) = x - iptr \wedge \left\{\begin{array}{ll} iptr = \lfloor x \rfloor, & x \geq 0 \\ iptr = \lceil x \rceil, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``modf`` returns the fractional part of :math:`x` in the range + * :math:`]-1.0,1.0[` and puts the integral part into the output pointer + * :math:`*iptr`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+----------------------------------+--------------+--------------+----------------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================================+==============+==============+==================================+==============+==============+ + * | **modf(x)** | :math:`-0` | :math:`x - \lceil x \rceil` | :math:`x` | :math:`x - \lfloor x \rfloor` | :math:`+0` | :math:`qNaN` | + * +---------------------+--------------+----------------------------------+--------------+--------------+----------------------------------+--------------+ + + * | :math:`*iptr` | :math:`-Inf` | :math:`\lceil x \rceil` | :math:`x` | :math:`\lfloor x \rfloor` | :math:`+Inf` | | + * +---------------------+--------------+----------------------------------+--------------+--------------+----------------------------------+--------------+--------------+ + * + */ + +#include +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double modf(double x, double *iptr) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double _xi = 0.0; + int32_t _i0, _i1, _j0; + uint32_t i; + + assert(iptr != (void*)0); + if(iptr == (void*)0) { + iptr = &_xi; + } + + 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 & 0x80000000U, 0U); /* *iptr = +-0 */ + return x; + } else { + i = (0x000fffff) >> _j0; + + if (((_i0 & i) | _i1) == 0) { /* x is integral */ + *iptr = x; + INSERT_WORDS(x, _i0 & 0x80000000U, 0U); /* return +-0 */ + return x; + } else { + INSERT_WORDS(*iptr, _i0 & (~i), 0); + return x - *iptr; + } + } + } else if (_j0 > 51) { /* no fraction part */ + *iptr = x; + + if (isnan(x)) { + return *iptr = x + x; /* x is NaN, return NaN */ + } + + INSERT_WORDS(x, _i0 & 0x80000000U, 0U); /* return +-0 */ + return x; + } else { /* fraction part in low x */ + i = ((uint32_t)(0xffffffffU)) >> (_j0 - 20); + + if ((_i1 & i) == 0) { /* x is integral */ + *iptr = x; + INSERT_WORDS(x, _i0 & 0x80000000U, 0U); /* return +-0 */ + return x; + } else { + INSERT_WORDS(*iptr, _i0, _i1 & (~i)); + return x - *iptr; + } + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double modfl(long double x, long double *iptr) +{ + return (long double) modf((double) x, (double *) iptr); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/nand.c b/libm/libmcs/libm/mathd/nand.c new file mode 100644 index 00000000..f08fe216 --- /dev/null +++ b/libm/libmcs/libm/mathd/nand.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This family of functions returns a predefined ``NaN``. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float nanf(const char *payload); + * double nan(const char *payload); + * long double nanl(const char *payload); + * + * Description + * =========== + * + * ``nan`` produces a fixed ``qNaN`` regardless of input. + * + * The return ``qNaN`` is ``0x7FF80000000D067D`` as ``double`` (float: ``0x7FCF067D``). + * + * This procedure is not C standard compliant as the payload parameter is + * ignored. If your platform/toolchain provides ``strtod`` as a workaround the + * call ``strtod("NAN(char-sequence)", NULL);`` can be used as a replacement if + * that functionality is wanted (same with ``strtof`` and ``strtold``). + * + * Returns + * ======= + * + * ``nan`` returns a ``qNaN``. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double nan(const char *payload) +{ + (void)payload; + + double x; + INSERT_WORDS(x,0x7FF80000,0x000D067D); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double nanl(const char *payload) +{ + return (long double) nan(payload); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/nearbyintd.c b/libm/libmcs/libm/mathd/nearbyintd.c new file mode 100644 index 00000000..91c9a137 --- /dev/null +++ b/libm/libmcs/libm/mathd/nearbyintd.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the nearest integer value to :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float nearbyintf(float x); + * double nearbyint(double x); + * long double nearbyintl(long double x); + * + * Description + * =========== + * + * ``nearbyint`` computes the nearest integer value to :math:`x`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * nearbyint(x) = \lfloor x \rceil + * + * Returns + * ======= + * + * ``nearbyint`` returns the nearest integer value to :math:`x`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------------------+--------------+--------------+--------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==========================+==============+==============+==========================+==============+==============+ + * | **nearbyint(x)** | :math:`-Inf` | :math:`\lfloor x \rceil` | :math:`x` | :math:`\lfloor x \rceil` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+--------------------------+--------------+--------------+--------------------------+--------------+--------------+ + * + */ + +#include + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double nearbyint(double x) +{ + return rint(x); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double nearbyintl(long double x) +{ + return (long double) nearbyint((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/nextafterd.c b/libm/libmcs/libm/mathd/nextafterd.c new file mode 100644 index 00000000..c6bea51c --- /dev/null +++ b/libm/libmcs/libm/mathd/nextafterd.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions computes the next floating-point value after + * :math:`x` in direction of :math:`y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float nextafterf(float x, float y); + * double nextafter(double x, double y); + * long double nextafterl(long double x, long double y); + * + * Description + * =========== + * + * ``nextafter`` computes the next floating-point value after :math:`x` in direction of :math:`y`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * nextafter(x, y) = \left\{\begin{array}{ll} y, & x = y \\ \text{min} \{z | z \in \mathbb{F} \wedge z > x\}, & x < y \\ \text{max} \{z | z \in \mathbb{F} \wedge z < x\}, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``nextafter`` returns the the next floating-point value after :math:`x` in + * direction of :math:`y`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the magnitude of :math:`x` is the largest + * finite value representable in the type and :math:`y` is infinite with the + * same sign as :math:`x`. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | nextafter(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`-Inf` | :math:`nextafter(x, y)` | max :math:`\mathbb{S}^{-}` | :math:`nextafter(x, y)` | :math:`nextafter(x, y)` | :math:`qNaN` | + * +--------------------------+--------------------------+ + + + + + + * | :math:`<0` | :math:`nextafter(x, y)` | | | | | | + * +--------------------------+ + +--------------------------+--------------------------+ + + + + * | :math:`-0` | | | :math:`y` | | | | + * +--------------------------+ + + + + + + + * | :math:`+0` | | | | | | | + * +--------------------------+ + +--------------------------+--------------------------+ + + + + * | :math:`>0` | | | min :math:`\mathbb{S}^{+}` | | | | + * +--------------------------+ + + + +--------------------------+ + + * | :math:`+Inf` | | | | | :math:`+Inf` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double nextafter(double x, double y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, hy, ix; + uint32_t lx, ly; + + EXTRACT_WORDS(hx, lx, x); + EXTRACT_WORDS(hy, ly, y); + ix = hx & 0x7fffffff; /* |x| */ + + if (isnan(x) || isnan(y)) { /* x or y is nan */ + return x + y; + } else if (hx == hy && lx == ly) { + return y; /* x == y, return y */ + } else if ((ix | lx) == 0) { /* x == 0 */ + if (ix == (hy & 0x7fffffff) && ly == 0U) { + return y; /* x == y, return y */ + } +#ifdef __LIBMCS_FPU_DAZ + INSERT_WORDS(x, (hy & 0x80000000U) | 0x00100000U, 0U); /* return +-minnormal */ +#else + INSERT_WORDS(x, hy & 0x80000000U, 1U); /* return +-minsubnormal */ + (void) __raise_underflow(x); +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return x; + } else if (hx >= 0) { /* x > 0 */ + if (hx > hy || ((hx == hy) && (lx > ly))) { /* x > y, x -= ulp */ + if (lx == 0) { + hx -= 1; + } + + lx -= 1; + } else { /* x < y, x += ulp */ + lx += 1; + + if (lx == 0) { + hx += 1; + } + } + } else { /* x < 0 */ + if (hy >= 0 || hx > hy || ((hx == hy) && (lx > ly))) { /* x < y, x -= ulp */ + if (lx == 0) { + hx -= 1; + } + + lx -= 1; + } else { /* x > y, x += ulp */ + lx += 1; + + if (lx == 0) { + hx += 1; + } + } + } + + hy = hx & 0x7ff00000; + + if (hy >= 0x7ff00000) { + return __raise_overflow(x); /* overflow if x is finite */ + } + + if (hy < 0x00100000) { /* underflow */ +#ifdef __LIBMCS_FPU_DAZ + INSERT_WORDS(x, hx & 0x80000000U, 0U); /* return +-0.0 */ + return x; +#else + (void) __raise_underflow(x); +#endif /* defined(__LIBMCS_FPU_DAZ) */ + } + + INSERT_WORDS(x, hx, lx); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double nextafterl(long double x, long double y) +{ + return (long double) nextafter((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/nexttowardd.c b/libm/libmcs/libm/mathd/nexttowardd.c new file mode 100644 index 00000000..d6913aa3 --- /dev/null +++ b/libm/libmcs/libm/mathd/nexttowardd.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +/** + * + * This family of functions computes the next floating-point value after + * :math:`x` in direction of :math:`y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float nexttowardf(float x, long double y); + * double nexttoward(double x, long double y); + * long double nexttowardl(long double x, long double y); + * + * Description + * =========== + * + * ``nexttoward`` computes the next floating-point value after :math:`x` in + * direction of :math:`y`. + * + * ``nexttoward`` is functionally equivalent to :ref:`nextafter` but uses + * ``long double`` for the :math:`y` input. As the library only supports 64bit + * ``long double`` the procedure ``nexttoward`` is just calling + * :ref:`nextafter` as the types are the same, but for ``nexttowardf`` there is + * an actual difference as :math:`y` can be chosen to be so close to :math:`x` + * that it would be the same value in ``float`` but isn't in (effectively) + * ``double``. This results in ``nexttowardf`` having it's own implementation + * while ``nexttoward`` does not. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * nexttoward(x, y) = \left\{\begin{array}{ll} y, & x = y \\ \text{min} \{z | z \in \mathbb{F} \wedge z > x\}, & x < y \\ \text{max} \{z | z \in \mathbb{F} \wedge z < x\}, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``nexttoward`` returns the the next floating-point value after :math:`x` in + * direction of :math:`y`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the magnitude of :math:`x` is the largest + * finite value representable in the type and :math:`y` is infinite with the + * same sign as :math:`x`. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | nexttoward(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`-Inf` | :math:`nexttoward(x, y)` | max :math:`\mathbb{S}^{-}` | :math:`nexttoward(x, y)` | :math:`nexttoward(x, y)` | :math:`qNaN` | + * +--------------------------+--------------------------+ + + + + + + * | :math:`<0` | :math:`nexttoward(x, y)` | | | | | | + * +--------------------------+ + +--------------------------+--------------------------+ + + + + * | :math:`-0` | | | :math:`y` | | | | + * +--------------------------+ + + + + + + + * | :math:`+0` | | | | | | | + * +--------------------------+ + +--------------------------+--------------------------+ + + + + * | :math:`>0` | | | min :math:`\mathbb{S}^{+}` | | | | + * +--------------------------+ + + + +--------------------------+ + + * | :math:`+Inf` | | | | | :math:`+Inf` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +#include + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +double nexttoward(double x, long double y) +{ + return nextafter(x, (double) y); +} + +long double nexttowardl(long double x, long double y) +{ + return (long double) nexttoward((double) x, y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/powd.c b/libm/libmcs/libm/mathd/powd.c new file mode 100644 index 00000000..a0dc7312 --- /dev/null +++ b/libm/libmcs/libm/mathd/powd.c @@ -0,0 +1,443 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the value of :math:`x` raised to the + * power of :math:`y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float powf(float x, float y); + * double pow(double x, double y); + * long double powl(long double x, long double y); + * + * Description + * =========== + * + * ``pow`` computes the value of :math:`x` raised to the power of :math:`y`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * pow(x, y) \approx x^y + * + * Returns + * ======= + * + * ``pow`` returns the value of :math:`x` raised to the power of :math:`y`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when :math:`x` is finite and negative + * and :math:`y` is finite and not an integer value. + * + * Raise ``divide by zero`` exception when :math:`x` is zero and :math:`y` is a + * negative odd integer value. + * + * Raise ``overflow`` exception when the magnitude of the result is too large. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | pow(x,y) | x | + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`< -1` | :math:`-1` | :math:`]-1,-0[` | :math:`-0` | :math:`+0` | :math:`]+0,+1[` | :math:`+1` | :math:`> +1` | :math:`+Inf` | :math:`qNaN` | :math:`sNaN` | + * +============================================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`+0` | :math:`+1` | :math:`+Inf` | :math:`+1` | :math:`+0` | :math:`qNaN` | :math:`qNaN` | + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ +--------------------------+--------------------------+ + + + * | :math:`\{2k + 1 : k \in \mathbb{Z}_{<0}\}` | :math:`-0` | :math:`x^y` | :math:`-Inf` | :math:`+Inf` | :math:`x^y` | | :math:`x^y` | :math:`+0` | | | + * +--------------------------------------------+--------------------------+ +--------------------------+--------------------------+ + + + + + + + * | :math:`\{2k : k \in \mathbb{Z}_{<0}\}` | :math:`+0` | | :math:`+Inf` | | | | | | | + * +--------------------------------------------+ +--------------------------+--------------------------+--------------------------+ + + + + + + + + * | :math:`< 0\ \wedge \notin \mathbb{Z}` | | :math:`qNaN` | | | | | | | | + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`-0` | :math:`+1` | | + * +--------------------------------------------+ + + + * | :math:`+0` | | | + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`> 0\ \wedge \notin \mathbb{Z}` | :math:`+Inf` | :math:`qNaN` | :math:`+0` | :math:`x^y` | :math:`+1` | :math:`x^y` | :math:`+Inf` | :math:`qNaN` | | + * +--------------------------------------------+ +--------------------------+--------------------------+--------------------------+ + + + + + + + + * | :math:`\{2k : k \in \mathbb{Z}_{>0}\}` | | :math:`x^y` | | | | | | | | + * +--------------------------------------------+--------------------------+ +--------------------------+--------------------------+ + + + + + + + * | :math:`\{2k - 1 : k \in \mathbb{Z}_{>0}\}` | :math:`-Inf` | | :math:`-0` | :math:`+0` | | | | | | | + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ +--------------------------+--------------------------+ + + + * | :math:`+Inf` | :math:`+Inf` | :math:`+1` | :math:`+0` | | :math:`+Inf` | | | + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ +--------------------------+--------------------------+--------------------------+ + + * | :math:`qNaN` | :math:`qNaN` | | :math:`qNaN` | | + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | :math:`sNaN` | :math:`qNaN` | + * +--------------------------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +bp[] = {1.0, 1.5}, +dp_h[] = { 0.0, 5.84962487220764160156e-01}, /* 0x3FE2B803, 0x40000000 */ +dp_l[] = { 0.0, 1.35003920212974897128e-08}, /* 0x3E4CFDEB, 0x43CFD006 */ +zero = 0.0, +one = 1.0, +two = 2.0, +two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ +/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ +L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ +L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ +L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ +L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ +L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ +lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ +lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ +ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ +cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ +cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ +cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ +ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ +ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ +ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + +double pow(double x, double y) +{ + double z, ax, z_h, z_l, p_h, p_l; + double _y1, t1, t2, r, s, sign, t, u, v, w; + int32_t i, j, k, yisint, n; + int32_t hx, hy, ix, iy; + uint32_t lx, ly; + + EXTRACT_WORDS(hx, lx, x); + EXTRACT_WORDS(hy, ly, y); + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + + /* y==zero: x**0 = 1 unless x is snan */ +#ifdef __LIBMCS_FPU_DAZ + if (iy < 0x00100000) { +#else + if ((iy | ly) == 0) { +#endif /* defined(__LIBMCS_FPU_DAZ) */ + if (__issignaling(x) != 0) { + return x + y; + } + + return one; + } + + /* x|y==NaN return NaN unless x==1 then return 1 */ /* For performance: don't use isnan */ + if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) || + iy > 0x7ff00000 || ((iy == 0x7ff00000) && (ly != 0))) { + if (((hx - 0x3ff00000) | lx) == 0 && __issignaling(y) == 0) { + return one; + } else { + return x + y; + } + } + +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; + + EXTRACT_WORDS(hx, lx, x); + EXTRACT_WORDS(hy, ly, y); + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + + if (hx < 0) { + if (iy >= 0x43400000) { + yisint = 2; /* even integer y */ + } else if (iy >= 0x3ff00000) { + k = (iy >> 20) - 0x3ff; /* exponent */ + + if (k > 20) { + j = ly >> (52 - k); + + if (((uint32_t)j << (52 - k)) == ly) { + yisint = 2 - (j & 1); + } + } else if (ly == 0) { + j = iy >> (20 - k); + + if ((j << (20 - k)) == iy) { + yisint = 2 - (j & 1); + } + } else { + /* No action required */ + } + } else { + /* No action required */ + } + } + + /* special value of y */ + if (ly == 0) { + if (iy == 0x7ff00000) { /* y is +-inf */ + if (((ix - 0x3ff00000) | lx) == 0) { + return one; /* +-1**+-inf = 1 */ + } else if (ix >= 0x3ff00000) { /* (|x|>1)**+-inf = inf,0 */ + return (hy >= 0) ? y : zero; + } else { /* (|x|<1)**-,+inf = inf,0 */ + return (hy < 0) ? -y : zero; + } + } + + if (iy == 0x3ff00000) { /* y is +-1 */ + if (hy < 0) { + return one / x; + } else { + return x; + } + } + + if (hy == 0x40000000) { + return x * x; /* y is 2 */ + } + + if (hy == 0x3fe00000) { /* y is 0.5 */ + if (hx >= 0) { /* x >= +0 */ + return sqrt(x); + } + } + } + + ax = fabs(x); + + /* special value of x */ + if (lx == 0) { + if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { + z = ax; /*x is +-0,+-inf,+-1*/ + + if (hy < 0) { /* z = (1/|x|) */ + if (ix == 0x7ff00000) { + z = zero; + } else if (ix == 0) { + z = __raise_div_by_zero(z); + } else { + /* No action required */ + } + } + + if (hx < 0) { + if (((ix - 0x3ff00000) | yisint) == 0) { + z = __raise_invalid(); /* (-1)**non-int is NaN */ + } else if (yisint == 1) { + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } else { + /* No action required */ + } + } + + return z; + } + } + + n = ((uint32_t)hx >> 31U) - 1U; + + /* (x<0)**(non-int) is NaN */ + if ((n | yisint) == 0) { + return __raise_invalid(); + } + + sign = one; /* (sign of result -ve**odd) = -1 else = 1 */ + if ((n | (yisint - 1)) == 0) { + sign = -one; /* (-ve)**(odd int) */ + } + + /* |y| is huge */ + if (iy > 0x42000000) { /* if |y| > ~2**33 (does not regard mantissa) */ + if (iy > 0x43f00000) { /* if |y| > ~2**64, must o/uflow and y is an even integer */ + if (ix <= 0x3fefffff) { /* |x| < 1 */ + return (hy < 0) ? __raise_overflow(one) : __raise_underflow(one); + } else { /* |x| > 1 */ + return (hy > 0) ? __raise_overflow(one) : __raise_underflow(one); + } + } + + /* over/underflow if x is not close to one */ + if (ix < 0x3fefffff) { + return (hy < 0) ? __raise_overflow(sign) : __raise_underflow(sign); + } + + if (ix > 0x3ff00000) { + return (hy > 0) ? __raise_overflow(sign) : __raise_underflow(sign); + } + + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = ax - 1; /* t has 20 trailing zeros */ + w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25)); + u = ivln2_h * t; /* ivln2_h has 21 sig. bits */ + v = t * ivln2_l - w * ivln2; + t1 = u + v; + SET_LOW_WORD(t1, 0); + t2 = v - (t1 - u); + } else { + double s2, s_h, s_l, t_h, t_l; + n = 0; + + /* take care subnormal number */ + if (ix < 0x00100000) { + ax *= two53; + n -= 53; + GET_HIGH_WORD(ix, ax); + } + + n += ((ix) >> 20) - 0x3ff; + j = ix & 0x000fffff; + /* determine interval */ + ix = j | 0x3ff00000; /* normalize ix */ + + if (j <= 0x3988E) { + k = 0; /* |x|> 1) | 0x20000000) + 0x00080000 + (k << 18)); + t_l = ax - (t_h - bp[k]); + s_l = v * ((u - s_h * t_h) - s_h * t_l); + /* compute log(ax) */ + s2 = s * s; + r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); + r += s_l * (s_h + s); + s2 = s_h * s_h; + t_h = 3.0 + s2 + r; + SET_LOW_WORD(t_h, 0); + t_l = r - ((t_h - 3.0) - s2); + /* u+v = s*(1+...) */ + u = s_h * t_h; + v = s_l * t_h + t_l * s; + /* 2/(3log2)*(s+...) */ + p_h = u + v; + SET_LOW_WORD(p_h, 0); + p_l = v - (p_h - u); + z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l * p_h + p_l * cp + dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double)n; + t1 = (((z_h + z_l) + dp_h[k]) + t); + SET_LOW_WORD(t1, 0); + t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); + } + + /* split up y into _y1+y2 and compute (_y1+y2)*(t1+t2) */ + _y1 = y; + SET_LOW_WORD(_y1, 0); + p_l = (y - _y1) * t1 + y * t2; + p_h = _y1 * t1; + z = p_l + p_h; + EXTRACT_WORDS(j, i, z); + + if (j >= 0x40900000) { /* z >= 1024 */ + if (((j - 0x40900000) | i) != 0) { /* if z > 1024 */ + return __raise_overflow(sign); + } else { + if (p_l + ovt > z - p_h) { + return __raise_overflow(sign); + } + } + } else if ((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ + if (((j - 0xc090cc00U) | i) != 0) { /* z < -1075 */ + return __raise_underflow(sign); + } else { + if (p_l <= z - p_h) { + return __raise_underflow(sign); + } + } + } else { + /* No action required */ + } + + /* + * compute 2**(p_h+p_l) + */ + i = j & 0x7fffffff; + k = (i >> 20) - 0x3ff; + n = 0; + + if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j + (0x00100000 >> (k + 1)); + k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ + t = zero; + SET_HIGH_WORD(t, n & ~(0x000fffff >> k)); + n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); + + if (j < 0) { + n = -n; + } + + p_h -= t; + } + + t = p_l + p_h; + SET_LOW_WORD(t, 0); + u = t * lg2_h; + v = (p_l - (t - p_h)) * lg2 + t * lg2_l; + z = u + v; + w = v - (z - u); + t = z * z; + t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + r = (z * t1) / (t1 - two) - (w + z * w); + z = one - (r - z); + GET_HIGH_WORD(j, z); + j += (n << 20); + + if ((j >> 20) <= 0) { + z = scalbn(z, (int32_t)n); /* subnormal output */ + } else { + SET_HIGH_WORD(z, j); + } + + return sign * z; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double powl(long double x, long double y) +{ + return (long double) pow((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/remainderd.c b/libm/libmcs/libm/mathd/remainderd.c new file mode 100644 index 00000000..cb96fa04 --- /dev/null +++ b/libm/libmcs/libm/mathd/remainderd.c @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the floating-point remainder :math:`x\ REM\ y`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float remainderf(float x, float y); + * double remainder(double x, double y); + * long double remainderl(long double x, long double y); + * + * Description + * =========== + * + * ``remainder`` computes the floating-point remainder :math:`r = x\ REM\ y = x + * - n \cdot y` of their arguments :math:`x` and :math:`y`, where :math:`n` is + * the integral value nearest to :math:`\frac{x}{y}`. + * + * The ``fmod`` and ``remainder`` procedures are rather similar, but not the + * same, see examples: + * + * +----------------+----------------+----------------+----------------+ + * | x | y | fmod | remainder | + * +================+================+================+================+ + * | :math:`+2.456` | :math:`+2.0` | :math:`+0.456` | :math:`+0.456` | + * +----------------+----------------+----------------+----------------+ + * | :math:`+3.456` | :math:`+2.0` | :math:`+1.456` | :math:`-0.544` | + * +----------------+----------------+----------------+----------------+ + * | :math:`-2.456` | :math:`+2.0` | :math:`-0.456` | :math:`-0.456` | + * +----------------+----------------+----------------+----------------+ + * | :math:`-3.456` | :math:`+2.0` | :math:`-1.456` | :math:`+0.544` | + * +----------------+----------------+----------------+----------------+ + * | :math:`+2.456` | :math:`-2.0` | :math:`+0.456` | :math:`+0.456` | + * +----------------+----------------+----------------+----------------+ + * | :math:`+3.456` | :math:`-2.0` | :math:`+1.456` | :math:`-0.544` | + * +----------------+----------------+----------------+----------------+ + * | :math:`-2.456` | :math:`-2.0` | :math:`-0.456` | :math:`-0.456` | + * +----------------+----------------+----------------+----------------+ + * | :math:`-3.456` | :math:`-2.0` | :math:`-1.456` | :math:`+0.544` | + * +----------------+----------------+----------------+----------------+ + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * remainder(x, y) = x - n \cdot y \wedge n \in \mathbb{Z} \wedge remainder(x, y) \in \left [-\left | \frac{y}{2} \right |,\left | \frac{y}{2} \right | \right ] + * + * Returns + * ======= + * + * ``remainder`` returns the floating-point remainder :math:`x\ REM\ y`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when :math:`x` is infinite or + * :math:`y` is zero. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | remainder(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`qNaN` | :math:`x` | :math:`qNaN` | :math:`qNaN` | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`<0` | | :math:`x\ REM\ y` | :math:`x` | :math:`x\ REM\ y` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`-0` | | :math:`qNaN` | | | + * +--------------------------+ + + + + + * | :math:`+0` | | | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`>0` | | :math:`x\ REM\ y` | :math:`x` | :math:`x\ REM\ y` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`+Inf` | | :math:`x` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double zero = 0.0; + +double remainder(double x, double y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, hy; + uint32_t sx, lx, ly; + double y_half; + + EXTRACT_WORDS(hx, lx, x); + EXTRACT_WORDS(hy, ly, y); + sx = hx & 0x80000000U; + hy &= 0x7fffffff; + hx &= 0x7fffffff; + + /* purge off exception values */ + if ((hx >= 0x7ff00000) || (hy >= 0x7ff00000)) { /* x or y not finite */ + if (isnan(x) || isnan(y)) { /* x or y is NaN */ + return x + y; + } else if (hx == 0x7ff00000) { /* x is infinite */ + return __raise_invalid(); + } else { + /* No action required */ + } + } else if ((hy | ly) == 0) { /* y = 0 */ + return __raise_invalid(); + } else { + /* No action required */ + } + + if (hy <= 0x7fdfffff) { + x = fmod(x, 2 * y); /* now x < 2y */ + } + + if (((hx - hy) | (lx - ly)) == 0) { /* x equals y */ + return zero * x; + } + + x = fabs(x); + y = fabs(y); + + if (hy < 0x00200000) { + if (x + x > y) { + x -= y; + + if (x + x >= y) { + x -= y; + } + } + } else { + y_half = 0.5 * y; + + if (x > y_half) { + x -= y; + + if (x >= y_half) { + x -= y; + } + } + } + + GET_HIGH_WORD(hx, x); + SET_HIGH_WORD(x, hx ^ sx); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double remainderl(long double x, long double y) +{ + return (long double) remainder((double) x, (double) y); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/remquod.c b/libm/libmcs/libm/mathd/remquod.c new file mode 100644 index 00000000..212089d1 --- /dev/null +++ b/libm/libmcs/libm/mathd/remquod.c @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the floating-point remainder :math:`x\ + * REM\ y` and puts the quotient (or rather its sign and 3 least significant + * bits) into the out pointer. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float remquof(float x, float y, int *quo); + * double remquo(double x, double y, int *quo); + * long double remquol(long double x, long double y, int *quo); + * + * Description + * =========== + * + * ``remquo`` computes the floating-point remainder :math:`r = x\ REM\ y = x - + * n \cdot y` of their arguments :math:`x` and :math:`y`, where :math:`n` is + * the integral value nearest to :math:`\frac{x}{y}`. + * + * The 3 least significant bits of :math:`n` and its sign are then put into the + * output pointer :math:`*quo`. + * + * ``remquo`` and ``remainder`` are functionally equivalent concerning the + * return value, ``remquo`` only adds an additional output. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * remquo(x, y) = x - n \cdot y \wedge n \in \mathbb{Z} \wedge remquo(x, y) \in \left [-\left | \frac{y}{2} \right |,\left | \frac{y}{2} \right | \right ] \wedge quo = n + * + * Returns + * ======= + * + * ``remquo`` returns the floating-point remainder :math:`x\ REM\ y`. The sign + * and 3 least significant bits of quotient :math:`n` is put into :math:`*quo`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when :math:`x` is infinite or + * :math:`y` is zero. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | remquo(x,y) | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`qNaN` | :math:`x` | :math:`qNaN` | :math:`qNaN` | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`<0` | | :math:`x\ REM\ y` | :math:`x` | :math:`x\ REM\ y` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`-0` | | :math:`qNaN` | | | + * +--------------------------+ + + + + + * | :math:`+0` | | | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`>0` | | :math:`x\ REM\ y` | :math:`x` | :math:`x\ REM\ y` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`+Inf` | | :math:`x` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`qNaN` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | :math:`*quo` | x | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * | y | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +==========================+==========================+==========================+==========================+==========================+==========================+==========================+==========================+ + * | :math:`-Inf` | :math:`0` | :math:`0` | :math:`0` | :math:`0` | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`<0` | | :math:`n` | :math:`0` | :math:`n` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`-0` | | :math:`0` | | | + * +--------------------------+ + + + + + * | :math:`+0` | | | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`>0` | | :math:`n` | :math:`0` | :math:`n` | | | + * +--------------------------+ +--------------------------+--------------------------+--------------------------+--------------------------+ + + + * | :math:`+Inf` | | :math:`0` | | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + + * | :math:`NaN` | :math:`0` | | + * +--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+--------------------------+ + * + */ + +#include +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double zero = 0.0; + +double remquo(double x, double y, int *quo) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; + y *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int _quo = 0; + int32_t hx, hy; + uint32_t sx, sq, lx, ly; + double y_half; + + assert(quo != (void*)0); + if(quo == (void*)0) { + quo = &_quo; + } + *quo = 0; + + EXTRACT_WORDS(hx, lx, x); + EXTRACT_WORDS(hy, ly, y); + sx = hx & 0x80000000U; + sq = sx ^ (hy & 0x80000000U); + hy &= 0x7fffffff; + hx &= 0x7fffffff; + + /* purge off exception values */ + if ((hx >= 0x7ff00000) || (hy >= 0x7ff00000)) { /* x or y not finite */ + if (isnan(x) || isnan(y)) { /* x or y is NaN */ + return x + y; + } else if (hx == 0x7ff00000) { /* x is infinite */ + return __raise_invalid(); + } else { + /* No action required */ + } + } else if ((hy | ly) == 0) { /* y = 0 */ + return __raise_invalid(); + } else { + /* No action required */ + } + + if (hy <= 0x7fbfffff) { + x = fmod(x, 8 * y); /* now x < 8y */ + } + + if (((hx - hy) | (lx - ly)) == 0) { /* x equals y */ + *quo = sq ? -1 : 1; + return zero * x; + } + + x = fabs(x); + y = fabs(y); + _quo = 0; + + if (x >= 4 * y) { + x -= 4 * y; + _quo += 4; + } + if (x >= 2 * y) { + x -= 2 * y; + _quo += 2; + } + + if (hy < 0x00200000) { + if (x + x > y) { + x -= y; + _quo++; + + if (x + x >= y) { + x -= y; + _quo++; + } + } + } else { + y_half = 0.5 * y; + + if (x > y_half) { + x -= y; + _quo++; + + if (x >= y_half) { + x -= y; + _quo++; + } + } + } + + _quo &= 0x7; + + *quo = sq ? -_quo : _quo; + + GET_HIGH_WORD(hx, x); + SET_HIGH_WORD(x, hx ^ sx); + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double remquol(long double x, long double y, int *quo) +{ + return (long double) remquo((double) x, (double) y, quo); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/rintd.c b/libm/libmcs/libm/mathd/rintd.c new file mode 100644 index 00000000..39bdef05 --- /dev/null +++ b/libm/libmcs/libm/mathd/rintd.c @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the nearest integer value to :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float rintf(float x); + * double rint(double x); + * long double rintl(long double x); + * + * Description + * =========== + * + * ``rint`` computes the nearest integer value to :math:`x`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * rint(x) = \lfloor x \rceil + * + * Returns + * ======= + * + * ``rint`` returns the nearest integer value to :math:`x`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------------------+--------------+--------------+--------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==========================+==============+==============+==========================+==============+==============+ + * | **rint(x)** | :math:`-Inf` | :math:`\lfloor x \rceil` | :math:`x` | :math:`\lfloor x \rceil` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+--------------------------+--------------+--------------+--------------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double TWO52[2] = { + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +double rint(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t _i0, _j0, sx; + uint32_t i, _i1; + double t; + volatile double w; + EXTRACT_WORDS(_i0, _i1, x); + sx = (_i0 >> 31) & 1; /* sign */ + _j0 = ((_i0 >> 20) & 0x7ff) - 0x3ff; /* exponent */ + + if (_j0 < 20) { /* no integral bits in LS part */ + if (_j0 < 0) { /* x is fractional or 0 */ + if (((_i0 & 0x7fffffff) | _i1) == 0) { + return x; /* x == 0 */ + } + + _i1 |= (_i0 & 0x0fffff); + _i0 &= 0xfffe0000U; + _i0 |= ((_i1 | -_i1) >> 12) & 0x80000; + SET_HIGH_WORD(x, _i0); + w = TWO52[sx] + x; + t = w - TWO52[sx]; + GET_HIGH_WORD(_i0, t); + SET_HIGH_WORD(t, (_i0 & 0x7fffffff) | (sx << 31)); + return t; + } else { /* x has integer and maybe fraction */ + i = (0x000fffff) >> _j0; + + if (((_i0 & i) | _i1) == 0) { + return x; /* x is integral */ + } + + i >>= 1; + + if (((_i0 & i) | _i1) != 0) { + /* 2nd or any later bit after radix is set */ + if (_j0 == 19) { + _i1 = 0x80000000U; + } else { + _i1 = 0; + } + + _i0 = (_i0 & (~i)) | ((0x40000) >> _j0); + } + } + } else if (_j0 > 51) { + if (_j0 == 0x400) { + return x + x; /* inf or NaN */ + } else { + return x; /* x is integral */ + } + } else { + i = ((uint32_t)0xffffffffU) >> (_j0 - 20); + + if ((_i1 & i) == 0) { + return x; /* x is integral */ + } + + i >>= 1; + + if ((_i1 & i) != 0) { + _i1 = (_i1 & (~i)) | ((0x40000000) >> (_j0 - 20)); + } + } + + INSERT_WORDS(x, _i0, _i1); + w = TWO52[sx] + x; + return w - TWO52[sx]; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double rintl(long double x) +{ + return (long double) rint((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/roundd.c b/libm/libmcs/libm/mathd/roundd.c new file mode 100644 index 00000000..4b41221c --- /dev/null +++ b/libm/libmcs/libm/mathd/roundd.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the nearest integer value to :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float roundf(float x); + * double round(double x); + * long double roundl(long double x); + * + * Description + * =========== + * + * ``round`` computes the nearest integer value to :math:`x`. Half-way cases + * are rounded away from zero (which is the only difference to + * :ref:`nearbyint`, :ref:`rint`). + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * round(x) = \lfloor x \rceil + * + * Returns + * ======= + * + * ``round`` returns the nearest integer value to :math:`x`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+--------------------------+--------------+--------------+--------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==========================+==============+==============+==========================+==============+==============+ + * | **round(x)** | :math:`-Inf` | :math:`\lfloor x \rceil` | :math:`x` | :math:`\lfloor x \rceil` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+--------------------------+--------------+--------------+--------------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double round(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + /* Most significant word, least significant word. */ + int32_t msw, exponent_less_1023; + uint32_t lsw; + + EXTRACT_WORDS(msw, lsw, x); + + /* Extract exponent field. */ + exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023; + + if (exponent_less_1023 < 20) { + if (exponent_less_1023 < 0) { + msw &= 0x80000000U; + + if (exponent_less_1023 == -1) { /* Result is +1.0 or -1.0. */ + msw |= ((int32_t)1023 << 20); + } + + lsw = 0; + } else { + uint32_t exponent_mask = 0x000fffff >> exponent_less_1023; + + if ((msw & exponent_mask) == 0 && lsw == 0) { /* x in an integral value. */ + return x; + } + + msw += 0x00080000 >> exponent_less_1023; + msw &= ~exponent_mask; + lsw = 0; + } + } else if (exponent_less_1023 > 51) { + if (exponent_less_1023 == 1024) { /* x is NaN or infinite. */ + return x + x; + } else { + return x; + } + } else { + uint32_t exponent_mask = 0xffffffffU >> (exponent_less_1023 - 20); + uint32_t tmp; + + if ((lsw & exponent_mask) == 0) { /* x is an integral value. */ + return x; + } + + tmp = lsw + (1 << (51 - exponent_less_1023)); + + if (tmp < lsw) { + msw += 1; + } + + lsw = tmp; + + lsw &= ~exponent_mask; + } + + INSERT_WORDS(x, msw, lsw); + + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double roundl(long double x) +{ + return (long double) round((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/scalblnd.c b/libm/libmcs/libm/mathd/scalblnd.c new file mode 100644 index 00000000..9517c999 --- /dev/null +++ b/libm/libmcs/libm/mathd/scalblnd.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions multiplies the input value :math:`x` by an integral + * power of :math:`2`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float scalblnf(float x, int n); + * double scalbln(double x, int n); + * long double scalblnl(long double x, int n); + * + * Description + * =========== + * + * ``scalbln`` multiplies the input value :math:`x` by an integral power of + * :math:`2`. + * + * ``scalbln`` and :ref:`scalbn` have the same functionality. The difference is + * that :ref:`scalbn` uses an ``int`` for :math:`n`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * scalbln(x, n) \approx x \cdot 2^{n} + * + * Returns + * ======= + * + * ``scalbln`` returns the input value :math:`x` multiplied by :math:`2` + * powered by the input value :math:`n`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception if the result overflows. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | scalbln(x,n) | n | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | x | :math:`<0` | :math:`0` | :math:`>0` | + * +=====================+=========================+=========================+=========================+ + * | :math:`-Inf` | :math:`x` | :math:`x` | :math:`x` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`<0` | :math:`x \cdot 2^{n}` | | :math:`x \cdot 2^{n}` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`-0` | :math:`x` | | :math:`x` | + * +---------------------+ + + + + * | :math:`+0` | | | | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`>0` | :math:`x \cdot 2^{n}` | | :math:`x \cdot 2^{n}` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`+Inf` | :math:`x` | | :math:`x` | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | :math:`NaN` | :math:`qNaN` | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17; /* 0x3C900000, 0x00000000 */ + +double scalbln(double x, long int n) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t k, hx, lx; + EXTRACT_WORDS(hx, lx, x); + k = (hx & 0x7ff00000) >> 20; /* extract exponent */ + + if (k == 0) { /* 0 or subnormal x */ + if ((lx | (hx & 0x7fffffff)) == 0) { + return x; /* +-0 */ + } + + x *= two54; + GET_HIGH_WORD(hx, x); + k = ((hx & 0x7ff00000) >> 20) - 54; + } + + if (k == 0x7ff) { + return x + x; /* NaN or Inf */ + } + + if (n > 50000) { + return __raise_overflow(x); /*overflow*/ + } + + k = k + n; + + if (k > 0x7fe) { + return __raise_overflow(x); /*overflow*/ + } + + if (n < -50000) { + return __raise_underflow(x); /*underflow*/ + } + + if (k > 0) { /* normal result */ + SET_HIGH_WORD(x, (hx & 0x800fffffU) | (k << 20U)); + return x; + } + + if (k <= -54) { + return __raise_underflow(x); /*underflow*/ + } + + k += 54; /* subnormal result */ + SET_HIGH_WORD(x, (hx & 0x800fffffU) | (k << 20U)); + return x * twom54; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double scalblnl(long double x, long int n) +{ + return (long double) scalbln((double) x, n); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/scalbnd.c b/libm/libmcs/libm/mathd/scalbnd.c new file mode 100644 index 00000000..8415567d --- /dev/null +++ b/libm/libmcs/libm/mathd/scalbnd.c @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions multiplies the input value :math:`x` by an integral + * power of :math:`2`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float scalbnf(float x, int n); + * double scalbn(double x, int n); + * long double scalbnl(long double x, int n); + * + * Description + * =========== + * + * ``scalbn`` multiplies the input value :math:`x` by an integral power of + * :math:`2`. + * + * ``scalbn`` and :ref:`ldexp` have the same functionality. In theory their + * definition could be different, but this only applies to architectures which + * do not use a binary system, which by now are assumed to be an obscurity. + * + * ``scalbn`` and :ref:`scalbln` have the same functionality. The difference is + * that :ref:`scalbln` uses a ``long int`` for :math:`n`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * scalbn(x, n) \approx x \cdot 2^{n} + * + * Returns + * ======= + * + * ``scalbn`` returns the input value :math:`x` multiplied by :math:`2` powered + * by the input value :math:`n`. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception if the result overflows. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | scalbn(x,n) | n | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | x | :math:`<0` | :math:`0` | :math:`>0` | + * +=====================+=========================+=========================+=========================+ + * | :math:`-Inf` | :math:`x` | :math:`x` | :math:`x` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`<0` | :math:`x \cdot 2^{n}` | | :math:`x \cdot 2^{n}` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`-0` | :math:`x` | | :math:`x` | + * +---------------------+ + + + + * | :math:`+0` | | | | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`>0` | :math:`x \cdot 2^{n}` | | :math:`x \cdot 2^{n}` | + * +---------------------+-------------------------+ +-------------------------+ + * | :math:`+Inf` | :math:`x` | | :math:`x` | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * | :math:`NaN` | :math:`qNaN` | + * +---------------------+-------------------------+-------------------------+-------------------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17; /* 0x3C900000, 0x00000000 */ + +double scalbn(double x, int n) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t k, hx, lx; + EXTRACT_WORDS(hx, lx, x); + k = (hx & 0x7ff00000) >> 20; /* extract exponent */ + + if (k == 0) { /* 0 or subnormal x */ + if ((lx | (hx & 0x7fffffff)) == 0) { + return x; /* +-0 */ + } + + x *= two54; + GET_HIGH_WORD(hx, x); + k = ((hx & 0x7ff00000) >> 20) - 54; + + if (n < -50000) { + return __raise_underflow(x); /*underflow*/ + } + } + + if (k == 0x7ff) { + return x + x; /* NaN or Inf */ + } + + if (n > 50000) { + return __raise_overflow(x); /*overflow */ + } + + k = k + n; + + if (k > 0x7fe) { + return __raise_overflow(x); /*overflow */ + } + + if (k > 0) { /* normal result */ + SET_HIGH_WORD(x, (hx & 0x800fffffU) | (k << 20U)); + return x; + } + + if (k <= -54) { + return __raise_underflow(x); /*underflow*/ + } + + k += 54; /* subnormal result */ + SET_HIGH_WORD(x, (hx & 0x800fffffU) | (k << 20U)); + return x * twom54; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double scalbnl(long double x, int n) +{ + return (long double) scalbn((double) x, n); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/sind.c b/libm/libmcs/libm/mathd/sind.c new file mode 100644 index 00000000..952f18ed --- /dev/null +++ b/libm/libmcs/libm/mathd/sind.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the sine of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float sinf(float x); + * double sin(double x); + * long double sinl(long double x); + * + * Description + * =========== + * + * ``sin`` computes the sine of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * sin(x) \approx sin(x) + * + * Returns + * ======= + * + * ``sin`` returns the sine of the input value, in the range :math:`[-1, 1]`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is infinite. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+================+================+================+================+================+================+================+ + * | **sin(x)** | :math:`qNaN` | :math:`sin(x)` | :math:`x` | :math:`sin(x)` | :math:`qNaN` | :math:`qNaN` | + * +---------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+ + * + */ + +#include +#include "../common/tools.h" +#include "internal/trigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double sin(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double y[2], z = 0.0; + int32_t n, ix; + + /* High word of x. */ + GET_HIGH_WORD(ix, x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + + if (ix <= 0x3fe921fb) { + if(ix < 0x3e500000) { /* |x| < 2**-26 */ + if (x == 0.0) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexact(x); + } + } + + return __sin(x, z, 0); + } + + /* sin(Inf or NaN) is NaN */ + else if (ix >= 0x7ff00000) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalid(); + } + } + + /* argument reduction needed */ + else { + n = __rem_pio2(x, y); + + switch (n & 3) { + case 0: + return __sin(y[0], y[1], 1); + + case 1: + return __cos(y[0], y[1]); + + case 2: + return -__sin(y[0], y[1], 1); + + default: + return -__cos(y[0], y[1]); + } + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double sinl(long double x) +{ + return (long double) sin((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/sinhd.c b/libm/libmcs/libm/mathd/sinhd.c new file mode 100644 index 00000000..ae4342d6 --- /dev/null +++ b/libm/libmcs/libm/mathd/sinhd.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the hyperbolic sine of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float sinhf(float x); + * double sinh(double x); + * long double sinhl(long double x); + * + * Description + * =========== + * + * ``sinh`` computes the hyperbolic sine of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * sinh(x) \approx sinh(x) = \frac{e^x-e^{-x}}{2} + * + * Returns + * ======= + * + * ``sinh`` returns the hyperbolic sine. + * + * Exceptions + * ========== + * + * Raise ``overflow`` exception when the magnitude of the input value is too + * large. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+-----------------+--------------+--------------+-----------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=================+==============+==============+=================+==============+==============+ + * | **sinh(x)** | :math:`-Inf` | :math:`sinh(x)` | :math:`x` | :math:`sinh(x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+-----------------+--------------+--------------+-----------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double one = 1.0; + +double sinh(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + 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 (x == 0.0) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexact(x); + } + } + + 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)0x8fb9f87dU)) { + w = exp(0.5 * fabs(x)); + t = h * w; + return t * w; + } + + /* |x| > overflowthresold, sinh(x) overflow */ + return __raise_overflow(x); +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double sinhl(long double x) +{ + return (long double) sinh((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/sqrtd.c b/libm/libmcs/libm/mathd/sqrtd.c new file mode 100644 index 00000000..843598bf --- /dev/null +++ b/libm/libmcs/libm/mathd/sqrtd.c @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the square root of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float sqrtf(float x); + * double sqrt(double x); + * long double sqrtl(long double x); + * + * Description + * =========== + * + * ``sqrt`` computes the square root of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * sqrt(x) \approx \sqrt{x} + * + * Returns + * ======= + * + * ``sqrt`` returns the square root of the input value. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when :math:`x` is negative. + * + * Output map + * ========== + * + * +---------------------+--------------+------------------+--------------+--------------+------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================+==============+==============+==================+==============+==============+ + * | **sqrt(x)** | :math:`qNaN` | :math:`qNaN` | :math:`x` | :math:`\sqrt{x}` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+------------------+--------------+--------------+------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double sqrt(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double z; + int32_t sign = 0x80000000U; + 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) { + if (isnan(x)) { /* sqrt(NaN)=NaN */ + return x + x; + } else if (ix0 > 0) { /* sqrt(+inf)=+inf */ + return x; + } else { /* sqrt(-inf)=sNaN */ + return __raise_invalid(); + } + } + + /* take care of zero and negative values */ + if (ix0 <= 0) { + if (((ix0 & (~sign)) | ix1) == 0) { + return x; /* sqrt(+-0) = +-0 */ + } else if (ix0 < 0) { + return __raise_invalid(); /* sqrt(-ve) = sNaN */ + } else { + /* No action required */ + } + } + + /* 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 (0 < (m & 1)) { /* odd m, double x to make it even */ + ix0 += ix0 + (int32_t)((ix1 & (uint32_t)sign) >> 31U); + ix1 += ix1; + } + + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + (int32_t)((ix1 & (uint32_t)sign) >> 31U); + 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 + (int32_t)((ix1 & (uint32_t)sign) >> 31U); + ix1 += ix1; + r >>= 1; + } + + r = sign; + + while (r != 0) { + t1 = s1 + r; + t = s0; + + if ((t < ix0) || ((t == ix0) && (t1 <= ix1))) { + s1 = t1 + r; + + if ((((int32_t)t1 & sign) == sign) && ((int32_t)s1 & sign) == 0) { + s0 += 1; + } + + ix0 -= t; + + if (ix1 < t1) { + ix0 -= 1; + } + + ix1 -= t1; + q1 += r; + } + + ix0 += ix0 + (int32_t)((ix1 & (uint32_t)sign) >> 31U); + ix1 += ix1; + r >>= 1; + } + + /* use floating add to find out rounding direction */ + if ((ix0 | ix1) != 0) { + (void) __raise_inexact(x); + if (q1 == (uint32_t)0xffffffffU) { + q1 = 0; + q += 1; + } else { + q1 += (q1 & 1); + } + } + + ix0 = (q >> 1) + 0x3fe00000; + ix1 = q1 >> 1; + + if ((q & 1) != 0) { + ix1 |= sign; + } + + ix0 += (m << 20); + INSERT_WORDS(z, ix0, ix1); + return z; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double sqrtl(long double x) +{ + return (long double) sqrt((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/tand.c b/libm/libmcs/libm/mathd/tand.c new file mode 100644 index 00000000..404360c0 --- /dev/null +++ b/libm/libmcs/libm/mathd/tand.c @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the tangent of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float tanf(float x); + * double tan(double x); + * long double tanl(long double x); + * float __tanf(float x, float y, int k); + * double __tan(double x, double y, int k); + * + * Description + * =========== + * + * ``tan`` computes the tangent of the input value. + * + * ``__tan`` is an internal function that computes the tangent of the input + * values. The sum of both input parameters :math:`x` and :math:`y` is bounded + * to [:math:`-\frac{\pi}{4}`, :math:`\frac{\pi}{4}`]. The first parameter + * :math:`x` is the requested value in raw precision while the second parameter + * :math:`y` contains a tail for higher precision. If the additional input + * variable :math:`k` is :math:`-1`, the function shall return the negative + * inverse tangent of :math:`x`, if :math:`k` is :math:`1` return the tangent. + * As ``__tan`` is an internal function, it should not be called by a user. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * tan(x) \approx tan(x) + * + * Returns + * ======= + * + * ``tan`` returns the tangent of the input value. + * + * ``__tan`` returns the tangent of the input value. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is infinite. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+================+================+================+================+================+================+================+ + * | **tan(x)** | :math:`qNaN` | :math:`tan(x)` | :math:`x` | :math:`tan(x)` | :math:`qNaN` | :math:`qNaN` | + * +---------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+ + * + */ + +#include +#include "../common/tools.h" +#include "internal/trigd.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ +pio4lo = 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */ +T[] = { + 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */ + 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */ + 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */ + 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */ + 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */ + 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */ + 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */ + 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */ + 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */ + 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */ + 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */ + -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */ + 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */ +}; + +static inline double __tan(double x, double y, int iy) +{ + double z, r, v, w, s; + int32_t ix, hx; + GET_HIGH_WORD(hx, x); + ix = hx & 0x7fffffff; /* high word of |x| */ + + if (ix >= 0x3FE59428) { /* |x|>=0.6744 */ + if (hx < 0) { + x = -x; + y = -y; + } + + z = pio4 - x; + w = pio4lo - y; + x = z + w; + y = 0.0; + } + + z = x * x; + w = z * z; + /* Break x^5*(T[1]+x^2*T[2]+...) into + * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) + */ + r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11])))); + v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12]))))); + s = z * x; + r = y + z * (s * (r + v) + y); + r += T[0] * s; + w = x + r; + + if (ix >= 0x3FE59428) { + v = (double)iy; + return (double)(1 - ((hx >> 30) & 2)) * (v - 2.0 * (x - (w * w / (w + v) - r))); + } + + if (iy == 1) { + return w; + } else { + /* if allow error up to 2 ulp, simply return -1.0/(x+r) here */ + /* compute -1.0/(x+r) accurately */ + double a, t; + z = w; + SET_LOW_WORD(z, 0); + v = r - (z - x); /* z+v = r+x */ + t = a = -1.0 / w; /* a = -1.0/w */ + SET_LOW_WORD(t, 0); + s = 1.0 + t * z; + return t + a * (s + t * v); + } +} + +double tan(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double y[2], z = 0.0; + int32_t n, ix; + + /* High word of x. */ + GET_HIGH_WORD(ix, x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + + if (ix <= 0x3fe921fb) { + if(ix < 0x3e400000) { /* x < 2**-27 */ + if (x == 0.0) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexact(x); + } + } + + return __tan(x, z, 1); + } + + /* tan(Inf or NaN) is NaN */ + else if (ix >= 0x7ff00000) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalid(); + } + } + + /* argument reduction needed */ + else { + n = __rem_pio2(x, y); + return __tan(y[0], y[1], 1 - ((n & 1) << 1)); /* 1 -- n even, -1 -- n odd */ + } +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double tanl(long double x) +{ + return (long double) tan((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/tanhd.c b/libm/libmcs/libm/mathd/tanhd.c new file mode 100644 index 00000000..df11ab4f --- /dev/null +++ b/libm/libmcs/libm/mathd/tanhd.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the hyperbolic tangent of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float tanhf(float x); + * double tanh(double x); + * long double tanhl(long double x); + * + * Description + * =========== + * + * ``tanh`` computes the hyperbolic tangent of the input value. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * tanh(x) \approx tanh(x) = \frac{e^x-e^{-x}}{e^x+e^{-x}} + * + * Returns + * ======= + * + * ``tanh`` returns the hyperbolic tangent, in the range :math:`[-1, 1]`. + * + * Exceptions + * ========== + * + * Does not raise overflow, division by zero, and invalid exceptions. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+-----------------+--------------+--------------+-----------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=================+==============+==============+=================+==============+==============+ + * | **tanh(x)** | :math:`-1` | :math:`tanh(x)` | :math:`x` | :math:`tanh(x)` | :math:`+1` | :math:`qNaN` | + * +---------------------+--------------+-----------------+--------------+--------------+-----------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double one = 1.0, two = 2.0; + +double tanh(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double t, z; + int32_t jx, ix; + + /* High word of |x|. */ + GET_HIGH_WORD(jx, x); + ix = jx & 0x7fffffff; + + /* x is INF or NaN */ + if (ix >= 0x7ff00000) { + if (isnan(x)) { /* tanh(NaN) = NaN */ + return x + x; + } else if (jx >= 0) { + return one; /* tanh(+inf)=+1 */ + } else { + return -one; /* tanh(-inf)=-1 */ + } + } + + /* |x| < 22 */ + if (ix < 0x40360000) { /* |x|<22 */ + if (ix < 0x3c800000) { /* |x|<2**-55 */ + if (x == 0.0) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexact(x); + } + } + + 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 = __raise_inexact(one); /* raised inexact flag */ + } + + return (jx >= 0) ? z : -z; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double tanhl(long double x) +{ + return (long double) tanh((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/tgammad.c b/libm/libmcs/libm/mathd/tgammad.c new file mode 100644 index 00000000..2ad0285b --- /dev/null +++ b/libm/libmcs/libm/mathd/tgammad.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the gamma function of :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float tgammaf(float x); + * double tgamma(double x); + * long double tgammal(long double x); + * + * Description + * =========== + * + * ``tgamma`` computes the gamma function of :math:`x`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * tgamma(x) \approx \Gamma(x) = \int_{0}^{\infty}e^{-t}t^{x-1}dt + * + * Returns + * ======= + * + * ``tgamma`` returns the gamma function of :math:`x`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is a negative + * integer or negative infinity. + * + * Raise ``divide by zero`` exception when the input value is zero. + * + * Raise ``overflow`` exception when the magnitude of the input value is too + * large or too small. + * + * Output map + * ========== + * + * +---------------------+--------------+---------------------------------------+-----------------------------+--------------+--------------+-------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0\ \wedge\ \notin \mathbb{Z}` | :math:`\in \mathbb{Z}_{<0}` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+=======================================+=============================+==============+==============+===================+==============+==============+ + * | **tgamma(x)** | :math:`qNaN` | :math:`\Gamma(x)` | :math:`qNaN` | :math:`-Inf` | :math:`+Inf` | :math:`\Gamma(x)` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+---------------------------------------+-----------------------------+--------------+--------------+-------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" +#include "internal/gammad.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double tgamma(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int signgam_local = 0; + double y = 0.0; + + if (isnan(x) != 0) { /* tgamma(NaN) = NaN */ + return x + x; + } else if (x == 0.0) { /* tgamma(+-0) = +-Inf */ + return __raise_div_by_zero(x); + } else if (floor(x) == x && x < 0.0) { /* tgamma(negative integer, -Inf) = NaN */ + return __raise_invalid(); + } else { + /* No action required */ + } + + y = exp(__lgamma(x, &signgam_local)); + + if (signgam_local < 0) { + y = -y; + } + + return y; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double tgammal(long double x) +{ + return (long double) tgamma((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/truncd.c b/libm/libmcs/libm/mathd/truncd.c new file mode 100644 index 00000000..726216d7 --- /dev/null +++ b/libm/libmcs/libm/mathd/truncd.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the nearest integer value towards zero + * from :math:`x`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * float truncf(float x); + * double trunc(double x); + * long double truncl(long double x); + * + * Description + * =========== + * + * ``trunc`` computes the nearest integer value towards zero from :math:`x`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * trunc(x) = \left\{\begin{array}{ll} \lfloor x \rfloor, & x \in \mathbb{F}^{+} \\ \lceil x \rceil, & otherwise \end{array}\right. + * + * Returns + * ======= + * + * ``trunc`` returns the nearest integer value towards zero from :math:`x`. + * + * Exceptions + * ========== + * + * Does not raise exceptions. + * + * Output map + * ========== + * + * +---------------------+--------------+---------------------------+--------------+--------------+---------------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+===========================+==============+==============+===========================+==============+==============+ + * | **trunc(x)** | :math:`-Inf` | :math:`\lceil x \rceil` | :math:`x` | :math:`\lfloor x \rfloor` | :math:`+Inf` | :math:`qNaN` | + * +---------------------+--------------+---------------------------+--------------+--------------+---------------------------+--------------+--------------+ + * + */ + +#include +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double trunc(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + uint32_t sb; + /* Most significant word, least significant word. */ + uint32_t msw; + uint32_t lsw; + int32_t exponent_less_1023; + + EXTRACT_WORDS(msw, lsw, x); + + /* Extract sign bit. */ + sb = msw & 0x80000000U; + + /* Extract exponent field. */ + exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023; + + if (exponent_less_1023 < 20) { + /* All significant digits are in msw. */ + if (exponent_less_1023 < 0) { + /* -1 < x < 1, so result is +0 or -0. */ + INSERT_WORDS(x, sb, 0); + } else { + /* All relevant fraction bits are in msw, so lsw of the result is 0. */ + INSERT_WORDS(x, sb | (msw & ~(0x000fffff >> exponent_less_1023)), 0); + } + } else if (exponent_less_1023 > 51) { + if (exponent_less_1023 == 1024) { + /* x is infinite, or not a number, so trigger an exception. */ + return x + x; + } + + /* All bits in the fraction fields of the msw and lsw are needed in the result. */ + } else { + /* All fraction bits in msw are relevant. Truncate irrelevant bits from lsw. */ + INSERT_WORDS(x, msw, lsw & ~(0xffffffffU >> (exponent_less_1023 - 20))); + } + + return x; +} + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +long double truncl(long double x) +{ + return (long double) trunc((double) x); +} + +#endif /* #ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS */ +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/y0d.c b/libm/libmcs/libm/mathd/y0d.c new file mode 100644 index 00000000..a75a1133 --- /dev/null +++ b/libm/libmcs/libm/mathd/y0d.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the Bessel function of the second kind + * of order 0. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * double y0(double x); + * + * Description + * =========== + * + * ``y0`` computes the Bessel value of :math:`x` of the second kind of order 0. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * y0(x) = Y_{0}(x) + * + * Notice that the mathematical function represented by the procedure ``y0`` is + * not :math:`y_0` (which is the spherical version of the Bessel function) but + * :math:`Y_0`. See `WolframAlpha Y_0(x) + * `_ for what it looks like + * and `Wikipedia `_ for more + * information. + * + * Returns + * ======= + * + * ``y0`` returns the Bessel value of :math:`x` of the second kind of order 0. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is negative. + * + * Raise ``divide by zero`` exception when the input value is zero. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+------------------+--------------+--------------+------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================+==============+==============+==================+==============+==============+ + * | **y0(x)** | :math:`qNaN` | :math:`-Inf` | :math:`Y_{0}(x)` | :math:`+0` | :math:`qNaN` | + * +---------------------+--------------+------------------+--------------+--------------+------------------+--------------+--------------+ + * + */ + +#include +#include "internal/besseld.h" +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double +u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ +u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ +u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ +u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */ +u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */ +u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */ +u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */ +v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */ +v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */ +v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ +v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ + +double y0(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double z, s, c, ss, cc, u, v; + int32_t hx, ix, lx; + + EXTRACT_WORDS(hx, lx, x); + ix = 0x7fffffff & hx; + + if (ix >= 0x7ff00000) { + if (isnan(x)) { /* y0(NaN) = NaN */ + return x + x; + } else if (hx > 0) { /* y0(+Inf) = +0.0 */ + return zero; + } else { + /* No action required */ + } + } + + if ((ix | lx) == 0) { /* y0(+-0) = +Inf */ + return __raise_div_by_zero(-1.0); + } + + if (hx < 0) { /* y0(<0) = NaN, y0(-Inf) = NaN */ + return __raise_invalid(); + } + + if (ix >= 0x40000000) { /* |x| >= 2.0 */ + /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) + * where x0 = x-pi/4 + * Better formula: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) + cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + s = sin(x); + c = cos(x); + ss = s - c; + cc = s + c; + + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + if (ix < 0x7fe00000) { /* make sure x+x not overflow */ + z = -cos(x + x); + + if ((s * c) < zero) { + cc = z / ss; + } else { + ss = z / cc; + } + } + + if (ix > 0x48000000) { + z = (invsqrtpi * ss) / sqrt(x); + } else { + u = __j0_p(x); + v = __j0_q(x); + z = invsqrtpi * (u * ss + v * cc) / sqrt(x); + } + + return z; + } + + if (ix <= 0x3e400000) { /* x < 2**-27 */ + return (u00 + tpi * log(x)); + } + + z = x * x; + u = u00 + z * (u01 + z * (u02 + z * (u03 + z * (u04 + z * (u05 + z * u06))))); + v = one + z * (v01 + z * (v02 + z * (v03 + z * v04))); + return (u / v + tpi * (j0(x) * log(x))); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/y1d.c b/libm/libmcs/libm/mathd/y1d.c new file mode 100644 index 00000000..4d95a063 --- /dev/null +++ b/libm/libmcs/libm/mathd/y1d.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the Bessel function of the second kind + * of order 1. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * double y1(double x); + * + * Description + * =========== + * + * ``y1`` computes the Bessel value of :math:`x` of the second kind of order 1. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * y1(x) = Y_{1}(x) + * + * Notice that the mathematical function represented by the procedure ``y1`` is + * not :math:`y_1` (which is the spherical version of the Bessel function) but + * :math:`Y_1`. See `WolframAlpha Y_1(x) + * `_ for what it looks like + * and `Wikipedia `_ for more + * information. + * + * Returns + * ======= + * + * ``y1`` returns the Bessel value of :math:`x` of the second kind of order 1. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when the input value is negative. + * + * Raise ``divide by zero`` exception when the input value is zero. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +---------------------+--------------+------------------+--------------+--------------+------------------+--------------+--------------+ + * | **x** | :math:`-Inf` | :math:`<0` | :math:`-0` | :math:`+0` | :math:`>0` | :math:`+Inf` | :math:`NaN` | + * +=====================+==============+==================+==============+==============+==================+==============+==============+ + * | **y1(x)** | :math:`qNaN` | :math:`-Inf` | :math:`Y_{1}(x)` | :math:`+0` | :math:`qNaN` | + * +---------------------+--------------+------------------+--------------+--------------+------------------+--------------+--------------+ + * + */ + +#include +#include "internal/besseld.h" +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +static const double U0[5] = { + -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ + 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ + -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ + 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ + -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ +}; +static const double V0[5] = { + 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ + 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ + 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ + 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ + 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ +}; + +double y1(double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + double z, s, c, ss, cc, u, v; + int32_t hx, ix, lx; + + EXTRACT_WORDS(hx, lx, x); + ix = 0x7fffffff & hx; + + if (ix >= 0x7ff00000) { + if (isnan(x)) { /* y1(NaN) = NaN */ + return x + x; + } else if (hx > 0) { /* y1(+Inf) = +0.0 */ + return zero; + } else { + /* No action required */ + } + } + + if ((ix | lx) == 0) { /* y1(+-0) = -Inf */ + return __raise_div_by_zero(-1.0); + } + + if (hx < 0) { /* y1(<0) = NaN, y1(-Inf) = NaN */ + return __raise_invalid(); + } + + if (ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(x); + c = cos(x); + ss = -s - c; + cc = s - c; + + if (ix < 0x7fe00000) { /* make sure x+x not overflow */ + z = cos(x + x); + + if ((s * c) > zero) { + cc = z / ss; + } else { + ss = z / cc; + } + } + + /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) + * where x0 = x-3pi/4 + * Better formula: + * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (cos(x) + sin(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + if (ix > 0x48000000) { + z = (invsqrtpi * ss) / sqrt(x); + } else { + u = __j1_p(x); + v = __j1_q(x); + z = invsqrtpi * (u * ss + v * cc) / sqrt(x); + } + + return z; + } + + if (ix <= 0x3c900000) { /* x < 2**-54 */ + return (-tpi / x); + } + + z = x * x; + u = U0[0] + z * (U0[1] + z * (U0[2] + z * (U0[3] + z * U0[4]))); + v = one + z * (V0[0] + z * (V0[1] + z * (V0[2] + z * (V0[3] + z * V0[4])))); + return (x * (u / v) + tpi * (j1(x) * log(x) - one / x)); +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathd/ynd.c b/libm/libmcs/libm/mathd/ynd.c new file mode 100644 index 00000000..1de96656 --- /dev/null +++ b/libm/libmcs/libm/mathd/ynd.c @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/** + * + * This family of functions implements the Bessel function of the second kind + * of order :math:`n`. + * + * Synopsis + * ======== + * + * .. code-block:: c + * + * #include + * double yn(int n, double x); + * + * Description + * =========== + * + * ``yn`` computes the Bessel value of :math:`x` of the second kind of order + * :math:`n`. + * + * Mathematical Function + * ===================== + * + * .. math:: + * + * yn(n, x) = Y_{n}(x) + * + * Notice that the mathematical function represented by the procedure ``yn`` is + * not :math:`y_n` (which is the spherical version of the Bessel function) but + * :math:`Y_n`. See `Wikipedia + * `_ for more information. + * + * Returns + * ======= + * + * ``yn`` returns the Bessel value of :math:`x` of the second kind of order + * :math:`n`. + * + * Exceptions + * ========== + * + * Raise ``invalid operation`` exception when :math:`x` is negative. + * + * Raise ``divide by zero`` exception when :math:`x` is zero. + * + * .. May raise ``underflow`` exception. + * + * Output map + * ========== + * + * +--------------------------+-------------------------------+-------------------------------+ + * | yn(n,x) | n | + * +--------------------------+-------------------------------+-------------------------------+ + * | x | :math:`<0` | :math:`>0` | + * +==========================+===============================+===============================+ + * | :math:`-Inf` | :math:`qNaN` | + * +--------------------------+ + + * | :math:`<0` | | + * +--------------------------+-------------------------------+-------------------------------+ + * | :math:`-0` | :math:`-Inf` | + * +--------------------------+ + + * | :math:`+0` | | + * +--------------------------+-------------------------------+-------------------------------+ + * | :math:`>0` | :math:`(-1)^n \cdot Y_{n}(x)` | :math:`Y_{n}(x)` | + * +--------------------------+-------------------------------+-------------------------------+ + * | :math:`+Inf` | :math:`+0` | + * +--------------------------+-------------------------------+-------------------------------+ + * | :math:`NaN` | :math:`qNaN` | + * +--------------------------+-------------------------------+-------------------------------+ + * + */ + +#include +#include "internal/besseld.h" +#include "../common/tools.h" + +#ifndef __LIBMCS_DOUBLE_IS_32BITS + +double yn(int n, double x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t i, hx, ix, lx; + int32_t sign; + double a, b, temp; + + EXTRACT_WORDS(hx, lx, x); + ix = 0x7fffffff & hx; + + /* if Y(n,NaN) is NaN */ + if (isnan(x)) { /* yn(n,NaN) = NaN */ + return x + x; + } + + if ((ix | lx) == 0) { /* yn(n,+-0) = +Inf */ + return __raise_div_by_zero(-1.0); + } + + if (hx < 0) { /* yn(n,<0) = NaN, y1(n,-Inf) = NaN */ + return __raise_invalid(); + } + + sign = 1; + + if (n < 0) { + n = -n; + sign = 1 - ((n & 1) << 1); + } + + if (n == 0) { + return (y0(x)); + } + + if (n == 1) { + return (sign * y1(x)); + } + + if (ix == 0x7ff00000) { /* yn(n,+Inf) = +0.0 */ + return zero; + } + + if (ix >= 0x52D00000) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + switch (n & 3) { + default: /* FALLTHRU */ + case 0: + temp = sin(x) - cos(x); + break; + + case 1: + temp = -sin(x) - cos(x); + break; + + case 2: + temp = -sin(x) + cos(x); + break; + + case 3: + temp = sin(x) + cos(x); + break; + } + + b = invsqrtpi * temp / sqrt(x); + } else { + uint32_t high; + a = y0(x); + b = y1(x); + /* quit if b is -inf */ + GET_HIGH_WORD(high, b); + + for (i = 1; i < n && high != 0xfff00000U; i++) { + temp = b; + b = ((double)(i + i) / x) * b - a; + GET_HIGH_WORD(high, b); + a = temp; + } + } + + if (sign > 0) { + return b; + } else { + return -b; + } +} + +#endif /* #ifndef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/acosf.c b/libm/libmcs/libm/mathf/acosf.c new file mode 100644 index 00000000..23f61271 --- /dev/null +++ b/libm/libmcs/libm/mathf/acosf.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +one = 1.0000000000e+00f, /* 0x3F800000 */ +pi = 3.1415925026e+00f, /* 0x40490fda */ +pio2_hi = 1.5707962513e+00f, /* 0x3fc90fda */ +pio2_lo = 7.5497894159e-08f, /* 0x33a22168 */ +pS0 = 1.6666667163e-01f, /* 0x3e2aaaab */ +pS1 = -3.2556581497e-01f, /* 0xbea6b090 */ +pS2 = 2.0121252537e-01f, /* 0x3e4e0aa8 */ +pS3 = -4.0055535734e-02f, /* 0xbd241146 */ +pS4 = 7.9153501429e-04f, /* 0x3a4f7f04 */ +pS5 = 3.4793309169e-05f, /* 0x3811ef08 */ +qS1 = -2.4033949375e+00f, /* 0xc019d139 */ +qS2 = 2.0209457874e+00f, /* 0x4001572d */ +qS3 = -6.8828397989e-01f, /* 0xbf303361 */ +qS4 = 7.7038154006e-02f; /* 0x3d9dc62e */ + +float acosf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float z, p, q, r, w, s, c, df; + int32_t hx, ix; + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix == 0x3f800000) { /* |x|==1 */ + if (hx > 0) { + return 0.0f; /* acos(1) = 0 */ + } else { + return pi + 2.0f * pio2_lo; /* acos(-1)= pi */ + } + } else if (ix > 0x3f800000) { /* |x| >= 1 */ + if (isnan(x)) { + return x + x; + } + + return __raise_invalidf(); /* acos(|x|>1) is NaN */ + } else { + /* No action required */ + } + + if (ix < 0x3f000000) { /* |x| < 0.5 */ + if (ix <= 0x23000000) { + return pio2_hi + pio2_lo; /*if|x|<2**-57*/ + } + + z = x * x; + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + r = p / q; + return pio2_hi - (x - (pio2_lo - x * r)); + } else if (hx < 0) { /* x < -0.5 */ + z = (one + x) * 0.5f; + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + s = sqrtf(z); + r = p / q; + w = r * s - pio2_lo; + return pi - 2.0f * (s + w); + } else { /* x > 0.5 */ + int32_t idf; + z = (one - x) * 0.5f; + s = sqrtf(z); + df = s; + GET_FLOAT_WORD(idf, df); + SET_FLOAT_WORD(df, idf & 0xfffff000U); + c = (z - df * df) / (s + df); + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + r = p / q; + w = r * s + c; + return 2.0f * (df + w); + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double acos(double x) +{ + return (double) acosf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/acoshf.c b/libm/libmcs/libm/mathf/acoshf.c new file mode 100644 index 00000000..d9b50c40 --- /dev/null +++ b/libm/libmcs/libm/mathf/acoshf.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +one = 1.0f, +ln2 = 6.9314718246e-01f; /* 0x3f317218 */ + +float acoshf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float t; + int32_t hx; + GET_FLOAT_WORD(hx, x); + + if (hx < 0x3f800000) { /* x < 1 */ + if (isnan(x)) { + return x + x; + } else { + return __raise_invalidf(); + } + } else if (hx >= 0x4d800000) { /* x > 2**28 */ + if (!FLT_UWORD_IS_FINITE(hx)) { /* x is +inf or NaN */ + return x + x; + } else { + return logf(x) + ln2; /* acosh(huge)=log(2x) */ + } + } else if (hx == 0x3f800000) { + return 0.0f; /* acosh(1) = 0 */ + } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ + t = x * x; + return logf(2.0f * x - one / (x + sqrtf(t - one))); + } else { /* 1 +#include "../common/tools.h" + +static const float +one = 1.0000000000e+00f, /* 0x3F800000 */ +pio2_hi = 1.57079637050628662109375f, +pio2_lo = -4.37113900018624283e-8f, +pio4_hi = 0.785398185253143310546875f, +/* coefficient for R(x^2) */ +pS0 = 1.6666667163e-01f, /* 0x3e2aaaab */ +pS1 = -3.2556581497e-01f, /* 0xbea6b090 */ +pS2 = 2.0121252537e-01f, /* 0x3e4e0aa8 */ +pS3 = -4.0055535734e-02f, /* 0xbd241146 */ +pS4 = 7.9153501429e-04f, /* 0x3a4f7f04 */ +pS5 = 3.4793309169e-05f, /* 0x3811ef08 */ +qS1 = -2.4033949375e+00f, /* 0xc019d139 */ +qS2 = 2.0209457874e+00f, /* 0x4001572d */ +qS3 = -6.8828397989e-01f, /* 0xbf303361 */ +qS4 = 7.7038154006e-02f; /* 0x3d9dc62e */ + +float asinf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float t, w, p, q, c, r, s; + int32_t hx, ix; + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix == 0x3f800000) { /* asin(1)=+-pi/2 with inexact */ + return x * pio2_hi + x * pio2_lo; + } else if (ix > 0x3f800000) { /* |x|>= 1 */ + if (isnan(x)) { + return x + x; + } + + return __raise_invalidf(); /* asin(|x|>1) is NaN */ + } else if (ix < 0x3f000000) { /* |x|<0.5 */ + if (ix < 0x32000000) { /* if |x| < 2**-27 */ + if (FLT_UWORD_IS_ZERO(ix)) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexactf(x); + } + } else { + t = x * x; + p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5))))); + q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4))); + w = p / q; + return x + x * w; + } + } else { + /* No action required */ + } + + /* 1> |x|>= 0.5 */ + w = one - fabsf(x); + t = w * 0.5f; + p = t * (pS0 + t * (pS1 + t * (pS2 + t * (pS3 + t * (pS4 + t * pS5))))); + q = one + t * (qS1 + t * (qS2 + t * (qS3 + t * qS4))); + s = sqrtf(t); + + if (ix >= 0x3F79999A) { /* if |x| > 0.975 */ + w = p / q; + t = pio2_hi - (2.0f * (s + s * w) - pio2_lo); + } else { + int32_t iw; + w = s; + GET_FLOAT_WORD(iw, w); + SET_FLOAT_WORD(w, iw & 0xfffff000U); + c = (t - w * w) / (s + w); + r = p / q; + p = 2.0f * s * r - (pio2_lo - 2.0f * c); + q = pio4_hi - 2.0f * w; + t = pio4_hi - (p - q); + } + + if (hx > 0) { + return t; + } else { + return -t; + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double asin(double x) +{ + return (double) asinf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/asinhf.c b/libm/libmcs/libm/mathf/asinhf.c new file mode 100644 index 00000000..98f18d8f --- /dev/null +++ b/libm/libmcs/libm/mathf/asinhf.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +one = 1.0000000000e+00f, /* 0x3F800000 */ +ln2 = 6.9314718246e-01f; /* 0x3f317218 */ + +float asinhf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float t, w; + int32_t hx, ix; + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (!FLT_UWORD_IS_FINITE(ix)) { + return x + x; /* x is inf or NaN */ + } + + if (ix < 0x31800000) { /* |x|<2**-28 */ + if (FLT_UWORD_IS_ZERO(ix)) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexactf(x); + } + } + + if (ix > 0x4d800000) { /* |x| > 2**28 */ + w = logf(fabsf(x)) + ln2; + } else if (ix > 0x40000000) { /* 2**28 > |x| > 2.0 */ + t = fabsf(x); + w = logf(2.0f * t + one / (sqrtf(x * x + one) + t)); + } else { /* 2.0 > |x| > 2**-28 */ + t = x * x; + w = log1pf(fabsf(x) + t / (one + sqrtf(one + t))); + } + + if (hx > 0) { + return w; + } else { + return -w; + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double asinh(double x) +{ + return (double) asinhf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/atan2f.c b/libm/libmcs/libm/mathf/atan2f.c new file mode 100644 index 00000000..7ef6c7f8 --- /dev/null +++ b/libm/libmcs/libm/mathf/atan2f.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +zero = 0.0f, +pi_o_4 = 7.8539818525e-01f, /* 0x3f490fdb */ +pi_o_2 = 1.5707963705e+00f, /* 0x3fc90fdb */ +pi = 3.1415927410e+00f, /* 0x40490fdb */ +pi_lo = -8.7422776573e-08f; /* 0xb3bbbd2e */ + +float atan2f(float y, float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + 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 (FLT_UWORD_IS_NAN(ix) || + FLT_UWORD_IS_NAN(iy)) { /* 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 (FLT_UWORD_IS_ZERO(iy)) { + switch (m) { + default: /* FALLTHRU */ + case 0: /* FALLTHRU */ + case 1: + return y; /* atan(+-0,+anything)=+-0 */ + + case 2: + return __raise_inexactf(pi); /* atan(+0,-anything) = pi */ + + case 3: + return -__raise_inexactf(pi); /* atan(-0,-anything) =-pi */ + } + } + + /* when x = 0 */ + if (FLT_UWORD_IS_ZERO(ix)) { + return (hy < 0) ? -__raise_inexactf(pi_o_2) : __raise_inexactf(pi_o_2); + } + + /* when x is INF */ + if (FLT_UWORD_IS_INFINITE(ix)) { + if (FLT_UWORD_IS_INFINITE(iy)) { + switch (m) { + default: /* FALLTHRU */ + case 0: + return __raise_inexactf(pi_o_4); /* atan(+INF,+INF) */ + + case 1: + return -__raise_inexactf(pi_o_4); /* atan(-INF,+INF) */ + + case 2: + return __raise_inexactf(3.0f * pi_o_4); /*atan(+INF,-INF)*/ + + case 3: + return -__raise_inexactf(3.0f * pi_o_4); /*atan(-INF,-INF)*/ + } + } else { + switch (m) { + default: /* FALLTHRU */ + case 0: + return zero; /* atan(+...,+INF) */ + + case 1: + return -zero; /* atan(-...,+INF) */ + + case 2: + return __raise_inexactf(pi); /* atan(+...,-INF) */ + + case 3: + return -__raise_inexactf(pi); /* atan(-...,-INF) */ + } + } + } + + /* when y is INF */ + if (FLT_UWORD_IS_INFINITE(iy)) { + return (hy < 0) ? -__raise_inexactf(pi_o_2) : __raise_inexactf(pi_o_2); + } + + /* compute y/x */ + k = (iy - ix) >> 23; + + if (k > 26) { + z = __raise_inexactf(pi_o_2); /* |y/x| > 2**26 */ + m &= 1; + } else if (hx < 0 && k < -26) { + z = 0.0f; /* 0 > |y|/x > -2**26 */ + } else { + z = atanf(fabsf(y / x)); /* safe to do y/x */ + } + + switch (m) { + case 0: + return z ; /* atan(+,+) */ + + case 1: + return -z ; /* atan(-,+) */ + + case 2: + return pi - (z - pi_lo); /* atan(+,-) */ + + default: /* case 3 */ + return (z - pi_lo) - pi; /* atan(-,-) */ + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double atan2(double y, double x) +{ + return (double) atan2f((float) y, (float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/atanf.c b/libm/libmcs/libm/mathf/atanf.c new file mode 100644 index 00000000..79491127 --- /dev/null +++ b/libm/libmcs/libm/mathf/atanf.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float atanhi[] = { + 4.6364760399e-01f, /* atan(0.5)hi 0x3eed6338 */ + 7.8539812565e-01f, /* atan(1.0)hi 0x3f490fda */ + 9.8279368877e-01f, /* atan(1.5)hi 0x3f7b985e */ + 1.5707962513e+00f, /* atan(inf)hi 0x3fc90fda */ +}; + +static const float atanlo[] = { + 5.0121582440e-09f, /* atan(0.5)lo 0x31ac3769 */ + 3.7748947079e-08f, /* atan(1.0)lo 0x33222168 */ + 3.4473217170e-08f, /* atan(1.5)lo 0x33140fb4 */ + 7.5497894159e-08f, /* atan(inf)lo 0x33a22168 */ +}; + +static const float aT[] = { + 3.3333334327e-01f, /* 0x3eaaaaaa */ + -2.0000000298e-01f, /* 0xbe4ccccd */ + 1.4285714924e-01f, /* 0x3e124925 */ + -1.1111110449e-01f, /* 0xbde38e38 */ + 9.0908870101e-02f, /* 0x3dba2e6e */ + -7.6918758452e-02f, /* 0xbd9d8795 */ + 6.6610731184e-02f, /* 0x3d886b35 */ + -5.8335702866e-02f, /* 0xbd6ef16b */ + 4.9768779427e-02f, /* 0x3d4bda59 */ + -3.6531571299e-02f, /* 0xbd15a221 */ + 1.6285819933e-02f, /* 0x3c8569d7 */ +}; + +static const float one = 1.0f; + +float atanf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float w, s1, s2, z; + int32_t ix, hx, id; + + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix >= 0x50800000) { /* if |x| >= 2^34 */ + if (FLT_UWORD_IS_NAN(ix)) { + return x + x; /* NaN */ + } + + if (hx > 0) { + return atanhi[3] + atanlo[3]; + } else { + return -atanhi[3] - atanlo[3]; + } + } + + if (ix < 0x3ee00000) { /* |x| < 0.4375 */ + if (ix < 0x31000000) { /* |x| < 2^-29 */ + if (FLT_UWORD_IS_ZERO(ix)) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexactf(x); + } + } + + id = -1; + } else { + x = fabsf(x); + + if (ix < 0x3f980000) { /* |x| < 1.1875 */ + if (ix < 0x3f300000) { /* 7/16 <=|x|<11/16 */ + id = 0; + x = (2.0f * x - one) / (2.0f + x); + } else { /* 11/16<=|x|< 19/16 */ + id = 1; + x = (x - one) / (x + one); + } + } else { + if (ix < 0x401c0000) { /* |x| < 2.4375 */ + id = 2; + x = (x - 1.5f) / (one + 1.5f * x); + } else { /* 2.4375 <= |x| < 2^66 */ + id = 3; + x = -1.0f / x; + } + } + } + + /* end of argument reduction */ + z = x * x; + w = z * z; + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + s1 = z * (aT[0] + w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10]))))); + s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9])))); + + if (id < 0) { + return x - x * (s1 + s2); + } else { + z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x); + return (hx < 0) ? -z : z; + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double atan(double x) +{ + return (double) atanf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/atanhf.c b/libm/libmcs/libm/mathf/atanhf.c new file mode 100644 index 00000000..0777d012 --- /dev/null +++ b/libm/libmcs/libm/mathf/atanhf.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float one = 1.0f; + +float atanhf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float t; + int32_t hx, ix; + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix > 0x3f800000) { /* |x|>1 */ + if (isnan(x)) { + return x + x; + } else { + return __raise_invalidf(); + } + } + + if (ix == 0x3f800000) { + return __raise_div_by_zerof(x); + } + + if (ix < 0x31800000) { /* x<2**-28 */ + if (FLT_UWORD_IS_ZERO(ix)) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexactf(x); + } + } + + SET_FLOAT_WORD(x, ix); + + if (ix < 0x3f000000) { /* x < 0.5 */ + t = x + x; + t = 0.5f * log1pf(t + t * x / (one - x)); + } else { + t = 0.5f * log1pf((x + x) / (one - x)); + } + + if (hx >= 0) { + return t; + } else { + return -t; + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double atanh(double x) +{ + return (double) atanhf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/cbrtf.c b/libm/libmcs/libm/mathf/cbrtf.c new file mode 100644 index 00000000..c6874eb4 --- /dev/null +++ b/libm/libmcs/libm/mathf/cbrtf.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +/* cbrtf(x) + * Return cube root of x + */ +static const uint32_t +B1 = 709958130, /* B1 = (84+2/3-0.03306235651)*2**23 */ +B2 = 642849266; /* B2 = (76+2/3-0.03306235651)*2**23 */ + +static const float +C = 5.4285717010e-01f, /* 19/35 = 0x3f0af8b0 */ +D = -7.0530611277e-01f, /* -864/1225 = 0xbf348ef1 */ +E = 1.4142856598e+00f, /* 99/70 = 0x3fb50750 */ +F = 1.6071428061e+00f, /* 45/28 = 0x3fcdb6db */ +G = 3.5714286566e-01f; /* 5/14 = 0x3eb6db6e */ + +float cbrtf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx; + float r, s, t; + uint32_t sign; + uint32_t high; + + GET_FLOAT_WORD(hx, x); + sign = hx & 0x80000000U; /* sign= sign(x) */ + hx ^= sign; + + if (!FLT_UWORD_IS_FINITE(hx)) { + return (x + x); /* cbrt(NaN,INF) is itself */ + } + + if (FLT_UWORD_IS_ZERO(hx)) { + return (x); /* cbrt(0) is itself */ + } + + SET_FLOAT_WORD(x, hx); /* x <- |x| */ + + /* rough cbrt to 5 bits */ + if (FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal number */ + SET_FLOAT_WORD(t, 0x4b800000); /* set t= 2**24 */ + t *= x; + GET_FLOAT_WORD(high, t); + SET_FLOAT_WORD(t, high / 3 + B2); + } else { + SET_FLOAT_WORD(t, hx / 3 + B1); + } + + + /* new cbrt to 23 bits */ + r = t * t / x; + s = C + r * t; + t *= G + F / (s + E + D / s); + + /* restore the sign bit */ + GET_FLOAT_WORD(high, t); + SET_FLOAT_WORD(t, high | sign); + return (t); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double cbrt(double x) +{ + return (double) cbrtf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/ceilf.c b/libm/libmcs/libm/mathf/ceilf.c new file mode 100644 index 00000000..998a20e1 --- /dev/null +++ b/libm/libmcs/libm/mathf/ceilf.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +float ceilf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t _i0, _j0; + uint32_t i, ix; + GET_FLOAT_WORD(_i0, x); + ix = (_i0 & 0x7fffffff); + _j0 = (ix >> 23) - 0x7f; + + if (_j0 < 23) { + if (_j0 < 0) { /* raise inexact if x != 0 */ + if (FLT_UWORD_IS_ZERO(ix)) { + return x; + } + + (void) __raise_inexactf(x); /* raise inexact flag */ + + if (_i0 < 0) { + _i0 = (int32_t)0x80000000U; + } else { + _i0 = 0x3f800000; + } + } else { + i = (0x007fffff) >> _j0; + + if ((_i0 & i) == 0) { + return x; /* x is integral */ + } + + (void) __raise_inexactf(x); /* raise inexact flag */ + + if (_i0 > 0) { + _i0 += (0x00800000) >> _j0; + } + + _i0 &= (~i); + } + } else { + if (!FLT_UWORD_IS_FINITE(ix)) { + return x + x; /* inf or NaN */ + } else { + return x; /* x is integral */ + } + } + + SET_FLOAT_WORD(x, _i0); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double ceil(double x) +{ + return (double) ceilf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/copysignf.c b/libm/libmcs/libm/mathf/copysignf.c new file mode 100644 index 00000000..5f81e35a --- /dev/null +++ b/libm/libmcs/libm/mathf/copysignf.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +/* + * copysignf(float x, float y) + * copysignf(x,y) returns a value with the magnitude of x and + * with the sign bit of y. + */ + +#include +#include "../common/tools.h" + +float copysignf(float x, float y) +{ + uint32_t ix, iy; + GET_FLOAT_WORD(ix, x); + GET_FLOAT_WORD(iy, y); + SET_FLOAT_WORD(x, (ix & 0x7fffffffU) | (iy & 0x80000000U)); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double copysign(double x, double y) +{ + return (double) copysignf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/cosf.c b/libm/libmcs/libm/mathf/cosf.c new file mode 100644 index 00000000..49b295ed --- /dev/null +++ b/libm/libmcs/libm/mathf/cosf.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" +#include "internal/trigf.h" + +float cosf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float y[2], z = 0.0f; + int32_t n, ix; + + GET_FLOAT_WORD(ix, x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + + if (ix <= 0x3f490fd8) { + if(ix < 0x39800000) { /* if x < 2**-12 */ + if (x == 0.0f) { /* return 1 inexact except 0 */ + return 1.0f; + } else { + return __raise_inexactf(1.0f); + } + } + return __cosf(x, z); + } + + /* cos(Inf or NaN) is NaN */ + else if (!FLT_UWORD_IS_FINITE(ix)) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalidf(); + } + } + + /* argument reduction needed */ + else { + n = __rem_pio2f(x, y); + + switch (n & 3) { + case 0: + return __cosf(y[0], y[1]); + + case 1: + return -__sinf(y[0], y[1], 1); + + case 2: + return -__cosf(y[0], y[1]); + + default: + return __sinf(y[0], y[1], 1); + } + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double cos(double x) +{ + return (double) cosf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/coshf.c b/libm/libmcs/libm/mathf/coshf.c new file mode 100644 index 00000000..4bafb9c9 --- /dev/null +++ b/libm/libmcs/libm/mathf/coshf.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float one = 1.0f, half = 0.5f; + +float coshf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float t, w; + int32_t ix; + + GET_FLOAT_WORD(ix, x); + ix &= 0x7fffffff; + + /* x is INF or NaN */ + if (!FLT_UWORD_IS_FINITE(ix)) { + return x * x; + } + + /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ + if (ix < 0x3eb17218) { + t = expm1f(fabsf(x)); + w = one + t; + + if (ix < 0x24000000) { + 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 < 0x41b00000) { + t = expf(fabsf(x)); + return half * t + half / t; + } + + /* |x| in [22, log(maxfloat)] return half*exp(|x|) */ + if (ix <= FLT_UWORD_LOG_MAX) { + return half * expf(fabsf(x)); + } + + /* |x| in [log(maxfloat), overflowthresold] */ + if (ix <= FLT_UWORD_LOG_2MAX) { + w = expf(half * fabsf(x)); + t = half * w; + return t * w; + } + + /* |x| > overflowthresold, cosh(x) overflow */ + return __raise_overflowf(1.0f); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double cosh(double x) +{ + return (double) coshf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/erfcf.c b/libm/libmcs/libm/mathf/erfcf.c new file mode 100644 index 00000000..f791ac11 --- /dev/null +++ b/libm/libmcs/libm/mathf/erfcf.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" +#include "internal/errorfunctionf.h" + +static const float +half = 5.0000000000e-01f, /* 0x3F000000 */ +two = 2.0000000000e+00f, /* 0x40000000 */ +erx = 8.42697144e-01f; /* 0x3f57bb00 */ + +float erfcf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, ix; + float R, S, P, Q, s, y, z, r; + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (!FLT_UWORD_IS_FINITE(ix)) { + if (isnan(x)) { /* erfc(nan) = nan */ + return x + x; + } else if (hx > 0) { /* erfc(+inf) = 0 */ + return 0.0f; + } else { /* erfc(-inf) = 2 */ + return two; + } + } + + if (ix < 0x3f580000) { /* |x|<0.84375 */ + if (ix < 0x33800000) { /* |x|<2**-24 */ + return __raise_inexactf(one); + } + + y = __erff_y(x); + + 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 = __erff_P(s); + Q = __erff_Q(s); + + if (hx >= 0) { + z = one - erx; + return z - P / Q; + } else { + z = erx + P / Q; + return one + z; + } + } + + if (ix < 0x41220000) { /* |x|<10.125 */ + x = fabsf(x); + s = one / (x * x); + + if (ix < 0x4036DB6D) { /* |x| < 1/.35 ~ 2.857143*/ + R = __erff_Ra(s); + S = __erff_Sa(s); + } else { /* |x| >= 1/.35 ~ 2.857143 */ + if (hx < 0 && ix >= 0x40c00000) { + return __raise_inexactf(two); /* x < -6 */ + } + + R = __erff_Rb(s); + S = __erff_Sb(s); + } + + GET_FLOAT_WORD(ix, x); + SET_FLOAT_WORD(z, ix & 0xffffc000U); + r = expf(-z * z - 0.5625f) * expf((z - x) * (z + x) + R / S); + + if (hx > 0) { + return r / x; + } else { + return two - r / x; + } + } else { + if (hx > 0) { + return __raise_underflowf(0.0f); + } else { + return __raise_inexactf(two); + } + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double erfc(double x) +{ + return (double) erfcf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/erff.c b/libm/libmcs/libm/mathf/erff.c new file mode 100644 index 00000000..283e34e6 --- /dev/null +++ b/libm/libmcs/libm/mathf/erff.c @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" +#include "internal/errorfunctionf.h" + +static const float +erx = 8.42697144e-01f, /* 0x3f57bb00 */ +/* + * In the domain [0, 2**-14], only the first term in the power series + * expansion of erf(x) is used. The magnitude of the first neglected + * terms is less than 2**-42. + */ +efx = 1.2837916613e-01f, /* 0x3e0375d4 */ +efx8 = 1.0270333290e+00f; /* 0x3f8375d4 */ + +float erff(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, ix; + float R, S, P, Q, s, z, r; + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (!FLT_UWORD_IS_FINITE(ix)) { + if (isnan(x)) { /* erf(nan) = nan */ + return x + x; + } else if (hx > 0) { /* erf(+inf) = +1 */ + return 1.0f; + } else { /* erf(-inf) = -1 */ + return -1.0f; + } + } + + if (ix < 0x3f580000) { /* |x|<0.84375 */ + if (ix < 0x38800000) { /* |x|<2**-14 */ + if (ix < 0x04000000) + /*avoid underflow */ + { + return 0.125f * (8.0f * x + efx8 * x); + } + + return x + efx * x; + } + + return x + x * __erff_y(x); + } + + if (ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ + s = fabsf(x) - one; + P = __erff_P(s); + Q = __erff_Q(s); + + if (hx >= 0) { + return erx + P / Q; + } else { + return -erx - P / Q; + } + } + + if (ix >= 0x40800000) { /* inf>|x|>=4 */ + if (hx >= 0) { + return __raise_inexactf(one); + } else { + return -__raise_inexactf(one); + } + } + + x = fabsf(x); + s = one / (x * x); + + if (ix < 0x4036DB8C) { /* |x| < 1/0.35 */ + R = __erff_Ra(s); + S = __erff_Sa(s); + } else { /* |x| >= 1/0.35 */ + R = __erff_Rb(s); + S = __erff_Sb(s); + } + + GET_FLOAT_WORD(ix, x); + SET_FLOAT_WORD(z, ix & 0xffffc000U); + r = expf(-z * z - 0.5625f) * expf((z - x) * (z + x) + R / S); + + if (hx >= 0) { + return one - r / x; + } else { + return r / x - one; + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double erf(double x) +{ + return (double) erff((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/exp2f.c b/libm/libmcs/libm/mathf/exp2f.c new file mode 100644 index 00000000..a9d77f26 --- /dev/null +++ b/libm/libmcs/libm/mathf/exp2f.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include + +float exp2f(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return powf(2.0f, x); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double exp2(double x) +{ + return (double) exp2f((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/expf.c b/libm/libmcs/libm/mathf/expf.c new file mode 100644 index 00000000..419d5757 --- /dev/null +++ b/libm/libmcs/libm/mathf/expf.c @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +one = 1.0f, +zero = 0.0f, +halF[2] = { 0.5f, -0.5f}, +twom100 = 7.8886090522e-31f, /* 2**-100=0x0d800000 */ +ln2HI[2] = { 6.9314575195e-01f, /* 0x3f317200 */ + -6.9314575195e-01f, /* 0xbf317200 */ +}, +ln2LO[2] = { 1.4286067653e-06f, /* 0x35bfbe8e */ + -1.4286067653e-06f, /* 0xb5bfbe8e */ +}, +invln2 = 1.4426950216e+00f, /* 0x3fb8aa3b */ +P1 = 1.6666667163e-01f, /* 0x3e2aaaab */ +P2 = -2.7777778450e-03f, /* 0xbb360b61 */ +P3 = 6.6137559770e-05f, /* 0x388ab355 */ +P4 = -1.6533901999e-06f, /* 0xb5ddea0e */ +P5 = 4.1381369442e-08f; /* 0x3331bb4c */ + +float expf(float x) /* default IEEE float exp */ +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float y, c, t; + float hi = 0.0; + float lo = 0.0; + int32_t k = 0; + int32_t xsb, sx; + uint32_t hx; + + GET_FLOAT_WORD(sx, x); + xsb = (sx >> 31) & 1; /* sign bit of x */ + hx = sx & 0x7fffffff; /* high word of |x| */ + + /* filter out non-finite argument */ + if (FLT_UWORD_IS_NAN(hx)) { + return x + x; /* NaN */ + } + + if (FLT_UWORD_IS_INFINITE(hx)) { + return (xsb == 0) ? x : zero; + } /* exp(+-inf)={inf,0} */ + + if (sx > FLT_UWORD_LOG_MAX) { + return __raise_overflowf(one); /* overflow */ + } + + if (sx < 0 && hx > FLT_UWORD_LOG_MIN) { + return __raise_underflowf(zero); /* underflow */ + } + + /* argument reduction */ + if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ + if (hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ + hi = x - ln2HI[xsb]; + lo = ln2LO[xsb]; + k = 1 - xsb - xsb; + } else { + k = invln2 * x + halF[xsb]; + t = k; + hi = x - t * ln2HI[0]; /* t*ln2HI is exact here */ + lo = t * ln2LO[0]; + } + + x = hi - lo; + } else if (hx < 0x34000000) { /* when |x|<2**-23 */ + if (x == 0.0f) { /* return 1 inexact except 0 */ + return one; + } else { + return __raise_inexactf(one + x); + } + } else { + /* No action required */ + } + + /* x is now in primary range */ + t = x * x; + c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + + if (k == 0) { + return one - ((x * c) / (c - 2.0f) - x); + } else { + y = one - ((lo - (x * c) / (2.0f - c)) - hi); + } + + if (k >= -125) { + uint32_t hy; + GET_FLOAT_WORD(hy, y); + SET_FLOAT_WORD(y, hy + (((uint32_t)k) << 23)); /* add k to y's exponent */ + return y; + } else { + uint32_t hy; + GET_FLOAT_WORD(hy, y); + SET_FLOAT_WORD(y, hy + (((uint32_t)k + 100U) << 23)); /* add k to y's exponent */ + return y * twom100; + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double exp(double x) +{ + return (double) expf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/expm1f.c b/libm/libmcs/libm/mathf/expm1f.c new file mode 100644 index 00000000..3fb9d40f --- /dev/null +++ b/libm/libmcs/libm/mathf/expm1f.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +one = 1.0f, +ln2_hi = 6.9313812256e-01f, /* 0x3f317180 */ +ln2_lo = 9.0580006145e-06f, /* 0x3717f7d1 */ +invln2 = 1.4426950216e+00f, /* 0x3fb8aa3b */ +/* scaled coefficients related to expm1 */ +Q1 = -3.3333335072e-02f, /* 0xbd088889 */ +Q2 = 1.5873016091e-03f, /* 0x3ad00d01 */ +Q3 = -7.9365076090e-05f, /* 0xb8a670cd */ +Q4 = 4.0082177293e-06f, /* 0x36867e54 */ +Q5 = -2.0109921195e-07f; /* 0xb457edbb */ + +float expm1f(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float y, hi, lo, c, t, e, hxs, hfx, r1; + int32_t k, xsb; + uint32_t hx; + + c = NAN; /* initial value of c is never actually used */ + + GET_FLOAT_WORD(hx, x); + xsb = hx & 0x80000000U; /* sign bit of x */ + + hx &= 0x7fffffffU; /* high word of |x| */ + + /* filter out huge and non-finite argument */ + if (hx >= 0x4195b844) { /* if |x|>=27*ln2 */ + if (FLT_UWORD_IS_NAN(hx)) { + return x + x; + } + + if (FLT_UWORD_IS_INFINITE(hx)) { + return (xsb == 0) ? x : -one; + }/* exp(+-inf)={inf,-1} */ + + if (xsb == 0 && hx > FLT_UWORD_LOG_MAX) { /* if x>=o_threshold */ + return __raise_overflowf(one); /* overflow */ + } + + if (xsb != 0) { /* x < -27*ln2, return -1.0 with inexact */ + return -__raise_inexactf(one); + } + } + + /* argument reduction */ + if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ + if (hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ + if (xsb == 0) { + hi = x - ln2_hi; + lo = ln2_lo; + k = 1; + } else { + hi = x + ln2_hi; + lo = -ln2_lo; + k = -1; + } + } else { + k = invln2 * x + ((xsb == 0) ? 0.5f : -0.5f); + t = k; + hi = x - t * ln2_hi; /* t*ln2_hi is exact here */ + lo = t * ln2_lo; + } + + x = hi - lo; + c = (hi - x) - lo; + } else if (hx < 0x33000000) { /* when |x|<2**-25, return x */ + if (x == 0.0f) { + return x; + } else { /* return x with inexact flags when x!=0 */ + return __raise_inexactf(x); + } + } else { + k = 0; + } + + /* x is now in primary range */ + hfx = 0.5f * x; + hxs = x * hfx; + r1 = one + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5)))); + t = 3.0f - r1 * hfx; + e = hxs * ((r1 - t) / (6.0f - x * t)); + + if (k == 0) { + return x - (x * e - hxs); /* c is 0 */ + } else { + e = (x * (e - c) - c); + e -= hxs; + + if (k == -1) { + return 0.5f * (x - e) - 0.5f; + } + + if (k == 1) { + if (x < -0.25f) { + return -2.0f * (e - (x + 0.5f)); + } else { + return one + 2.0f * (x - e); + } + } + + if (k <= -2 || k > 56) { /* suffice to return exp(x)-1 */ + int32_t i; + y = one - (e - x); + GET_FLOAT_WORD(i, y); + SET_FLOAT_WORD(y, i + (((uint32_t)k) << 23)); /* add k to y's exponent */ + return y - one; + } + + t = one; + + if (k < 23) { + int32_t i; + SET_FLOAT_WORD(t, 0x3f800000 - (0x1000000 >> k)); /* t=1-2^-k */ + y = t - (e - x); + GET_FLOAT_WORD(i, y); + SET_FLOAT_WORD(y, i + (k << 23)); /* add k to y's exponent */ + } else { + int32_t i; + SET_FLOAT_WORD(t, ((0x7f - k) << 23)); /* 2^-k */ + y = x - (e + t); + y += one; + GET_FLOAT_WORD(i, y); + SET_FLOAT_WORD(y, i + (k << 23)); /* add k to y's exponent */ + } + } + + return y; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double expm1(double x) +{ + return (double) expm1f((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/fabsf.c b/libm/libmcs/libm/mathf/fabsf.c new file mode 100644 index 00000000..f60522dd --- /dev/null +++ b/libm/libmcs/libm/mathf/fabsf.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +/* + * fabsf(x) returns the absolute value of x. + */ + +#include +#include "../common/tools.h" + +float fabsf(float x) +{ + uint32_t ix; + GET_FLOAT_WORD(ix, x); + SET_FLOAT_WORD(x, ix & 0x7fffffff); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double fabs(double x) +{ + return (double) fabsf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/fdimf.c b/libm/libmcs/libm/mathf/fdimf.c new file mode 100644 index 00000000..04ed1db9 --- /dev/null +++ b/libm/libmcs/libm/mathf/fdimf.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. */ + +#include + +float fdimf(float x, float y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + if (isnan(x) || isnan(y)) { + return x * y; + } + + return x > y ? x - y : 0.0f; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double fdim(double x, double y) +{ + return (double) fdimf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/floorf.c b/libm/libmcs/libm/mathf/floorf.c new file mode 100644 index 00000000..4d5b504f --- /dev/null +++ b/libm/libmcs/libm/mathf/floorf.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +/* + * floorf(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to floorf(x). + */ + +#include +#include "../common/tools.h" + +float floorf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t _i0, _j0; + uint32_t i, ix; + GET_FLOAT_WORD(_i0, x); + ix = (_i0 & 0x7fffffff); + _j0 = (ix >> 23) - 0x7f; + + if (_j0 < 23) { + if (_j0 < 0) { /* raise inexact if x != 0 */ + if (FLT_UWORD_IS_ZERO(ix)) { + return x; + } + + (void) __raise_inexactf(x); + + if (_i0 >= 0) { + _i0 = 0; + } else { + _i0 = (int32_t)0xbf800000U; + } + } else { + i = (0x007fffff) >> _j0; + + if ((_i0 & i) == 0) { /* x is integral */ + return x; + } + + (void) __raise_inexactf(x); + + if (_i0 < 0) { + _i0 += (0x00800000) >> _j0; + } + + _i0 &= (~i); + } + } else { + if (!FLT_UWORD_IS_FINITE(ix)) { + return x + x; /* inf or NaN */ + } else { + return x; /* x is integral */ + } + } + + SET_FLOAT_WORD(x, _i0); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double floor(double x) +{ + return (double) floorf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/fmaf.c b/libm/libmcs/libm/mathf/fmaf.c new file mode 100644 index 00000000..c03bd315 --- /dev/null +++ b/libm/libmcs/libm/mathf/fmaf.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#include + +float fmaf(float x, float y, float z) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; + z *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return x * y + z; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double fma(double x, double y, double z) +{ + return (double) fmaf((float) x, (float) y, (float) z); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/fmaxf.c b/libm/libmcs/libm/mathf/fmaxf.c new file mode 100644 index 00000000..73facf17 --- /dev/null +++ b/libm/libmcs/libm/mathf/fmaxf.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. */ + +#include +#include "../common/tools.h" + +float fmaxf(float x, float y) +{ + if (isnan(x)) { + if (__issignalingf(x) != 0 || __issignalingf(y) != 0) { + return x * y; + } +#ifdef __LIBMCS_FPU_DAZ + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return y; + } + + if (isnan(y)) { + if (__issignalingf(y) != 0) { + return x * y; + } +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return x; + } + +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return x > y ? x : y; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double fmax(double x, double y) +{ + return (double) fmaxf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/fminf.c b/libm/libmcs/libm/mathf/fminf.c new file mode 100644 index 00000000..98aa5b2f --- /dev/null +++ b/libm/libmcs/libm/mathf/fminf.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. */ + +#include +#include "../common/tools.h" + +float fminf(float x, float y) +{ + if (isnan(x)) { + if (__issignalingf(x) != 0 || __issignalingf(y) != 0) { + return x * y; + } +#ifdef __LIBMCS_FPU_DAZ + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return y; + } + + if (isnan(y)) { + if (__issignalingf(y) != 0) { + return x * y; + } +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return x; + } + +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return x < y ? x : y; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double fmin(double x, double y) +{ + return (double) fminf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/fmodf.c b/libm/libmcs/libm/mathf/fmodf.c new file mode 100644 index 00000000..22ba3bd1 --- /dev/null +++ b/libm/libmcs/libm/mathf/fmodf.c @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +/* + * fmodf(x,y) + * Return x mod y in exact arithmetic + * Method: shift and subtract + */ + +#include +#include "../common/tools.h" + +static const float Zero[] = {0.0f, -0.0f,}; + +float fmodf(float x, float y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t n, hx, hy, hz, ix, iy, sx, i; + + GET_FLOAT_WORD(hx, x); + GET_FLOAT_WORD(hy, y); + sx = hx & 0x80000000U; /* sign of x */ + hx ^= sx; /* |x| */ + hy &= 0x7fffffff; /* |y| */ + + /* purge off exception values */ + if (!FLT_UWORD_IS_FINITE(hx) || !FLT_UWORD_IS_FINITE(hy)) { /* x or y is +-Inf/NaN */ + if (FLT_UWORD_IS_INFINITE(hx)) { /* x is +-Inf */ + return __raise_invalidf(); + } else if (FLT_UWORD_IS_NAN(hx) || FLT_UWORD_IS_NAN(hy)) { /* x or y is NaN */ + return x + y; + } else { + /* No action required */ + } + } else if (FLT_UWORD_IS_ZERO(hy)) { /* y is +-0 */ + return __raise_invalidf(); + } else { + /* No action required */ + } + + if (hx < hy) { + return x; /* |x|<|y| return x */ + } + + if (hx == hy) { + return Zero[(uint32_t)sx >> 31]; /* |x|=|y| return x*0*/ + } + + /* Note: y cannot be zero if we reach here. */ + + /* determine ix = ilogb(x) */ + if (FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal x */ + for (ix = -126, i = (hx << 8); i > 0; i <<= 1) { + ix -= 1; + } + } else { + ix = (hx >> 23) - 127; + } + + /* determine iy = ilogb(y) */ + if (FLT_UWORD_IS_SUBNORMAL(hy)) { /* 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 << n; + } + + if (iy >= -126) { + hy = 0x00800000 | (0x007fffff & hy); + } else { /* subnormal y, shift y to normal */ + n = -126 - iy; + hy = hy << n; + } + + /* fix point fmod */ + n = ix - iy; + + while (n-- > 0) { + hz = hx - hy; + + if (hz < 0) { + hx = hx + hx; + } else { + if (hz == 0) { /* return sign(x)*0 */ + return Zero[(uint32_t)sx >> 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[(uint32_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); +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + } + + return x; /* exact output */ +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double fmod(double x, double y) +{ + return (double) fmodf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/frexpf.c b/libm/libmcs/libm/mathf/frexpf.c new file mode 100644 index 00000000..bfec0dea --- /dev/null +++ b/libm/libmcs/libm/mathf/frexpf.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include +#include "../common/tools.h" + +static const float +two25 = 3.3554432000e+07f; /* 0x4c000000 */ + +float frexpf(float x, int *eptr) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int _xexp = 0; + int32_t hx, ix; + + assert(eptr != (void*)0); + if(eptr == (void*)0) { + eptr = &_xexp; + } + + GET_FLOAT_WORD(hx, x); + ix = 0x7fffffff & hx; + *eptr = 0; + + if (!FLT_UWORD_IS_FINITE(ix) || FLT_UWORD_IS_ZERO(ix)) { + return x + x; /* 0,inf,nan */ + } + + if (FLT_UWORD_IS_SUBNORMAL(ix)) { /* subnormal */ + x *= two25; + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + *eptr = -25; + } + + *eptr += (ix >> 23) - 126; + hx = (hx & 0x807fffffU) | 0x3f000000U; + SET_FLOAT_WORD(x, hx); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double frexp(double x, int *eptr) +{ + return (double) frexpf((float) x, eptr); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/hypotf.c b/libm/libmcs/libm/mathf/hypotf.c new file mode 100644 index 00000000..91f0c351 --- /dev/null +++ b/libm/libmcs/libm/mathf/hypotf.c @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +float hypotf(float x, float y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float a = x; + float b = y; + float t1, t2; + float _y1, _y2; + float w; + int32_t j, k, ha, hb; + + GET_FLOAT_WORD(ha, x); + ha &= 0x7fffffff; + GET_FLOAT_WORD(hb, y); + hb &= 0x7fffffff; + + if (hb > ha) { + j = ha; + ha = hb; + hb = j; + } + + SET_FLOAT_WORD(a, ha); /* a <- |a| */ + SET_FLOAT_WORD(b, hb); /* b <- |b| */ + + if ((ha - hb) > 0xf000000) { + return a + b; /* x/y > 2**30 */ + } + + k = 0; + + if (ha > 0x58800000) { /* a>2**50 */ + if (!FLT_UWORD_IS_FINITE(ha)) { /* Inf or NaN */ + w = a + b; /* for sNaN */ + + if (FLT_UWORD_IS_INFINITE(ha)) { + w = a; + } + + if (FLT_UWORD_IS_INFINITE(hb)) { + w = b; + } + + return w; + } + + /* scale a and b by 2**-68 */ + ha -= 0x22000000; + hb -= 0x22000000; + k += 68; + SET_FLOAT_WORD(a, ha); + SET_FLOAT_WORD(b, hb); + } + + if (hb < 0x26800000) { /* b < 2**-50 */ + if (FLT_UWORD_IS_ZERO(hb)) { + return a; + } else if (FLT_UWORD_IS_SUBNORMAL(hb)) { + SET_FLOAT_WORD(t1, 0x7e800000); /* t1=2^126 */ + b *= t1; + a *= t1; + k -= 126; + } else { /* scale a and b by 2^80 */ + ha += 0x28000000; /* a *= 2^80 */ + hb += 0x28000000; /* b *= 2^80 */ + k -= 80; + SET_FLOAT_WORD(a, ha); + SET_FLOAT_WORD(b, hb); + } + } + + /* medium size a and b */ + w = a - b; + + if (w > b) { + SET_FLOAT_WORD(t1, ha & 0xfffff000U); + t2 = a - t1; + w = sqrtf(t1 * t1 - (b * (-b) - t2 * (a + t1))); + } else { + a = a + a; + SET_FLOAT_WORD(_y1, hb & 0xfffff000U); + _y2 = b - _y1; + SET_FLOAT_WORD(t1, (ha + 0x00800000) & 0xfffff000U); + t2 = a - t1; + w = sqrtf(t1 * _y1 - (w * (-w) - (t1 * _y2 + t2 * b))); + } + + if (k != 0) { + SET_FLOAT_WORD(t1, (0x7F + k) << 23); + return t1 * w; + } else { + return w; + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double hypot(double x, double y) +{ + return (double) hypotf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/ilogbf.c b/libm/libmcs/libm/mathf/ilogbf.c new file mode 100644 index 00000000..23ad7b76 --- /dev/null +++ b/libm/libmcs/libm/mathf/ilogbf.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +int ilogbf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, ix; + + GET_FLOAT_WORD(hx, x); + hx &= 0x7fffffff; + + if (FLT_UWORD_IS_ZERO(hx)) { + (void) __raise_invalidf(); + return FP_ILOGB0; /* ilogb(0) = special case error */ + } else if (FLT_UWORD_IS_SUBNORMAL(hx)) { + for (ix = -126, hx <<= 8; hx > 0; hx <<= 1) { + ix -= 1; + } + + return ix; + } else if (FLT_UWORD_IS_FINITE(hx)) { + return (hx >> 23) - 127; + } else if (FLT_UWORD_IS_NAN(hx)) { + (void) __raise_invalidf(); + return FP_ILOGBNAN; /* NAN */ + } else { + (void) __raise_invalidf(); + return INT_MAX; /* infinite */ + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +int ilogb(double x) +{ + return ilogbf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/internal/errorfunctionf.h b/libm/libmcs/libm/mathf/internal/errorfunctionf.h new file mode 100644 index 00000000..98a2d5fe --- /dev/null +++ b/libm/libmcs/libm/mathf/internal/errorfunctionf.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#ifndef LIBMCS_ERRORFUNCTIONF_H +#define LIBMCS_ERRORFUNCTIONF_H + +#include +#include "../../common/tools.h" + +static const float +one = 1.00000000e+00f, /* 0x3F800000 */ +/* + * Domain [0, 0.84375], range ~[-5.4419e-10, 5.5179e-10]: + * |(erf(x) - x)/x - pp(x)/qq(x)| < 2**-31 + */ +pp0 = 1.28379166e-01f, /* 0x3e0375d4 */ +pp1 = -3.36030394e-01f, /* 0xbeac0c2d */ +pp2 = -1.86261395e-03f, /* 0xbaf422f4 */ +qq1 = 3.12324315e-01f, /* 0x3e9fe8f9 */ +qq2 = 2.16070414e-02f, /* 0x3cb10140 */ +qq3 = -1.98859372e-03f, /* 0xbb025311 */ +/* + * Domain [0.84375, 1.25], range ~[-1.023e-9, 1.023e-9]: + * |(erf(x) - erx) - pa(x)/qa(x)| < 2**-31 + */ +pa0 = 3.65041046e-06f, /* 0x3674f993 */ +pa1 = 4.15109307e-01f, /* 0x3ed48935 */ +pa2 = -2.09395722e-01f, /* 0xbe566bd5 */ +pa3 = 8.67677554e-02f, /* 0x3db1b34b */ +qa1 = 4.95560974e-01f, /* 0x3efdba2b */ +qa2 = 3.71248513e-01f, /* 0x3ebe1449 */ +qa3 = 3.92478965e-02f, /* 0x3d20c267 */ +/* + * Domain [1.25,1/0.35], range ~[-4.821e-9, 4.927e-9]: + * |log(x*erfc(x)) + x**2 + 0.5625 - ra(x)/sa(x)| < 2**-28 + */ +ra0 = -9.88156721e-03f, /* 0xbc21e64c */ +ra1 = -5.43658376e-01f, /* 0xbf0b2d32 */ +ra2 = -1.66828310e+00f, /* 0xbfd58a4d */ +ra3 = -6.91554189e-01f, /* 0xbf3109b2 */ +sa1 = 4.48581553e+00f, /* 0x408f8bcd */ +sa2 = 4.10799170e+00f, /* 0x408374ab */ +sa3 = 5.53855181e-01f, /* 0x3f0dc974 */ +/* + * Domain [2.85715, 11], range ~[-1.484e-9, 1.505e-9]: + * |log(x*erfc(x)) + x**2 + 0.5625 - rb(x)/sb(x)| < 2**-30 + */ +rb0 = -9.86496918e-03f, /* 0xbc21a0ae */ +rb1 = -5.48049808e-01f, /* 0xbf0c4cfe */ +rb2 = -1.84115684e+00f, /* 0xbfebab07 */ +sb1 = 4.87132740e+00f, /* 0x409be1ea */ +sb2 = 3.04982710e+00f, /* 0x4043305e */ +sb3 = -7.61900663e-01f; /* 0xbf430bec */ + +static inline float __erff_y(float x) +{ + float s, z, r; + z = x * x; + r = pp0 + z * (pp1 + z * pp2); + s = one + z * (qq1 + z * (qq2 + z * qq3)); + return r / s; +} + +static inline float __erff_P(float s) +{ + return pa0 + s * (pa1 + s * (pa2 + s * pa3)); +} + +static inline float __erff_Q(float s) +{ + return one + s * (qa1 + s * (qa2 + s * qa3)); +} + +static inline float __erff_Ra(float s) +{ + return ra0 + s * (ra1 + s * (ra2 + s * ra3)); +} + +static inline float __erff_Sa(float s) +{ + return one + s * (sa1 + s * (sa2 + s * sa3)); +} + +static inline float __erff_Rb(float s) +{ + return rb0 + s * (rb1 + s * rb2); +} + +static inline float __erff_Sb(float s) +{ + return one + s * (sb1 + s * (sb2 + s * sb3)); +} + +#endif /* !LIBMCS_ERRORFUNCTIONF_H */ diff --git a/libm/libmcs/libm/mathf/internal/fpclassifyf.c b/libm/libmcs/libm/mathf/internal/fpclassifyf.c new file mode 100644 index 00000000..cfa4d285 --- /dev/null +++ b/libm/libmcs/libm/mathf/internal/fpclassifyf.c @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002,2007 by Red Hat, Incorporated. All rights reserved. */ + +#include +#include "../../common/tools.h" + +int __fpclassifyf(float x) +{ + uint32_t w; + + GET_FLOAT_WORD(w, x); + w &= 0x7fffffffU; + + if (w == 0x00000000U) { + return FP_ZERO; + } else if (w >= 0x00800000U && w <= 0x7f7fffffU) { + return FP_NORMAL; + } else if (w <= 0x007fffffU) { + return FP_SUBNORMAL; + } else if (w == 0x7f800000U) { + return FP_INFINITE; + } else { + return FP_NAN; + } +} + diff --git a/libm/libmcs/libm/mathf/internal/gammaf.c b/libm/libmcs/libm/mathf/internal/gammaf.c new file mode 100644 index 00000000..b84b02f3 --- /dev/null +++ b/libm/libmcs/libm/mathf/internal/gammaf.c @@ -0,0 +1,298 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include "../../common/tools.h" +#include "gammaf.h" +#include "trigf.h" + +static const float +two23 = 8.3886080000e+06f, /* 0x4b000000 */ +half = 5.0000000000e-01f, /* 0x3f000000 */ +one = 1.0000000000e+00f, /* 0x3f800000 */ +pi = 3.1415927410e+00f, /* 0x40490fdb */ +a0 = 7.7215664089e-02f, /* 0x3d9e233f */ +a1 = 3.2246702909e-01f, /* 0x3ea51a66 */ +a2 = 6.7352302372e-02f, /* 0x3d89f001 */ +a3 = 2.0580807701e-02f, /* 0x3ca89915 */ +a4 = 7.3855509982e-03f, /* 0x3bf2027e */ +a5 = 2.8905137442e-03f, /* 0x3b3d6ec6 */ +a6 = 1.1927076848e-03f, /* 0x3a9c54a1 */ +a7 = 5.1006977446e-04f, /* 0x3a05b634 */ +a8 = 2.2086278477e-04f, /* 0x39679767 */ +a9 = 1.0801156895e-04f, /* 0x38e28445 */ +a10 = 2.5214456400e-05f, /* 0x37d383a2 */ +a11 = 4.4864096708e-05f, /* 0x383c2c75 */ +tc = 1.4616321325e+00f, /* 0x3fbb16c3 */ +tf = -1.2148628384e-01f, /* 0xbdf8cdcd */ +/* tt = -(tail of tf) */ +tt = 6.6971006518e-09f, /* 0x31e61c52 */ +t0 = 4.8383611441e-01f, /* 0x3ef7b95e */ +t1 = -1.4758771658e-01f, /* 0xbe17213c */ +t2 = 6.4624942839e-02f, /* 0x3d845a15 */ +t3 = -3.2788541168e-02f, /* 0xbd064d47 */ +t4 = 1.7970675603e-02f, /* 0x3c93373d */ +t5 = -1.0314224288e-02f, /* 0xbc28fcfe */ +t6 = 6.1005386524e-03f, /* 0x3bc7e707 */ +t7 = -3.6845202558e-03f, /* 0xbb7177fe */ +t8 = 2.2596477065e-03f, /* 0x3b141699 */ +t9 = -1.4034647029e-03f, /* 0xbab7f476 */ +t10 = 8.8108185446e-04f, /* 0x3a66f867 */ +t11 = -5.3859531181e-04f, /* 0xba0d3085 */ +t12 = 3.1563205994e-04f, /* 0x39a57b6b */ +t13 = -3.1275415677e-04f, /* 0xb9a3f927 */ +t14 = 3.3552918467e-04f, /* 0x39afe9f7 */ +u0 = -7.7215664089e-02f, /* 0xbd9e233f */ +u1 = 6.3282704353e-01f, /* 0x3f2200f4 */ +u2 = 1.4549225569e+00f, /* 0x3fba3ae7 */ +u3 = 9.7771751881e-01f, /* 0x3f7a4bb2 */ +u4 = 2.2896373272e-01f, /* 0x3e6a7578 */ +u5 = 1.3381091878e-02f, /* 0x3c5b3c5e */ +v1 = 2.4559779167e+00f, /* 0x401d2ebe */ +v2 = 2.1284897327e+00f, /* 0x4008392d */ +v3 = 7.6928514242e-01f, /* 0x3f44efdf */ +v4 = 1.0422264785e-01f, /* 0x3dd572af */ +v5 = 3.2170924824e-03f, /* 0x3b52d5db */ +s0 = -7.7215664089e-02f, /* 0xbd9e233f */ +s1 = 2.1498242021e-01f, /* 0x3e5c245a */ +s2 = 3.2577878237e-01f, /* 0x3ea6cc7a */ +s3 = 1.4635047317e-01f, /* 0x3e15dce6 */ +s4 = 2.6642270386e-02f, /* 0x3cda40e4 */ +s5 = 1.8402845599e-03f, /* 0x3af135b4 */ +s6 = 3.1947532989e-05f, /* 0x3805ff67 */ +r1 = 1.3920053244e+00f, /* 0x3fb22d3b */ +r2 = 7.2193557024e-01f, /* 0x3f38d0c5 */ +r3 = 1.7193385959e-01f, /* 0x3e300f6e */ +r4 = 1.8645919859e-02f, /* 0x3c98bf54 */ +r5 = 7.7794247773e-04f, /* 0x3a4beed6 */ +r6 = 7.3266842264e-06f, /* 0x36f5d7bd */ +w0 = 4.1893854737e-01f, /* 0x3ed67f1d */ +w1 = 8.3333335817e-02f, /* 0x3daaaaab */ +w2 = -2.7777778450e-03f, /* 0xbb360b61 */ +w3 = 7.9365057172e-04f, /* 0x3a500cfd */ +w4 = -5.9518753551e-04f, /* 0xba1c065c */ +w5 = 8.3633989561e-04f, /* 0x3a5b3dd2 */ +w6 = -1.6309292987e-03f; /* 0xbad5c4e8 */ + +static const float zero = 0.0000000000e+00f; + +static float __sin_pif(float x) +{ + float y, z; + int32_t n, ix; + + GET_FLOAT_WORD(ix, x); + ix &= 0x7fffffff; + + if (ix < 0x3e800000) { + return __sinf(pi * x, zero, 0); + } + + y = -x; /* x is assume negative */ + + /* + * argument reduction, make sure inexact flag not raised if input + * is an integer + */ + z = floorf(y); + + if (z != y) { /* inexact anyway */ + y *= 0.5f; + y = 2.0f * (y - floorf(y)); /* y = |x| mod 2.0 */ + n = (int32_t)(y * 4.0f); + } else { + z = y + two23; /* exact */ + + GET_FLOAT_WORD(n, z); + n &= 1; + y = n; + n <<= 2; + } + + switch (n) { + case 0: + y = __sinf(pi * y, zero, 0); + break; + + case 1: /* FALLTHRU */ + case 2: + y = __cosf(pi * (0.5f - y), zero); + break; + + case 3: /* FALLTHRU */ + case 4: + y = __sinf(pi * (one - y), zero, 0); + break; + + case 5: /* FALLTHRU */ + case 6: + y = -__cosf(pi * (y - 1.5f), zero); + break; + + default: + y = __sinf(pi * (y - 2.0f), zero, 0); + break; + } + + return -y; +} + +float __lgammaf(float x, int *signgamp) +{ + float t, y, z, nadj = 0.0f, p, p1, p2, p3, q, r, w; + int32_t i, hx, ix; + + GET_FLOAT_WORD(hx, x); + + /* purge off +-inf, NaN, +-0, and negative arguments */ + *signgamp = 1; + ix = hx & 0x7fffffff; + + if (ix >= 0x7f800000) { + return x * x; + } + + if (ix == 0) { + if(hx < 0) { + *signgamp = -1; + } + return __raise_div_by_zerof(zero); + } + + if (ix < 0x30800000) { /* |x|<2**-30, return -log(|x|) */ + if (hx < 0) { + *signgamp = -1; + return -logf(-x); + } else { + return -logf(x); + } + } + + if (hx < 0) { + if (ix >= 0x4b000000) { /* |x|>=2**23, must be -integer */ + return __raise_div_by_zerof(zero); + } + + t = __sin_pif(x); + + if (t == zero) { + return __raise_div_by_zerof(zero); /* -integer */ + } + + nadj = logf(pi / fabsf(t * x)); + + if (t < zero) { + *signgamp = -1; + } + + x = -x; + } + + /* purge off 1 and 2 */ + if (ix == 0x3f800000 || ix == 0x40000000) { + r = 0; + } + /* for x < 2.0 */ + else if (ix < 0x40000000) { + if (ix <= 0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */ + r = -logf(x); + + if (ix >= 0x3f3b4a20) { + y = one - x; + i = 0; + } else if (ix >= 0x3e6d3308) { + y = x - (tc - one); + i = 1; + } else { + y = x; + i = 2; + } + } else { + r = zero; + + if (ix >= 0x3fdda618) { + y = 2.0f - x; /* [1.7316,2] */ + i = 0; + } else if (ix >= 0x3F9da620) { + y = x - tc; /* [1.23,1.73] */ + i = 1; + } else { + y = x - one; + i = 2; + } + } + + switch (i) { + default: /* FALLTHRU */ + case 0: + z = y * y; + p1 = a0 + z * (a2 + z * (a4 + z * (a6 + z * (a8 + z * a10)))); + p2 = z * (a1 + z * (a3 + z * (a5 + z * (a7 + z * (a9 + z * a11))))); + p = y * p1 + p2; + r += (p - 0.5f * y); + break; + + case 1: + z = y * y; + w = z * y; + p1 = t0 + w * (t3 + w * (t6 + w * (t9 + w * t12))); /* parallel comp */ + p2 = t1 + w * (t4 + w * (t7 + w * (t10 + w * t13))); + p3 = t2 + w * (t5 + w * (t8 + w * (t11 + w * t14))); + p = z * p1 - (tt - w * (p2 + y * p3)); + r += (tf + p); + break; + + case 2: + p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * u5))))); + p2 = one + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * v5)))); + r += (-0.5f * y + p1 / p2); + break; + } + } else if (ix < 0x41000000) { /* x < 8.0 */ + i = (int32_t)x; + y = x - (float)i; + p = y * (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6)))))); + q = one + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * r6))))); + r = half * y + p / q; + z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ + + switch (i) { + case 7: + z *= (y + 6.0f); /* FALLTHRU */ + + case 6: + z *= (y + 5.0f); /* FALLTHRU */ + + case 5: + z *= (y + 4.0f); /* FALLTHRU */ + + case 4: + z *= (y + 3.0f); /* FALLTHRU */ + + case 3: + z *= (y + 2.0f); /* FALLTHRU */ + + default: + r += logf(z); + break; + } + + /* 8.0 <= x < 2**58 */ + } else if (ix < 0x5c800000) { + t = logf(x); + z = one / x; + y = z * z; + w = w0 + z * (w1 + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * w6))))); + r = (x - half) * (t - one) + w; + } else + /* 2**58 <= x <= inf */ + { + r = x * (logf(x) - one); + } + + if (hx < 0) { + r = nadj - r; + } + + return r; +} diff --git a/libm/libmcs/libm/mathf/internal/gammaf.h b/libm/libmcs/libm/mathf/internal/gammaf.h new file mode 100644 index 00000000..46d624fc --- /dev/null +++ b/libm/libmcs/libm/mathf/internal/gammaf.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_GAMMAF_H +#define LIBMCS_GAMMAF_H + +extern float __lgammaf(float x, int *signgamp); + +#endif /* !LIBMCS_GAMMAF_H */ diff --git a/libm/libmcs/libm/mathf/internal/log1pmff.h b/libm/libmcs/libm/mathf/internal/log1pmff.h new file mode 100644 index 00000000..4a40a488 --- /dev/null +++ b/libm/libmcs/libm/mathf/internal/log1pmff.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +#ifndef LIBMCS_LOG1PMFF_H +#define LIBMCS_LOG1PMFF_H + +static const float +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +Lg1 = 0xaaaaaa.0p-24f, /* 0.66666662693, 0x3F2AAAAA */ +Lg2 = 0xccce13.0p-25f, /* 0.40000972152, 0x3ECCCE13 */ +Lg3 = 0x91e9ee.0p-25f, /* 0.28498786688, 0x3E91E9EE */ +Lg4 = 0xf89e26.0p-26f; /* 0.24279078841, 0x3E789E26 */ + +static inline float __log1pmff(float f) +{ + float hfsq, s, z, R, w, t1, t2; + + s = f / (2.0f + f); + z = s * s; + w = z * z; + t1 = w * (Lg2 + w * Lg4); + t2 = z * (Lg1 + w * Lg3); + R = t2 + t1; + hfsq = 0.5f * f * f; + return s * (hfsq + R); +} + +#endif /* !LIBMCS_LOG1PMFF_H */ diff --git a/libm/libmcs/libm/mathf/internal/signbitf.c b/libm/libmcs/libm/mathf/internal/signbitf.c new file mode 100644 index 00000000..7e98236d --- /dev/null +++ b/libm/libmcs/libm/mathf/internal/signbitf.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: RedHat */ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. */ + +/* +FUNCTION +<>---Does floating-point number have negative sign? + +INDEX + signbit + +SYNOPSIS + #include + int signbit(real-floating <[x]>); + +DESCRIPTION +The <> macro determines whether the sign of its argument value is +negative. The macro reports the sign of all values, including infinities, +zeros, and NaNs. If zero is unsigned, it is treated as positive. As shown in +the synopsis, the argument is "real-floating," meaning that any of the real +floating-point types (float, double, etc.) may be given to it. + +Note that because of the possibilities of signed 0 and NaNs, the expression +"<[x]> < 0.0" does not give the same result as <> in all cases. + +RETURNS +The <> macro returns a nonzero value if and only if the sign of its +argument value is negative. + +PORTABILITY +C99, POSIX. + +*/ + +#include +#include "../../common/tools.h" + +int __signbitf(float x) +{ + uint32_t w; + + GET_FLOAT_WORD(w, x); + + return (w & 0x80000000U) != 0; +} diff --git a/libm/libmcs/libm/mathf/internal/trigf.c b/libm/libmcs/libm/mathf/internal/trigf.c new file mode 100644 index 00000000..ad8fdca0 --- /dev/null +++ b/libm/libmcs/libm/mathf/internal/trigf.c @@ -0,0 +1,502 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../../common/tools.h" +#include "trigf.h" + +/* In the float version, the input parameter x contains 8 bit + integers, not 24 bit integers. 113 bit precision is not supported. */ + +/* + * 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. + */ + +/* + * Single precision array, obtained by cutting pi/2 + * into 8 bits chunks. + */ +static const float PIo2[] = { + 1.5703125000e+00f, /* 0x3fc90000 */ + 4.5776367188e-04f, /* 0x39f00000 */ + 2.5987625122e-05f, /* 0x37da0000 */ + 7.5437128544e-08f, /* 0x33a20000 */ + 6.0026650317e-11f, /* 0x2e840000 */ + 7.3896444519e-13f, /* 0x2b500000 */ + 5.3845816694e-15f, /* 0x27c20000 */ + 5.6378512969e-18f, /* 0x22d00000 */ + 8.3009228831e-20f, /* 0x1fc40000 */ + 3.2756352257e-22f, /* 0x1bc60000 */ + 6.3331015649e-25f, /* 0x17440000 */ +}; + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + * + * The integer array contains the (8*i)-th to (8*i+7)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * ipio2[i] * 2^(-8(i+1)). + */ +static const int32_t ipio2[] = { + 0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC, + 0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62, + 0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63, + 0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A, + 0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09, + 0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29, + 0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44, + 0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41, + 0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C, + 0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8, + 0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11, + 0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF, + 0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E, + 0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5, + 0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92, + 0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08, + 0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0, + 0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3, + 0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85, + 0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80, + 0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA, + 0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B, +}; + +static const float zero = 0.0f; +static const float one = 1.0f; +static const float two8 = 0x1p+08; /* 2.5600000000e+02f 0x43800000 */ +static const float twon8 = 0x1p-08; /* 3.9062500000e-03f 0x3b800000 */ + +static inline int __rem_pio2f_internal(float *x, float *y, int e0, int nx) +{ + int32_t jk = 7; /* precision setting + jk+1 is the initial number of terms of ipio2[] needed in the computation. */ + int32_t jp = jk; /* stores the initial value of jk until the final result computation */ + + int32_t k; /* number of additional ipio2 terms needed for recomputation */ + int32_t i, j, m; /* general purpose indices and variables */ + int32_t jz, jx, jv; /* other specific indices */ + int32_t carry; /* indicates whether there is a contribution of q when computing the complementary angle */ + int32_t ih; /* variable that indicates the position of the angle within the resulting quadrant. + If ih is positive then q[] is >= 0.5, hence it acts as the "signbit" of the result, + which will be positive for negative angles within the quadrant. */ + + + float q[20] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /* value of q = x/(pi/2) = x*(2/pi) */ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + int32_t q0; /* the corresponding exponent of q[0]. Note that the exponent for q[i] would be q0-8*i */ + + int32_t n; /* indicates the octant where the angle falls into; it is used to get the quadrant */ + float z; /* high order fractional part of q, down to the q0 bit */ + int32_t iq[20] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* lower order 8 bit chunks of fractional part of q in inverted order. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* iq starts after the q0 bits which are in z */ + + float fw; /* temporary variable to compute q, iq, and fq */ + float f[20] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /* ipio2[] terms taken fro computation in floating point */ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + float fq[20] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /* final product of q*pi/2 in fq[0],..,fq[jk]; */ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; /* computing the fractional value [0,1] within the quadrant back into radians */ + + + + bool recompute; /* variable used to signalize that a recomputation is needed as the current selection of ipio2[] terms has led to loss of significance. + The recomputation will take more terms of ipio2[]. */ + bool exhausted; /* variable used to signalize that the available ipio2 precision has been exhausted making no further recomputing possible */ + + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx - 1; + jv = (e0 - 3) / 8; + + q0 = e0 - 8 * (jv + 1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv - jx; + m = jx + jk; + + for (i = 0; i <= m; i++, j++) { + f[i] = (j < 0) ? zero : (float) ipio2[j]; + } + + /* compute q[0],q[1],...q[jk] */ + for (i = 0; i <= jk; i++) { + for (j = 0, fw = 0.0f; j <= jx; j++) { + fw += x[j] * f[jx + i - j]; + } + + q[i] = fw; + } + + jz = jk; + do { + recompute = false; + exhausted = false; + + /* distill the lower part of q[] into iq[] reversingly and leave the higher part in z */ + for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) { + fw = (float)((int32_t)(twon8 * z)); + iq[i] = (int32_t)(z - two8 * fw); + z = q[j - 1] + fw; + } + + /* compute n */ + z = scalbnf(z, (int32_t)q0); /* actual value of z */ + z -= 8.0f * floorf(z * 0.125f); /* trim off integer >= 8 */ + n = (int32_t) z; + z -= (float)n; + ih = 0; + + if (q0 > 0) { /* need iq[jz-1] to determine n */ + i = (iq[jz - 1] >> (8 - q0)); + n += i; + iq[jz - 1] -= i << (8 - q0); + ih = iq[jz - 1] >> (7 - q0); + } else if (q0 == 0) { + ih = iq[jz - 1] >> 7; + } else if (z >= 0.5f) { + ih = 2; + } else { + /* No action required */ + } + + /* for the cases that the angle is in the upper side of the quadrant, the complementary is computed */ + if (ih > 0) { /* q > 0.5 */ + n += 1; + carry = 0; + + for (i = 0; i < jz ; i++) { /* compute 1-q by computing the complementary of iq */ + j = iq[i]; + + if (carry == 0) { + if (j != 0) { + carry = 1; + iq[i] = 0x100 - j; + } + } else { + iq[i] = 0xff - j; + } + } + + if (q0 > 0) { /* rare case: chance is 1 in 12 */ + switch (q0) { + default: /* FALLTHRU */ + case 1: + iq[jz - 1] &= 0x7f; + break; + + case 2: + iq[jz - 1] &= 0x3f; + break; + } + } + + if (ih == 2) { /* compute the complementary of z */ + z = one - z; + + /* in case that iq[] does have a contribution, subtract the order of magnitude + of this contribution from the complement of z so that z + iq can be computed. */ + if (carry != 0) { + z -= scalbnf(one, (int32_t)q0); + /* Given the following decimal example of: z = 0.7 and iq = 0.01 for the angle z + iq = 0.71 + the complements would be z = 1 - z = 0.3 and iq = 0.1 - iq = 0.09 + now, z needs to be decremented by 0.1; z = z - 0.1 so that z + iq = 0.2 + 0.09 = 0.29 + which is the correct complement of the original angle 0.71 */ + } + } + } + + /* check if recomputation is needed in case of loss of significance in z and iq[] */ + if (z == zero) { + j = 0; + + for (i = jz - 1; i >= jk; i--) { + j |= iq[i]; + } + + if (j == 0) { /* need recomputation */ + for (k = 1; (jk - k >= 0) && (iq[jk - k] == 0); k++) { /* k = no. of terms needed */ + } + + /* add q[jz+1] to q[jz+k] + don't pull more terms of ipio2[] than available + and don't overflow f[] */ + for (i = jz + 1; i <= jz + k; i++) { + if ((jv + i < 66) && + (jx + i < 20)) { + f[jx + i] = (float) ipio2[jv + i]; + } else{ + exhausted = true; + } + + for (j = 0, fw = 0.0f; j <= jx; j++) { + fw += x[j] * f[jx + i - j]; + } + + q[i] = fw; + } + + jz += k; + recompute = true; + } + } + /* The original authors of the algorithm Payne and Hanek estimate the + amount of needed recomputing to be low. Currently only 2 recomputes + are observed at most */ + } while (recompute && !exhausted); + + /* chop off zero terms */ + if (z == 0.0f) { + q0 -= 8; + + for (jz -= 1; jz>=0; --jz) { + if (iq[jz]!=0) { + break; + } + q0 -= 8; + } + } else { /* break z into 8-bit if necessary */ + z = scalbnf(z, -(int32_t)q0); + + iq[jz] = (int32_t) z ; + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbnf(one, (int32_t)q0); + + for (i = jz; i >= 0; i--) { + q[i] = fw * (float)iq[i]; + fw *= twon8; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for (i = jz; i >= 0; i--) { + for (fw = 0.0f, k = 0; k <= jp && k <= jz - i; k++) { + fw += PIo2[k] * q[i + k]; + } + + fq[jz - i] = fw; + } + + /* compress fq[] into y[] */ + fw = 0.0f; + + for (i = jz; i >= 0; i--) { + fw += fq[i]; + } + + y[0] = (ih == 0) ? fw : -fw; + fw = fq[0] - fw; + + for (i = 1; i <= jz; i++) { + fw += fq[i]; + } + + y[1] = (ih == 0) ? fw : -fw; + + return n & 7; +} + +/* __rem_pio2f(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __rem_pio2f_internal() + */ + +/* + * invpio2: 24 bits of 2/pi + * pio2_1: first 17 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 17 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 17 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ + +static const float +half = 5.0000000000e-01f, /* 0x3f000000 */ +invpio2 = 6.3661980629e-01f, /* 0x3f22f984 */ +pio2_1 = 1.5707855225e+00f, /* 0x3fc90f80 */ +pio2_1t = 1.0804334124e-05f, /* 0x37354443 */ +pio2_2 = 1.0804273188e-05f, /* 0x37354400 */ +pio2_2t = 6.0770999344e-11f, /* 0x2e85a308 */ +pio2_3 = 6.0770943833e-11f, /* 0x2e85a300 */ +pio2_3t = 6.1232342629e-17f; /* 0x248d3132 */ + +int32_t __rem_pio2f(float x, float *y) +{ + float z, w, t, r, fn; + float tx[3]; + int32_t i, j, n, ix, hx; + int32_t e0, nx; + + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; + + if (ix <= 0x3f490fd8) { /* |x| ~<= pi/4 , no need for reduction */ + y[0] = x; + y[1] = 0; + return 0; + } + + if (ix < 0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */ + /* 17+17+24 bit pi has sufficient precision and best efficiency */ + if (hx > 0) { + z = x - pio2_1; + + if ((ix & 0xfffe0000U) != 0x3fc80000) { /* 17+24 bit pi OK */ + y[0] = z - pio2_1t; + y[1] = (z - y[0]) - pio2_1t; + } else { /* near pi/2, use 17+17+24 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z - y[0]) - pio2_2t; + } + + return 1; + } else { /* negative x */ + z = x + pio2_1; + + if ((ix & 0xfffe0000U) != 0x3fc80000) { /* 17+24 bit pi OK */ + y[0] = z + pio2_1t; + y[1] = (z - y[0]) + pio2_1t; + } else { /* near pi/2, use 17+17+24 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z - y[0]) + pio2_2t; + } + + return -1; + } + } + + if (ix <= 0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */ + t = fabsf(x); + n = (int32_t)(t * invpio2 + half); + fn = (float)n; + r = t - fn * pio2_1; + w = fn * pio2_1t; /* 1st round good to 40 bit */ + + { + uint32_t high; + j = ix >> 23; + y[0] = r - w; + GET_FLOAT_WORD(high, y[0]); + i = j - ((high >> 23) & 0xff); + + if (i > 8) { /* 2nd iteration needed, good to 57 */ + t = r; + w = fn * pio2_2; + r = t - w; + w = fn * pio2_2t - ((t - r) - w); + y[0] = r - w; + GET_FLOAT_WORD(high, y[0]); + i = j - ((high >> 23) & 0xff); + + if (i > 25) { /* 3rd iteration need, 74 bits acc */ + t = r; /* will cover all possible cases */ + w = fn * pio2_3; + r = t - w; + w = fn * pio2_3t - ((t - r) - w); + y[0] = r - w; + } + } + } + + y[1] = (r - y[0]) - w; + + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } else { + return n; + } + } + + /* + * all other (large) arguments + */ + if (!FLT_UWORD_IS_FINITE(ix)) { + if (isnan(x)) { + y[1] = x - x; + y[0] = y[1]; + } else { + y[1] = __raise_invalidf(); + y[0] = y[1]; + } + return 0; + } + + /* set z = scalbn(|x|,ilogb(x)-7) */ + e0 = (int32_t)((ix >> 23) - 134); /* e0 = ilogb(z)-7; */ + SET_FLOAT_WORD(z, ix - ((int32_t)e0 << 23)); + + for (i = 0; i < 2; i++) { + tx[i] = (float)((int32_t)(z)); + z = (z - tx[i]) * two8; + } + + tx[2] = z; + + for (nx = 3; nx>1; --nx) { /* skip zero term */ + if (tx[nx-1]!=zero) { + break; + } + } + + n = __rem_pio2f_internal(tx, y, e0, nx); + + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } + + return n; +} + +static const float +C1 = 0xaaaaa5.0p-28f, /* 0.04166664555668830871582031250, 0x3D2AAAA5 */ +C2 = -0xb60615.0p-33f, /* -0.001388731063343584537506103516, 0xBAB60615 */ +C3 = 0xccf47d.0p-39f; /* 0.00002443254288664320483803749084, 0x37CCF47C */ + +float __cosf(float x, float y) +{ + float hz, z, r, w; + + z = x * x; + r = z * (C1 + z * (C2 + z * C3)); + + hz = 0.5f * z; + w = one - hz; + return w + (((one - w) - hz) + (z * r - x * y)); +} + +static const float +S1 = -0xaaaaab.0p-26f, /* -0.16666667163, 0xBE2AAAAB */ +S2 = 0x8888bb.0p-30f, /* 0.0083333803341, 0x3C0888BB */ +S3 = -0xd02de1.0p-36f, /* -0.00019853517006, 0xB9502DE1 */ +S4 = 0xbe6dbe.0p-42f; /* 0.0000028376084629, 0x363E6DBE */ + +float __sinf(float x, float y, int iy) +{ + float z, r, v; + + z = x * x; + v = z * x; + r = S2 + z * (S3 + z * S4); + + if (iy == 0) { + return x + v * (S1 + z * r); + } else { + return x - ((z * (half * y - v * r) - y) - v * S1); + } +} diff --git a/libm/libmcs/libm/mathf/internal/trigf.h b/libm/libmcs/libm/mathf/internal/trigf.h new file mode 100644 index 00000000..8a1e5ef8 --- /dev/null +++ b/libm/libmcs/libm/mathf/internal/trigf.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#ifndef LIBMCS_TRIGF_H +#define LIBMCS_TRIGF_H + +#include "../../common/tools.h" + +extern float __sinf(float x, float y, int iy); +extern float __cosf(float x, float y); +extern int32_t __rem_pio2f(float x, float *y); + +#endif /* !LIBMCS_TRIGF_H */ diff --git a/libm/libmcs/libm/mathf/ldexpf.c b/libm/libmcs/libm/mathf/ldexpf.c new file mode 100644 index 00000000..0b9187ec --- /dev/null +++ b/libm/libmcs/libm/mathf/ldexpf.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include + +float ldexpf(float x, int exp) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + if ((isfinite(x) == 0) || x == 0.0f) { + return x + x; + } + + return scalbnf(x, exp); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double ldexp(double x, int exp) +{ + return (double) ldexpf((float) x, exp); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/lgammaf.c b/libm/libmcs/libm/mathf/lgammaf.c new file mode 100644 index 00000000..128b216c --- /dev/null +++ b/libm/libmcs/libm/mathf/lgammaf.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "internal/gammaf.h" + +float lgammaf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + return __lgammaf(x, &__signgam); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double lgamma(double x) +{ + return (double) lgammaf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/llrintf.c b/libm/libmcs/libm/mathf/llrintf.c new file mode 100644 index 00000000..e3e936fd --- /dev/null +++ b/libm/libmcs/libm/mathf/llrintf.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* lrint adapted to be llrint for Newlib, 2009 by Craig Howland. */ + +/* + * llrintf(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to llrintf(x). + */ + +#include +#include "../common/tools.h" + +static const float +/* Adding a float, x, to 2^23 will cause the result to be rounded based on + the fractional part of x, according to the implementation's current rounding + mode. 2^23 is the smallest float that can be represented using all 23 significant + digits. */ +TWO23[2] = { + 8.3886080000e+06f, /* 0x4b000000 */ + -8.3886080000e+06f, /* 0xcb000000 */ +}; + +long long int llrintf(float x) +{ + int32_t _j0, sx; + uint32_t _i0; + float t; + volatile float w; + long long int result; + + GET_FLOAT_WORD(_i0, x); + + /* Extract sign bit. */ + sx = (_i0 >> 31); + + /* Extract exponent field. */ + _j0 = ((_i0 & 0x7f800000) >> 23) - 127; + + if (_j0 < (int32_t)(sizeof(long long int) * 8) - 1) { + if (_j0 < -1) { + return 0; + } else if (_j0 >= 23) { + result = (long long int)((_i0 & 0x7fffff) | 0x800000) << (_j0 - 23); + } else { + w = TWO23[sx] + x; + t = w - TWO23[sx]; + GET_FLOAT_WORD(_i0, t); + + /* Detect the all-zeros representation of plus and + minus zero, which fails the calculation below. */ + if ((_i0 & ~((uint32_t)1 << 31)) == 0) { + return 0; + } + + _j0 = ((_i0 >> 23) & 0xff) - 0x7f; + _i0 &= 0x7fffff; + _i0 |= 0x800000; + result = _i0 >> (23 - _j0); + } + } else { + (void) __raise_invalidf(); + if (sx != 0) { + return __MIN_LONG_LONG; + } + else { + return __MAX_LONG_LONG; + } + } + + return (sx != 0) ? -result : result; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +long long int llrint(double x) +{ + return llrintf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/llroundf.c b/libm/libmcs/libm/mathf/llroundf.c new file mode 100644 index 00000000..9de17e1a --- /dev/null +++ b/libm/libmcs/libm/mathf/llroundf.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* lrint adapted to be llrint for Newlib, 2009 by Craig Howland. */ + +#include +#include "../common/tools.h" + +long long int llroundf(float x) +{ + int32_t exponent_less_127; + uint32_t w; + long long int result; + int32_t sign; + + GET_FLOAT_WORD(w, x); + exponent_less_127 = ((w & 0x7f800000) >> 23) - 127; + sign = (w & 0x80000000U) != 0 ? -1 : 1; + w &= 0x7fffff; + w |= 0x800000; + + if (exponent_less_127 < (int32_t)((8 * sizeof(long long int)) - 1)) { + if (exponent_less_127 < 0) { + return exponent_less_127 < -1 ? 0 : sign; + } else if (exponent_less_127 >= 23) { + result = (long long int) w << (exponent_less_127 - 23); + } else { + w += 0x400000 >> exponent_less_127; + result = w >> (23 - exponent_less_127); + } + } else { + (void) __raise_invalidf(); + if (sign == -1) { + return __MIN_LONG_LONG; + } + else { + return __MAX_LONG_LONG; + } + } + + return sign * result; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +long long int llround(double x) +{ + return llroundf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/log10f.c b/libm/libmcs/libm/mathf/log10f.c new file mode 100644 index 00000000..f50ce390 --- /dev/null +++ b/libm/libmcs/libm/mathf/log10f.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" +#include "internal/log1pmff.h" + +static const float +two25 = 3.3554432000e+07f, /* 0x4c000000 */ +ivln10hi = 4.3432617188e-01f, /* 0x3ede6000 */ +ivln10lo = -3.1689971365e-05f, /* 0xb804ead9 */ +log10_2hi = 3.0102920532e-01f, /* 0x3e9a2080 */ +log10_2lo = 7.9034151668e-07f; /* 0x355427db */ + +static const float zero = 0.0f; + +float log10f(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float f, hfsq, hi, lo, r, y; + int32_t i, k, hx; + + GET_FLOAT_WORD(hx, x); + + k = 0; + + if (FLT_UWORD_IS_ZERO(hx & 0x7fffffff)) { + return __raise_div_by_zerof(-1.0f); /* log(+-0)=-inf */ + } + + if (FLT_UWORD_IS_NAN(hx & 0x7fffffff)) { /* x = NaN */ + return x + x; + } + + if (hx < 0) { + return __raise_invalidf(); /* log(-#) = NaN */ + } + + if (FLT_UWORD_IS_INFINITE(hx)) { /* x = +Inf */ + return x + x; + } + + if (FLT_UWORD_IS_SUBNORMAL(hx)) { + k -= 25; + x *= two25; /* subnormal number, scale up x */ + GET_FLOAT_WORD(hx, x); + } + + if (hx == 0x3f800000) { /* log(1) = +0 */ + return zero; + } + + k += (hx >> 23) - 127; + hx &= 0x007fffff; + i = (hx + (0x4afb0d)) & 0x800000; + SET_FLOAT_WORD(x, hx | (i ^ 0x3f800000)); /* normalize x or x/2 */ + k += (i >> 23); + y = (float)k; + f = x - 1.0f; + hfsq = 0.5f * f * f; + r = __log1pmff(f); + hi = f - hfsq; + GET_FLOAT_WORD(hx, hi); + SET_FLOAT_WORD(hi, hx & 0xfffff000U); + lo = (f - hi) - hfsq + r; + return y * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + y * log10_2hi; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double log10(double x) +{ + return (double) log10f((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/log1pf.c b/libm/libmcs/libm/mathf/log1pf.c new file mode 100644 index 00000000..c0d6f113 --- /dev/null +++ b/libm/libmcs/libm/mathf/log1pf.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" +#include "internal/log1pmff.h" + +static const float +ln2_hi = 6.9313812256e-01f, /* 0x3f317180 */ +ln2_lo = 9.0580006145e-06f; /* 0x3717f7d1 */ + +static const float zero = 0.0f; + +float log1pf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float hfsq, f, c, R, u; + int32_t k, hx, hu, ax; + + c = NAN; /* initial value of c is never actually used */ + f = NAN; /* initial value of f is never actually used */ + hu = INT_MAX; /* initial value of hu is never actually used */ + + GET_FLOAT_WORD(hx, x); + ax = hx & 0x7fffffff; + + k = 1; + + if (!FLT_UWORD_IS_FINITE(hx)) { /* x = NaN/+Inf */ + return x + x; + } + + if (hx < 0x3ed413d7) { /* x < 0.41422 */ + if (ax >= 0x3f800000) { /* x <= -1.0 */ + if (FLT_UWORD_IS_NAN(ax)) { /* x = NaN */ + return x + x; + } else if (x == -1.0f) { + return __raise_div_by_zerof(-1.0f); /* log1p(-1)=-inf */ + } else { + return __raise_invalidf(); /* log1p(x<-1)=NaN */ + } + } + + if (ax < 0x31000000) { /* |x| < 2**-29 */ + if (ax < 0x24800000) { /* |x| < 2**-54 */ + return __raise_inexactf(x); + } else { + return __raise_inexactf(x - x * x * 0.5f); + } + } + + if (hx > 0 || hx <= ((int32_t)0xbe95f61fU)) { + k = 0; + f = x; + hu = 1; + } /* -0.2929> 23) - 127; + /* correction term */ + c = (k > 0) ? 1.0f - (u - x) : x - (u - 1.0f); + c /= u; + } else { + u = x; + GET_FLOAT_WORD(hu, u); + k = (hu >> 23) - 127; + c = 0; + } + + hu &= 0x007fffff; + + if (hu < 0x3504f7) { + SET_FLOAT_WORD(u, hu | 0x3f800000); /* normalize u */ + } else { + k += 1; + SET_FLOAT_WORD(u, hu | 0x3f000000); /* normalize u/2 */ + hu = (0x00800000 - hu) >> 2; + } + + f = u - 1.0f; + } + + hfsq = 0.5f * f * f; + + if (hu == 0) { /* |f| < 2**-20 */ + if (f == zero) { + c += k * ln2_lo; + return k * ln2_hi + c; + } + + R = hfsq * (1.0f - 0.66666666666666666f * f); + + return k * ln2_hi - ((R - (k * ln2_lo + c)) - f); + } + + if (k == 0) { + return f - (hfsq - __log1pmff(f)); + } else { + return k * ln2_hi - ((hfsq - (__log1pmff(f) + (k * ln2_lo + c))) - f); + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double log1p(double x) +{ + return (double) log1pf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/log2f.c b/libm/libmcs/libm/mathf/log2f.c new file mode 100644 index 00000000..0336d0b5 --- /dev/null +++ b/libm/libmcs/libm/mathf/log2f.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" +#include "internal/log1pmff.h" + +static const float +two25 = 3.3554432000e+07f, /* 0x4c000000 */ +ivln2hi = 1.4428710938e+00f, /* 0x3fb8b000 */ +ivln2lo = -1.7605285393e-04f; /* 0xb9389ad4 */ + +static const float zero = 0.0f; + +float log2f(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float f, hfsq, hi, lo, r, y; + int32_t i, k, hx; + + GET_FLOAT_WORD(hx, x); + + k = 0; + + if (FLT_UWORD_IS_ZERO(hx & 0x7fffffff)) { + return __raise_div_by_zerof(-1.0f); /* log(+-0)=-inf */ + } + + if (FLT_UWORD_IS_NAN(hx & 0x7fffffff)) { /* x = NaN */ + return x + x; + } + + if (hx < 0) { + return __raise_invalidf(); /* log(-#) = NaN */ + } + + if (FLT_UWORD_IS_INFINITE(hx)) { /* x = +Inf */ + return x + x; + } + + if (FLT_UWORD_IS_SUBNORMAL(hx)) { + k -= 25; + x *= two25; /* subnormal number, scale up x */ + GET_FLOAT_WORD(hx, x); + } + + if (hx == 0x3f800000) { /* log(1) = +0 */ + return zero; + } + + k += (hx >> 23) - 127; + hx &= 0x007fffff; + i = (hx + (0x4afb0d)) & 0x800000; + SET_FLOAT_WORD(x, hx | (i ^ 0x3f800000)); /* normalize x or x/2 */ + k += (i >> 23); + y = (float)k; + f = x - 1.0f; + hfsq = 0.5f * f * f; + r = __log1pmff(f); + hi = f - hfsq; + GET_FLOAT_WORD(hx, hi); + SET_FLOAT_WORD(hi, hx & 0xfffff000U); + lo = (f - hi) - hfsq + r; + return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + y; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double log2(double x) +{ + return (double) log2f((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/logbf.c b/libm/libmcs/libm/mathf/logbf.c new file mode 100644 index 00000000..25fe2ac2 --- /dev/null +++ b/libm/libmcs/libm/mathf/logbf.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +/* float logb(float x) + * return the binary exponent of non-zero x + * logbf(0) = -inf, raise divide-by-zero floating point exception + * logbf(+inf|-inf) = +inf (no signal is raised) + * logbf(NaN) = NaN (no signal is raised) + * Per C99 recommendation, a NaN argument is returned unchanged. + */ + +#include +#include "../common/tools.h" + +float logbf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, ix; + + GET_FLOAT_WORD(hx, x); + hx &= 0x7fffffff; + + if (FLT_UWORD_IS_ZERO(hx)) { + return __raise_div_by_zerof(-1.0f); /* logbf(0) = -inf */ + } + + if (FLT_UWORD_IS_SUBNORMAL(hx)) { + for (ix = -126, hx <<= 8; hx > 0; hx <<= 1) { + ix -= 1; + } + + return (float) ix; + } else if (!FLT_UWORD_IS_FINITE(hx)) { /* x = NaN/+-Inf */ + return x * x; + } else { + return (float)((hx >> 23) - 127); + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double logb(double x) +{ + return (double) logbf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/logf.c b/libm/libmcs/libm/mathf/logf.c new file mode 100644 index 00000000..51e33131 --- /dev/null +++ b/libm/libmcs/libm/mathf/logf.c @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +ln2_hi = 6.9313812256e-01f, /* 0x3f317180 */ +ln2_lo = 9.0580006145e-06f, /* 0x3717f7d1 */ +two25 = 3.355443200e+07f, /* 0x4c000000 */ +Lg1 = 6.6666668653e-01f, /* 0x3F2AAAAB */ +Lg2 = 4.0000000596e-01f, /* 0x3ECCCCCD */ +Lg3 = 2.8571429849e-01f, /* 0x3E924925 */ +Lg4 = 2.2222198546e-01f, /* 0x3E638E29 */ +Lg5 = 1.8183572590e-01f, /* 0x3E3A3325 */ +Lg6 = 1.5313838422e-01f, /* 0x3E1CD04F */ +Lg7 = 1.4798198640e-01f; /* 0x3E178897 */ + +static const float zero = 0.0f; + +float logf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float hfsq, f, s, z, R, w, t1, t2, dk; + int32_t k, ix, i, j; + + GET_FLOAT_WORD(ix, x); + + k = 0; + + if (FLT_UWORD_IS_ZERO(ix & 0x7fffffff)) { + return __raise_div_by_zerof(-1.0f); /* log(+-0)=-inf */ + } + + if (FLT_UWORD_IS_NAN(ix & 0x7fffffff)) { /* x = NaN */ + return x + x; + } + + if (ix < 0) { + return __raise_invalidf(); /* log(-#) = NaN */ + } + + if (FLT_UWORD_IS_INFINITE(ix)) { /* x = +Inf */ + return x + x; + } + + if (FLT_UWORD_IS_SUBNORMAL(ix)) { + k -= 25; + x *= two25; /* subnormal number, scale up x */ + GET_FLOAT_WORD(ix, x); + } + + k += (ix >> 23) - 127; + ix &= 0x007fffff; + i = (ix + (0x95f64 << 3)) & 0x800000; + SET_FLOAT_WORD(x, ix | (i ^ 0x3f800000)); /* normalize x or x/2 */ + k += (i >> 23); + f = x - 1.0f; + + if ((0x007fffff & (15 + ix)) < 16) { /* |f| < 2**-20 */ + if (f == zero) { + if (k == 0) { + return zero; + } else { + dk = (float)k; + return dk * ln2_hi + dk * ln2_lo; + } + } + + R = f * f * (0.5f - 0.33333333333333333f * f); + + if (k == 0) { + return f - R; + } else { + dk = (float)k; + return dk * ln2_hi - ((R - dk * ln2_lo) - f); + } + } + + s = f / (2.0f + f); + dk = (float)k; + z = s * s; + i = ix - (0x6147a << 3); + w = z * z; + j = (0x6b851 << 3) - ix; + t1 = w * (Lg2 + w * (Lg4 + w * Lg6)); + t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7))); + i |= j; + R = t2 + t1; + + if (i > 0) { + hfsq = 0.5f * f * f; + + if (k == 0) { + return f - (hfsq - s * (hfsq + R)); + } else { + return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f); + } + } else { + if (k == 0) { + return f - s * (f - R); + } else { + return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f); + } + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double log(double x) +{ + return (double) logf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/lrintf.c b/libm/libmcs/libm/mathf/lrintf.c new file mode 100644 index 00000000..f04abe43 --- /dev/null +++ b/libm/libmcs/libm/mathf/lrintf.c @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +/* + * lrintf(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to lrintf(x). + */ + +#include +#include "../common/tools.h" + +static const float +/* Adding a float, x, to 2^23 will cause the result to be rounded based on + the fractional part of x, according to the implementation's current rounding + mode. 2^23 is the smallest float that can be represented using all 23 significant + digits. */ +TWO23[2] = { + 8.3886080000e+06f, /* 0x4b000000 */ + -8.3886080000e+06f, /* 0xcb000000 */ +}; + +long int lrintf(float x) +{ + int32_t _j0, sx; + uint32_t _i0; + float t; + volatile float w; + long int result; + + GET_FLOAT_WORD(_i0, x); + + /* Extract sign bit. */ + sx = (_i0 >> 31); + + /* Extract exponent field. */ + _j0 = ((_i0 & 0x7f800000) >> 23) - 127; + + if (_j0 < (int32_t)(sizeof(long int) * 8) - 1) { + if (_j0 < -1) { + return 0; + } else if (_j0 >= 23) { + result = (long int)((_i0 & 0x7fffff) | 0x800000) << (_j0 - 23); + } else { + w = TWO23[sx] + x; + t = w - TWO23[sx]; + GET_FLOAT_WORD(_i0, t); + + /* Detect the all-zeros representation of plus and + minus zero, which fails the calculation below. */ + if ((_i0 & ~(1U << 31)) == 0) { + return 0; + } + + _j0 = ((_i0 >> 23) & 0xff) - 0x7f; + _i0 &= 0x7fffff; + _i0 |= 0x800000; + result = _i0 >> (23 - _j0); + } + } else { + (void) __raise_invalidf(); + if (sx != 0) { + return __MIN_LONG; + } + else { + return __MAX_LONG; + } + } + + return (sx != 0) ? -result : result; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +long int lrint(double x) +{ + return lrintf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/lroundf.c b/libm/libmcs/libm/mathf/lroundf.c new file mode 100644 index 00000000..f674a8cb --- /dev/null +++ b/libm/libmcs/libm/mathf/lroundf.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +#include +#include "../common/tools.h" + +long int lroundf(float x) +{ + int32_t exponent_less_127; + uint32_t w; + long int result; + int32_t sign; + + GET_FLOAT_WORD(w, x); + exponent_less_127 = ((w & 0x7f800000) >> 23) - 127; + sign = (w & 0x80000000U) != 0 ? -1 : 1; + w &= 0x7fffff; + w |= 0x800000; + + if (exponent_less_127 < (int32_t)((8 * sizeof(long int)) - 1)) { + if (exponent_less_127 < 0) { + return exponent_less_127 < -1 ? 0 : sign; + } else if (exponent_less_127 >= 23) { + result = (long int) w << (exponent_less_127 - 23); + } else { + w += 0x400000 >> exponent_less_127; + result = w >> (23 - exponent_less_127); + } + } else { + (void) __raise_invalidf(); + if (sign == -1) { + return __MIN_LONG; + } else { + return __MAX_LONG; + } + } + + return sign * result; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +long int lround(double x) +{ + return lroundf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/modff.c b/libm/libmcs/libm/mathf/modff.c new file mode 100644 index 00000000..b270a863 --- /dev/null +++ b/libm/libmcs/libm/mathf/modff.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include +#include "../common/tools.h" + +float modff(float x, float *iptr) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float _xi = 0.0f; + int32_t _i0, _j0; + uint32_t i; + + assert(iptr != (void*)0); + if(iptr == (void*)0) { + iptr = &_xi; + } + + GET_FLOAT_WORD(_i0, x); + _j0 = ((_i0 >> 23) & 0xff) - 0x7f; /* exponent of x */ + + if (_j0 < 23) { /* integer part in x */ + if (_j0 < 0) { /* |x|<1 */ + SET_FLOAT_WORD(*iptr, _i0 & 0x80000000U); /* *iptr = +-0 */ + return x; + } else { + i = (0x007fffff) >> _j0; + + if ((_i0 & i) == 0) { /* x is integral */ + *iptr = x; + SET_FLOAT_WORD(x, _i0 & 0x80000000U); /* return +-0 */ + return x; + } else { + SET_FLOAT_WORD(*iptr, _i0 & (~i)); + return x - *iptr; + } + } + } else { /* no fraction part */ + *iptr = x; + + if (isnan(x)) { + return *iptr = x + x; /* x is NaN, return NaN */ + } + + SET_FLOAT_WORD(x, _i0 & 0x80000000U); /* return +-0 */ + return x; + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double modf(double x, double *iptr) +{ + return (double) modff((float) x, (float *) iptr); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/nanf.c b/libm/libmcs/libm/mathf/nanf.c new file mode 100644 index 00000000..0814bc19 --- /dev/null +++ b/libm/libmcs/libm/mathf/nanf.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2025 by GTD GmbH. */ + +#include +#include "../common/tools.h" + +float nanf(const char *payload) +{ + (void)payload; + + float x; + SET_FLOAT_WORD(x,0x7FCF067D); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double nan(const char *payload) +{ + return (double) nanf(payload); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/nearbyintf.c b/libm/libmcs/libm/mathf/nearbyintf.c new file mode 100644 index 00000000..c6c26ad3 --- /dev/null +++ b/libm/libmcs/libm/mathf/nearbyintf.c @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +#include + +float nearbyintf(float x) +{ + return rintf(x); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double nearbyint(double x) +{ + return (double) nearbyintf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/nextafterf.c b/libm/libmcs/libm/mathf/nextafterf.c new file mode 100644 index 00000000..b72d7289 --- /dev/null +++ b/libm/libmcs/libm/mathf/nextafterf.c @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +float nextafterf(float x, float y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, hy, ix, iy; + + GET_FLOAT_WORD(hx, x); + GET_FLOAT_WORD(hy, y); + ix = hx & 0x7fffffff; /* |x| */ + iy = hy & 0x7fffffff; /* |y| */ + + if (FLT_UWORD_IS_NAN(ix) || FLT_UWORD_IS_NAN(iy)) { + return x + y; + } else if (hx == hy) { + return y; /* x == y, return y */ + } else if (ix == 0) { /* x == 0 */ + if (ix == iy) { + return y; /* x == y, return y */ + } +#ifdef __LIBMCS_FPU_DAZ + SET_FLOAT_WORD(x, (hy & 0x80000000U) | 0x00800000U); /* return +-minnormal */ +#else + SET_FLOAT_WORD(x, (hy & 0x80000000U) | 1U); /* return +-minsubnormal */ + (void) __raise_underflowf(x); +#endif /* defined(__LIBMCS_FPU_DAZ) */ + return x; + } else if (hx >= 0) { /* x > 0 */ + if (hx > hy) { /* x > y, x -= ulp */ + hx -= 1; + } else { /* x < y, x += ulp */ + hx += 1; + } + } else { /* x < 0 */ + if (hy >= 0 || hx > hy) { /* x < y, x -= ulp */ + hx -= 1; + } else { /* x > y, x += ulp */ + hx += 1; + } + } + + hy = hx & 0x7f800000; + + if (hy > FLT_UWORD_MAX) { + return __raise_overflowf(x); /* overflow if x is finite */ + } + + if (hy < 0x00800000) { /* underflow */ +#ifdef __LIBMCS_FPU_DAZ + SET_FLOAT_WORD(x, hx & 0x80000000U); /* return +-0.0 */ + return x; +#else + (void) __raise_underflowf(x); +#endif /* defined(__LIBMCS_FPU_DAZ) */ + } + + SET_FLOAT_WORD(x, hx); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double nextafter(double x, double y) +{ + return (double) nextafterf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/nexttowardf.c b/libm/libmcs/libm/mathf/nexttowardf.c new file mode 100644 index 00000000..ad4bcecd --- /dev/null +++ b/libm/libmcs/libm/mathf/nexttowardf.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: RichFelker */ +/* Copyright © 2005-2014 Rich Felker, et al. */ + +#include +#include "../common/tools.h" + +#ifdef __LIBMCS_LONG_DOUBLE_IS_64BITS + +union fshape { + float value; + uint32_t bits; +}; + +float nexttowardf(float x, long double y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= (long double)__volatile_one; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + union fshape ux; + uint32_t e; + + if (isnan(x) || isnan(y)) { + return x + y; + } + + if (x == y) { + return y; + } + + ux.value = x; + + if (x == 0) { +#ifdef __LIBMCS_FPU_DAZ + ux.bits = 0x00800000U; /* return +-minnormal */ +#else + ux.bits = 1U; /* return +-minsubnormal */ +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + if (signbit(y) != 0) { + ux.bits |= 0x80000000U; + } + } else if (x < y) { + if (signbit(x) != 0) { + ux.bits--; + } else { + ux.bits++; + } + } else { + if (signbit(x) != 0) { + ux.bits++; + } else { + ux.bits--; + } + } + + e = ux.bits & 0x7f800000; + + /* raise overflow if ux.value is infinite and x is finite */ + if (e == 0x7f800000) { + return __raise_overflowf(x); + } + + /* raise underflow if ux.value is subnormal or zero */ + if (e == 0) { +#ifdef __LIBMCS_FPU_DAZ + ux.bits = 0U; /* return +-0.0 */ + + if (signbit(x) != 0) { + ux.bits |= 0x80000000U; + } +#else + (void) __raise_underflowf(x); +#endif /* defined(__LIBMCS_FPU_DAZ) */ + } + + return ux.value; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double nexttoward(double x, long double y) +{ + return (double) nexttowardf((float) x, y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ + +#endif /* __LIBMCS_LONG_DOUBLE_IS_64BITS */ diff --git a/libm/libmcs/libm/mathf/powf.c b/libm/libmcs/libm/mathf/powf.c new file mode 100644 index 00000000..45831ef7 --- /dev/null +++ b/libm/libmcs/libm/mathf/powf.c @@ -0,0 +1,339 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +bp[] = { 1.0f, 1.5f}, +dp_h[] = { 0.0f, 5.84960938e-01f}, /* 0x3f15c000 */ +dp_l[] = { 0.0f, 1.56322085e-06f}, /* 0x35d1cfdc */ +zero = 0.0f, +one = 1.0f, +two = 2.0f, +two24 = 16777216.0f, /* 0x4b800000 */ +/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 6.0000002384e-01f, /* 0x3f19999a */ +L2 = 4.2857143283e-01f, /* 0x3edb6db7 */ +L3 = 3.3333334327e-01f, /* 0x3eaaaaab */ +L4 = 2.7272811532e-01f, /* 0x3e8ba305 */ +L5 = 2.3066075146e-01f, /* 0x3e6c3255 */ +L6 = 2.0697501302e-01f, /* 0x3e53f142 */ +P1 = 1.6666667163e-01f, /* 0x3e2aaaab */ +P2 = -2.7777778450e-03f, /* 0xbb360b61 */ +P3 = 6.6137559770e-05f, /* 0x388ab355 */ +P4 = -1.6533901999e-06f, /* 0xb5ddea0e */ +P5 = 4.1381369442e-08f, /* 0x3331bb4c */ +lg2 = 6.9314718246e-01f, /* 0x3f317218 */ +lg2_h = 6.93145752e-01f, /* 0x3f317200 */ +lg2_l = 1.42860654e-06f, /* 0x35bfbe8c */ +ovt = 4.2995665694e-08f, /* -(128-log2(ovfl+.5ulp)) */ +cp = 9.6179670095e-01f, /* 0x3f76384f =2/(3ln2) */ +cp_h = 9.6191406250e-01f, /* 0x3f764000 =12b of cp */ +cp_l = -1.1736857402e-04f, /* 0xb8f623c6 =tail of cp_h */ +ivln2 = 1.4426950216e+00f, /* 0x3fb8aa3b =1/ln2 */ +ivln2_h = 1.4426879883e+00f, /* 0x3fb8aa00 =16b 1/ln2*/ +ivln2_l = 7.0526075433e-06f; /* 0x36eca570 =1/ln2 tail*/ + +float powf(float x, float y) +{ + float z, ax, z_h, z_l, p_h, p_l; + float _y1, t1, t2, r, s, t, u, v, w; + int32_t i, j, k, yisint, n; + int32_t hx, hy, ix, iy, is; + + GET_FLOAT_WORD(hx, x); + GET_FLOAT_WORD(hy, y); + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + + /* y==zero: x**0 = 1 */ + if (FLT_UWORD_IS_ZERO(iy)) { + if (__issignalingf(x) != 0) { + return x + y; + } + + return one; + } + + /* x|y==NaN return NaN unless x==1 then return 1 */ + if (FLT_UWORD_IS_NAN(ix) || FLT_UWORD_IS_NAN(iy)) { + if (hx == 0x3f800000 && __issignalingf(y) == 0) { + return one; + } else { + return x + y; + } + } + +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; + + GET_FLOAT_WORD(hx, x); + GET_FLOAT_WORD(hy, y); + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + + if (hx < 0) { + if (iy >= 0x4b800000) { + yisint = 2; /* even integer y */ + } else if (iy >= 0x3f800000) { + k = (iy >> 23) - 0x7f; /* exponent */ + j = iy >> (23 - k); + + if ((j << (23 - k)) == iy) { + yisint = 2 - (j & 1); + } + } else { + /* No action required */ + } + } + + /* special value of y */ + if (FLT_UWORD_IS_INFINITE(iy)) { /* y is +-inf */ + if (ix == 0x3f800000) { + return one; /* +-1**+-inf = 1 */ + } else if (ix > 0x3f800000) { /* (|x|>1)**+-inf = inf,0 */ + return (hy >= 0) ? y : zero; + } else { /* (|x|<1)**-,+inf = inf,0 */ + return (hy < 0) ? -y : zero; + } + } + + if (iy == 0x3f800000) { /* y is +-1 */ + if (hy < 0) { + return one / x; + } else { + return x; + } + } + + if (hy == 0x40000000) { + return x * x; /* y is 2 */ + } + + if (hy == 0x3f000000) { /* y is 0.5 */ + if (hx >= 0) { /* x >= +0 */ + return sqrtf(x); + } + } + + ax = fabsf(x); + + /* special value of x */ + if (FLT_UWORD_IS_INFINITE(ix) || FLT_UWORD_IS_ZERO(ix) || ix == 0x3f800000) { + z = ax; /*x is +-0,+-inf,+-1*/ + + if (hy < 0) { /* z = (1/|x|) */ + if (FLT_UWORD_IS_INFINITE(ix)) { + z = zero; + } else if (FLT_UWORD_IS_ZERO(ix)) { + z = __raise_div_by_zerof(z); + } else { + /* No action required */ + } + } + + if (hx < 0) { + if (((ix - 0x3f800000) | yisint) == 0) { + z = __raise_invalidf(); /* (-1)**non-int is NaN */ + } else if (yisint == 1) { + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } else { + /* No action required */ + } + } + + return z; + } + + /* (x<0)**(non-int) is NaN */ + if (((((uint32_t)hx >> 31U) - 1U) | (uint32_t)yisint) == 0) { + return __raise_invalidf(); + } + + /* |y| is huge */ + if (iy > 0x4d000000) { /* if |y| > 2**27 */ + /* over/underflow if x is not close to one */ + /* Contrary to the double procedure we don't need the sign for these over/underflows as |y| > 2**27 means that y is an even integer (should the border ever be lowered to 2**23 or lower, the sign plays a role). */ + if (ix < 0x3f7ffff4) { + return (hy < 0) ? __raise_overflowf(one) : __raise_underflowf(one); + } + + if (ix > 0x3f800007) { + return (hy > 0) ? __raise_overflowf(one) : __raise_underflowf(one); + } + + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = ax - 1; /* t has 20 trailing zeros */ + w = (t * t) * (0.5f - t * (0.333333333333f - t * 0.25f)); + u = ivln2_h * t; /* ivln2_h has 16 sig. bits */ + v = t * ivln2_l - w * ivln2; + t1 = u + v; + GET_FLOAT_WORD(is, t1); + SET_FLOAT_WORD(t1, is & 0xfffff000U); + t2 = v - (t1 - u); + } else { + float s2, s_h, s_l, t_h, t_l; + n = 0; + + /* take care subnormal number */ + if (FLT_UWORD_IS_SUBNORMAL(ix)) { + ax *= two24; + n -= 24; + GET_FLOAT_WORD(ix, ax); + } + + n += ((ix) >> 23) - 0x7f; + j = ix & 0x007fffff; + /* determine interval */ + ix = j | 0x3f800000; /* normalize ix */ + + if (j <= 0x1cc471) { + k = 0; /* |x|> 1) & 0xfffff000U) | 0x20000000; + SET_FLOAT_WORD(t_h, is + 0x00400000 + (k << 21)); + t_l = ax - (t_h - bp[k]); + s_l = v * ((u - s_h * t_h) - s_h * t_l); + /* compute log(ax) */ + s2 = s * s; + r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); + r += s_l * (s_h + s); + s2 = s_h * s_h; + t_h = 3.0f + s2 + r; + GET_FLOAT_WORD(is, t_h); + SET_FLOAT_WORD(t_h, is & 0xfffff000U); + t_l = r - ((t_h - 3.0f) - s2); + /* u+v = s*(1+...) */ + u = s_h * t_h; + v = s_l * t_h + t_l * s; + /* 2/(3log2)*(s+...) */ + p_h = u + v; + GET_FLOAT_WORD(is, p_h); + SET_FLOAT_WORD(p_h, is & 0xfffff000U); + p_l = v - (p_h - u); + z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l * p_h + p_l * cp + dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (float)n; + t1 = (((z_h + z_l) + dp_h[k]) + t); + GET_FLOAT_WORD(is, t1); + SET_FLOAT_WORD(t1, is & 0xfffff000U); + t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + + if (((((uint32_t)hx >> 31U) - 1U) | (uint32_t)(yisint - 1)) == 0) { + s = -one; /* (-ve)**(odd int) */ + } + + /* split up y into _y1+y2 and compute (_y1+y2)*(t1+t2) */ + GET_FLOAT_WORD(is, y); + SET_FLOAT_WORD(_y1, is & 0xfffff000U); + p_l = (y - _y1) * t1 + y * t2; + p_h = _y1 * t1; + z = p_l + p_h; + GET_FLOAT_WORD(j, z); + i = j & 0x7fffffff; + + if (j > 0) { + if (i > FLT_UWORD_EXP_MAX) { + return __raise_overflowf(s); /* overflow */ + } else if (i == FLT_UWORD_EXP_MAX) { + if (p_l + ovt > z - p_h) { + return __raise_overflowf(s); /* overflow */ + } + } else { + /* No action required */ + } + } else { + if (i > FLT_UWORD_EXP_MIN) { + return __raise_underflowf(s); /* underflow */ + } else if (i == FLT_UWORD_EXP_MIN) { + if (p_l <= z - p_h) { + return __raise_underflowf(s); /* underflow */ + } + } else { + /* No action required */ + } + } + + /* + * compute 2**(p_h+p_l) + */ + k = (i >> 23) - 0x7f; + n = 0; + + if (i > 0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j + (0x00800000 >> (k + 1)); + k = ((n & 0x7fffffff) >> 23) - 0x7f; /* new k for n */ + SET_FLOAT_WORD(t, n & ~(0x007fffff >> k)); + n = ((n & 0x007fffff) | 0x00800000) >> (23 - k); + + if (j < 0) { + n = -n; + } + + p_h -= t; + } + + t = p_l + p_h; + GET_FLOAT_WORD(is, t); + SET_FLOAT_WORD(t, is & 0xffff8000U); + u = t * lg2_h; + v = (p_l - (t - p_h)) * lg2 + t * lg2_l; + z = u + v; + w = v - (z - u); + t = z * z; + t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + r = (z * t1) / (t1 - two) - (w + z * w); + z = one - (r - z); + GET_FLOAT_WORD(j, z); + j += (n << 23); + + if ((j >> 23) <= 0) { + z = scalbnf(z, (int32_t)n); /* subnormal output */ + } else { + SET_FLOAT_WORD(z, j); + } + + return s * z; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double pow(double x, double y) +{ + return (double) powf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/remainderf.c b/libm/libmcs/libm/mathf/remainderf.c new file mode 100644 index 00000000..6d149b0a --- /dev/null +++ b/libm/libmcs/libm/mathf/remainderf.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float zero = 0.0f; + +float remainderf(float x, float y) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t hx, hy; + uint32_t sx; + float y_half; + + GET_FLOAT_WORD(hx, x); + GET_FLOAT_WORD(hy, y); + sx = hx & 0x80000000U; + hy &= 0x7fffffff; + hx &= 0x7fffffff; + + /* purge off exception values */ + if (FLT_UWORD_IS_NAN(hx) || FLT_UWORD_IS_NAN(hy)) { /* x or y is NaN */ + return x + y; + } else if (FLT_UWORD_IS_ZERO(hy) || FLT_UWORD_IS_INFINITE(hx)) { /* y is 0 or x is inf */ + return __raise_invalidf(); + } else { + /* No action required */ + } + + if (hy <= FLT_UWORD_HALF_MAX) { + x = fmodf(x, 2 * y); /* now x < 2y */ + } + + if ((hx - hy) == 0) { + return zero * x; + } + + x = fabsf(x); + y = fabsf(y); + + if (hy < 0x01000000) { + if (x + x > y) { + x -= y; + + if (x + x >= y) { + x -= y; + } + } + } else { + y_half = 0.5f * y; + + if (x > y_half) { + x -= y; + + if (x >= y_half) { + x -= y; + } + } + } + + GET_FLOAT_WORD(hx, x); + SET_FLOAT_WORD(x, hx ^ sx); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double remainder(double x, double y) +{ + return (double) remainderf((float) x, (float) y); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/remquof.c b/libm/libmcs/libm/mathf/remquof.c new file mode 100644 index 00000000..85b46772 --- /dev/null +++ b/libm/libmcs/libm/mathf/remquof.c @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +#include +#include +#include "../common/tools.h" + +static const float zero = 0.0f; + +float remquof(float x, float y, int *quo) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; + y *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int _quo = 0; + int32_t hx, hy; + uint32_t sx, sq; + float y_half; + + assert(quo != (void*)0); + if(quo == (void*)0) { + quo = &_quo; + } + *quo = 0; + + GET_FLOAT_WORD(hx, x); + GET_FLOAT_WORD(hy, y); + sx = hx & 0x80000000U; + sq = sx ^ (hy & 0x80000000U); + hy &= 0x7fffffff; + hx &= 0x7fffffff; + + /* purge off exception values */ + if (FLT_UWORD_IS_NAN(hx) || FLT_UWORD_IS_NAN(hy)) { /* x or y is NaN */ + return x + y; + } else if (FLT_UWORD_IS_ZERO(hy) || FLT_UWORD_IS_INFINITE(hx)) { /* y is 0 or x is inf */ + return __raise_invalidf(); + } else { + /* No action required */ + } + + if (hy <= 0x7dffffff) { + x = fmodf(x, 8 * y); /* now x < 8y */ + } + + if ((hx - hy) == 0) { + *quo = sq ? -1 : 1; + return zero * x; + } + + x = fabsf(x); + y = fabsf(y); + _quo = 0; + + if (x >= 4 * y) { + x -= 4 * y; + _quo += 4; + } + if (x >= 2 * y) { + x -= 2 * y; + _quo += 2; + } + + if (hy < 0x01000000) { + if (x + x > y) { + x -= y; + _quo++; + + if (x + x >= y) { + x -= y; + _quo++; + } + } + } else { + y_half = 0.5f * y; + + if (x > y_half) { + x -= y; + _quo++; + + if (x >= y_half) { + x -= y; + _quo++; + } + } + } + + _quo &= 0x7; + + *quo = sq ? -_quo : _quo; + + GET_FLOAT_WORD(hx, x); + SET_FLOAT_WORD(x, hx ^ sx); + return x; +} diff --git a/libm/libmcs/libm/mathf/rintf.c b/libm/libmcs/libm/mathf/rintf.c new file mode 100644 index 00000000..d804f9ef --- /dev/null +++ b/libm/libmcs/libm/mathf/rintf.c @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +#include +#include "../common/tools.h" + +static const float +TWO23[2] = { + 8.3886080000e+06f, /* 0x4b000000 */ + -8.3886080000e+06f, /* 0xcb000000 */ +}; + +float rintf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t _i0, _j0, sx; + uint32_t i, _i1, ix; + float t; + volatile float w; + + GET_FLOAT_WORD(_i0, x); + sx = (_i0 >> 31) & 1; + ix = (_i0 & 0x7fffffff); + _j0 = (ix >> 23) - 0x7f; + + if (_j0 < 23) { + if (FLT_UWORD_IS_ZERO(ix)) { + return x; + } + + if (_j0 < 0) { + _i1 = (_i0 & 0x07fffff); + _i0 &= 0xfff00000U; + _i0 |= ((_i1 | -_i1) >> 9) & 0x400000; + SET_FLOAT_WORD(x, _i0); + w = TWO23[sx] + x; + t = w - TWO23[sx]; + GET_FLOAT_WORD(_i0, t); + SET_FLOAT_WORD(t, (_i0 & 0x7fffffff) | (sx << 31)); + return t; + } else { + i = (0x007fffff) >> _j0; + + if ((_i0 & i) == 0) { + return x; /* x is integral */ + } + + i >>= 1; + + if ((_i0 & i) != 0) { + _i0 = (_i0 & (~i)) | ((0x200000) >> _j0); + } + } + } else { + if (!FLT_UWORD_IS_FINITE(ix)) { + return x + x; /* inf or NaN */ + } else { + return x; /* x is integral */ + } + } + + SET_FLOAT_WORD(x, _i0); + w = TWO23[sx] + x; + return w - TWO23[sx]; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double rint(double x) +{ + return (double) rintf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/roundf.c b/libm/libmcs/libm/mathf/roundf.c new file mode 100644 index 00000000..d1ba9db4 --- /dev/null +++ b/libm/libmcs/libm/mathf/roundf.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +#include +#include "../common/tools.h" + +float roundf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + uint32_t w; + /* Most significant word, least significant word. */ + int32_t exponent_less_127; + + GET_FLOAT_WORD(w, x); + + /* Extract exponent field. */ + exponent_less_127 = (int32_t)((w & 0x7f800000) >> 23) - 127; + + if (exponent_less_127 < 23) { + if (exponent_less_127 < 0) { + w &= 0x80000000U; + + if (exponent_less_127 == -1) { + /* Result is +1.0 or -1.0. */ + + w |= ((uint32_t)127 << 23); + } + } else { + uint32_t exponent_mask = 0x007fffff >> exponent_less_127; + + if ((w & exponent_mask) == 0) { + /* x has an integral value. */ + + return x; + } + + w += 0x00400000 >> exponent_less_127; + w &= ~exponent_mask; + } + } else { + if (exponent_less_127 == 128) { + /* x is NaN or infinite. */ + + return x + x; + } else { + return x; + } + } + + SET_FLOAT_WORD(x, w); + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double round(double x) +{ + return (double) roundf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/scalblnf.c b/libm/libmcs/libm/mathf/scalblnf.c new file mode 100644 index 00000000..a02634ef --- /dev/null +++ b/libm/libmcs/libm/mathf/scalblnf.c @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float +two25 = 3.355443200e+07f, /* 0x4c000000 */ +twom25 = 2.9802322388e-08f; /* 0x33000000 */ + +float scalblnf(float x, long int n) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t k, ix; + GET_FLOAT_WORD(ix, x); + k = (ix & 0x7f800000) >> 23; /* extract exponent */ + + if (k == 0) { /* 0 or subnormal x */ + if ((ix & 0x7fffffff) == 0) { + return x; /* +-0 */ + } + + x *= two25; + GET_FLOAT_WORD(ix, x); + k = ((ix & 0x7f800000) >> 23) - 25; + } + + if (k == 0xff) { + return x + x; /* NaN or Inf */ + } + + if (n > 50000) { + return __raise_overflowf(x); /*overflow*/ + } + + k = k + n; + + if (k > 0xfe) { + return __raise_overflowf(x); /*overflow*/ + } + + if (n < -50000) { + return __raise_underflowf(x); /*underflow*/ + } + + if (k > 0) { /* normal result */ + SET_FLOAT_WORD(x, (ix & 0x807fffffU) | (k << 23U)); + return x; + } + + if (k <= -25) { + return __raise_underflowf(x); /*underflow*/ + } + + k += 25; /* subnormal result */ + SET_FLOAT_WORD(x, (ix & 0x807fffffU) | (k << 23U)); + return x * twom25; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double scalbln(double x, long int n) +{ + return (double) scalblnf((float) x, n); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/scalbnf.c b/libm/libmcs/libm/mathf/scalbnf.c new file mode 100644 index 00000000..8331f1fd --- /dev/null +++ b/libm/libmcs/libm/mathf/scalbnf.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +#if INT_MAX > 50000 + #define OVERFLOW_INT 50000 +#else + #define OVERFLOW_INT 30000 +#endif + +static const float +two25 = 3.355443200e+07f, /* 0x4c000000 */ +twom25 = 2.9802322388e-08f; /* 0x33000000 */ + +float scalbnf(float x, int n) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t k, ix; + uint32_t hx; + + GET_FLOAT_WORD(ix, x); + hx = ix & 0x7fffffff; + k = hx >> 23; /* extract exponent */ + + if (FLT_UWORD_IS_ZERO(hx)) { + return x; + } + + if (!FLT_UWORD_IS_FINITE(hx)) { + return x + x; /* NaN or Inf */ + } + + if (FLT_UWORD_IS_SUBNORMAL(hx)) { + x *= two25; + GET_FLOAT_WORD(ix, x); + k = ((ix & 0x7f800000) >> 23) - 25; + + if (n < -50000) { + return __raise_underflowf(x); /*underflow*/ + } + } + + if (n > OVERFLOW_INT) { + return __raise_overflowf(x); /*overflow */ + } + + k = k + n; + + if (k > FLT_LARGEST_EXP) { + return __raise_overflowf(x); /*overflow */ + } + + if (k > 0) { /* normal result */ + SET_FLOAT_WORD(x, (ix & 0x807fffffU) | (k << 23U)); + return x; + } + + if (k < FLT_SMALLEST_EXP) { + return __raise_underflowf(x); /*underflow*/ + } + + k += 25; /* subnormal result */ + SET_FLOAT_WORD(x, (ix & 0x807fffffU) | (k << 23U)); + return x * twom25; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double scalbn(double x, int n) +{ + return (double) scalbnf((float) x, n); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/sinf.c b/libm/libmcs/libm/mathf/sinf.c new file mode 100644 index 00000000..be6cc23a --- /dev/null +++ b/libm/libmcs/libm/mathf/sinf.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" +#include "internal/trigf.h" + +float sinf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float y[2], z = 0.0f; + int32_t n, ix; + + GET_FLOAT_WORD(ix, x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + + if (ix <= 0x3f490fd8) { + if(ix < 0x39800000) { /* if x < 2**-12 */ + if (FLT_UWORD_IS_ZERO(ix)) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexactf(x); + } + } + return __sinf(x, z, 0); + } + + /* sin(Inf or NaN) is NaN */ + else if (!FLT_UWORD_IS_FINITE(ix)) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalidf(); + } + } + + /* argument reduction needed */ + else { + n = __rem_pio2f(x, y); + + switch (n & 3) { + case 0: + return __sinf(y[0], y[1], 1); + + case 1: + return __cosf(y[0], y[1]); + + case 2: + return -__sinf(y[0], y[1], 1); + + default: + return -__cosf(y[0], y[1]); + } + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double sin(double x) +{ + return (double) sinf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/sinhf.c b/libm/libmcs/libm/mathf/sinhf.c new file mode 100644 index 00000000..8193ab2c --- /dev/null +++ b/libm/libmcs/libm/mathf/sinhf.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float one = 1.0f; + +float sinhf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float t, w, h; + int32_t ix, jx; + + GET_FLOAT_WORD(jx, x); + ix = jx & 0x7fffffff; + + /* x is INF or NaN */ + if (!FLT_UWORD_IS_FINITE(ix)) { + return x + x; + } + + h = 0.5f; + + if (jx < 0) { + h = -h; + } + + /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ + if (ix < 0x41b00000) { /* |x|<22 */ + if (ix < 0x31800000) { /* |x|<2**-28 */ + if (FLT_UWORD_IS_ZERO(ix)) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexactf(x); + } + } + + t = expm1f(fabsf(x)); + + if (ix < 0x3f800000) { + return h * (2.0f * t - t * t / (t + one)); + } + + return h * (t + t / (t + one)); + } + + /* |x| in [22, log(maxfloat)] return 0.5*exp(|x|) */ + if (ix <= FLT_UWORD_LOG_MAX) { + return h * expf(fabsf(x)); + } + + /* |x| in [log(maxfloat), overflowthresold] */ + if (ix <= FLT_UWORD_LOG_2MAX) { + w = expf(0.5f * fabsf(x)); + t = h * w; + return t * w; + } + + /* |x| > overflowthresold, sinh(x) overflow */ + return __raise_overflowf(x); +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double sinh(double x) +{ + return (double) sinhf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/sqrtf.c b/libm/libmcs/libm/mathf/sqrtf.c new file mode 100644 index 00000000..ea638e40 --- /dev/null +++ b/libm/libmcs/libm/mathf/sqrtf.c @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +float sqrtf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float z; + uint32_t r, hx; + int32_t ix, s, q, m, t, i; + + GET_FLOAT_WORD(ix, x); + hx = ix & 0x7fffffff; + + /* take care of Inf and NaN */ + if (!FLT_UWORD_IS_FINITE(hx)) { + if (FLT_UWORD_IS_NAN(hx)) { /* sqrt(NaN)=NaN */ + return x + x; + } else if (ix > 0) { /* sqrt(+inf)=+inf */ + return x; + } else { /* sqrt(-inf)=sNaN */ + return __raise_invalidf(); + } + } + + /* take care of zero and -ves */ + if (FLT_UWORD_IS_ZERO(hx)) { + return x; /* sqrt(+-0) = +-0 */ + } + + if (ix < 0) { + return __raise_invalidf(); /* sqrt(-ve) = sNaN */ + } + + /* normalize x */ + m = (ix >> 23); + + if (FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal x */ + for (i = 0; (ix & 0x00800000) == 0; i++) { + ix <<= 1; + } + + m -= i - 1; + } + + m -= 127; /* unbias exponent */ + ix = (ix & 0x007fffff) | 0x00800000; + + if (0 < (m & 1)) { /* odd m, double x to make it even */ + ix += ix; + } + + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix += ix; + q = s = 0; /* q = sqrt(x) */ + r = 0x01000000; /* r = moving bit from right to left */ + + while (r != 0) { + t = s + r; + + if (t <= ix) { + s = t + r; + ix -= t; + q += r; + } + + ix += ix; + r >>= 1; + } + + if (ix != 0) { + (void) __raise_inexactf(x); + q += (q & 1); + } + + ix = (q >> 1) + 0x3f000000; + ix += (m << 23); + SET_FLOAT_WORD(z, ix); + return z; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double sqrt(double x) +{ + return (double) sqrtf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/tanf.c b/libm/libmcs/libm/mathf/tanf.c new file mode 100644 index 00000000..b91e188a --- /dev/null +++ b/libm/libmcs/libm/mathf/tanf.c @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" +#include "internal/trigf.h" + +static const float +pio4 = 7.8539812565e-01f, /* 0x3f490fda */ +pio4lo = 3.7748947079e-08f, /* 0x33222168 */ +T[] = { + 3.3333334327e-01f, /* 0x3eaaaaab */ + 1.3333334029e-01f, /* 0x3e088889 */ + 5.3968254477e-02f, /* 0x3d5d0dd1 */ + 2.1869488060e-02f, /* 0x3cb327a4 */ + 8.8632395491e-03f, /* 0x3c11371f */ + 3.5920790397e-03f, /* 0x3b6b6916 */ + 1.4562094584e-03f, /* 0x3abede48 */ + 5.8804126456e-04f, /* 0x3a1a26c8 */ + 2.4646313977e-04f, /* 0x398137b9 */ + 7.8179444245e-05f, /* 0x38a3f445 */ + 7.1407252108e-05f, /* 0x3895c07a */ + -1.8558637748e-05f, /* 0xb79bae5f */ + 2.5907305826e-05f, /* 0x37d95384 */ +}; + +static inline float __tanf(float x, float y, int iy) +{ + float z, r, v, w, s; + int32_t ix, hx; + + GET_FLOAT_WORD(hx, x); + ix = hx & 0x7fffffff; /* high word of |x| */ + + if (ix >= 0x3f2ca140) { /* |x|>=0.6744 */ + if (hx < 0) { + x = -x; + y = -y; + } + + z = pio4 - x; + w = pio4lo - y; + x = z + w; + y = 0.0f; + } + + z = x * x; + w = z * z; + /* Break x^5*(T[1]+x^2*T[2]+...) into + * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) + */ + r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11])))); + v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12]))))); + s = z * x; + r = y + z * (s * (r + v) + y); + r += T[0] * s; + w = x + r; + + if (ix >= 0x3f2ca140) { + v = (float)iy; + return (float)(1 - ((hx >> 30) & 2)) * (v - 2.0f * (x - (w * w / (w + v) - r))); + } + + if (iy == 1) { + return w; + } else { + /* if allow error up to 2 ulp, simply return -1.0/(x+r) here */ + /* compute -1.0/(x+r) accurately */ + float a, t; + int32_t i; + z = w; + GET_FLOAT_WORD(i, z); + SET_FLOAT_WORD(z, i & 0xfffff000U); + v = r - (z - x); /* z+v = r+x */ + t = a = -1.0f / w; /* a = -1.0/w */ + GET_FLOAT_WORD(i, t); + SET_FLOAT_WORD(t, i & 0xfffff000U); + s = 1.0f + t * z; + return t + a * (s + t * v); + } +} + +float tanf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float y[2], z = 0.0; + int32_t n, ix; + + GET_FLOAT_WORD(ix, x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + + if (ix <= 0x3f490fda) { + if(ix < 0x39800000) { /* |x| < 2**-12 */ + if (FLT_UWORD_IS_ZERO(ix)) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexactf(x); + } + } + return __tanf(x, z, 1); + } + + /* tan(Inf or NaN) is NaN */ + else if (!FLT_UWORD_IS_FINITE(ix)) { + if (isnan(x)) { + return x + x; + } else { + return __raise_invalidf(); + } + } + + /* argument reduction needed */ + else { + n = __rem_pio2f(x, y); + return __tanf(y[0], y[1], 1 - ((n & 1) << 1)); /* 1 -- n even, -1 -- n odd */ + } +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double tan(double x) +{ + return (double) tanf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/tanhf.c b/libm/libmcs/libm/mathf/tanhf.c new file mode 100644 index 00000000..dca784b2 --- /dev/null +++ b/libm/libmcs/libm/mathf/tanhf.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +#include +#include "../common/tools.h" + +static const float one = 1.0f, two = 2.0f; + +float tanhf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + float t, z; + int32_t jx, ix; + + GET_FLOAT_WORD(jx, x); + ix = jx & 0x7fffffff; + + /* x is INF or NaN */ + if (!FLT_UWORD_IS_FINITE(ix)) { + if (isnan(x)) { /* tanh(NaN) = NaN */ + return x + x; + } else if (jx >= 0) { + return one; /* tanh(+inf)=+1 */ + } else { + return -one; /* tanh(-inf)=-1 */ + } + } + + /* |x| < 22 */ + if (ix < 0x41b00000) { /* |x|<22 */ + if (ix < 0x24000000) { /* |x|<2**-55 */ + if (FLT_UWORD_IS_ZERO(ix)) { /* return x inexact except 0 */ + return x; + } else { + return __raise_inexactf(x); + } + } + + if (ix >= 0x3f800000) { /* |x|>=1 */ + t = expm1f(two * fabsf(x)); + z = one - two / (t + two); + } else { + t = expm1f(-two * fabsf(x)); + z = -t / (t + two); + } + + /* |x| > 22, return +-1 */ + } else { + z = __raise_inexactf(one); /* raised inexact flag */ + } + + return (jx >= 0) ? z : -z; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double tanh(double x) +{ + return (double) tanhf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/tgammaf.c b/libm/libmcs/libm/mathf/tgammaf.c new file mode 100644 index 00000000..dd95ab31 --- /dev/null +++ b/libm/libmcs/libm/mathf/tgammaf.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ +/* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ + +/* __tgammaf(x) + * Float version the Gamma function. Returns gamma(x) + * + * Method: See __lgammaf + */ + +#include +#include "../common/tools.h" +#include "internal/gammaf.h" + +float tgammaf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int signgam_local = 0; + float y = 0.0f; + + if (isnan(x) != 0) { /* tgamma(NaN) = NaN */ + return x + x; + } else if (x == 0.0f) { /* tgamma(+-0) = +-Inf */ + return __raise_div_by_zerof(x); + } else if (floorf(x) == x && x < 0.0f) { /* tgamma(negative integer, -Inf) = NaN */ + return __raise_invalidf(); + } else { + /* No action required */ + } + + y = expf(__lgammaf(x, &signgam_local)); + + if (signgam_local < 0) { + y = -y; + } + + return y; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double tgamma(double x) +{ + return (double) tgammaf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathf/truncf.c b/libm/libmcs/libm/mathf/truncf.c new file mode 100644 index 00000000..20c43bd5 --- /dev/null +++ b/libm/libmcs/libm/mathf/truncf.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: SunMicrosystems */ +/* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. */ + +#include +#include "../common/tools.h" + +float truncf(float x) +{ +#ifdef __LIBMCS_FPU_DAZ + x *= __volatile_onef; +#endif /* defined(__LIBMCS_FPU_DAZ) */ + + int32_t sb; + int32_t w; + int32_t exponent_less_127; + + GET_FLOAT_WORD(w, x); + + /* Extract sign bit. */ + sb = w & 0x80000000U; + + /* Extract exponent field. */ + exponent_less_127 = ((w & 0x7f800000) >> 23) - 127; + + if (exponent_less_127 < 23) { + if (exponent_less_127 < 0) { + /* -1 < x < 1, so result is +0 or -0. */ + SET_FLOAT_WORD(x, sb); + } else { + SET_FLOAT_WORD(x, sb | (w & ~(0x007fffff >> exponent_less_127))); + } + } else { + if (exponent_less_127 == 128) + /* x is NaN or infinite. */ + { + return x + x; + } + + /* All bits in the fraction field are relevant. */ + } + + return x; +} + +#ifdef __LIBMCS_DOUBLE_IS_32BITS + +double trunc(double x) +{ + return (double) truncf((float) x); +} + +#endif /* #ifdef __LIBMCS_DOUBLE_IS_32BITS */ diff --git a/libm/libmcs/libm/mathfe/internal/.gitkeep b/libm/libmcs/libm/mathfe/internal/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/libm/libmcs/libm/mathl/internal/.gitkeep b/libm/libmcs/libm/mathl/internal/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/libm/libmcs/poetry.lock b/libm/libmcs/poetry.lock new file mode 100644 index 00000000..65c97577 --- /dev/null +++ b/libm/libmcs/poetry.lock @@ -0,0 +1,1118 @@ +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. + +[[package]] +name = "alabaster" +version = "1.0.0" +description = "A light, configurable Sphinx theme" +optional = false +python-versions = ">=3.10" +files = [ + {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"}, + {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, +] + +[[package]] +name = "babel" +version = "2.16.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, + {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + +[[package]] +name = "certifi" +version = "2024.8.30" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, +] + +[[package]] +name = "clang" +version = "14.0.6" +description = "libclang python bindings" +optional = false +python-versions = "*" +files = [ + {file = "clang-14.0.6-py3-none-any.whl", hash = "sha256:1bb534a031473d6250fb6af7a2a7d545ca6d3e72781b4c688ee5c0782ce2e851"}, + {file = "clang-14.0.6.tar.gz", hash = "sha256:5ffb10e52328b6117c93b7b86fa5bf1df2d0bdfdd8011b208bda66209feee32a"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "contourpy" +version = "1.3.0" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.9" +files = [ + {file = "contourpy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:880ea32e5c774634f9fcd46504bf9f080a41ad855f4fef54f5380f5133d343c7"}, + {file = "contourpy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:76c905ef940a4474a6289c71d53122a4f77766eef23c03cd57016ce19d0f7b42"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92f8557cbb07415a4d6fa191f20fd9d2d9eb9c0b61d1b2f52a8926e43c6e9af7"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36f965570cff02b874773c49bfe85562b47030805d7d8360748f3eca570f4cab"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cacd81e2d4b6f89c9f8a5b69b86490152ff39afc58a95af002a398273e5ce589"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69375194457ad0fad3a839b9e29aa0b0ed53bb54db1bfb6c3ae43d111c31ce41"}, + {file = "contourpy-1.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a52040312b1a858b5e31ef28c2e865376a386c60c0e248370bbea2d3f3b760d"}, + {file = "contourpy-1.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3faeb2998e4fcb256542e8a926d08da08977f7f5e62cf733f3c211c2a5586223"}, + {file = "contourpy-1.3.0-cp310-cp310-win32.whl", hash = "sha256:36e0cff201bcb17a0a8ecc7f454fe078437fa6bda730e695a92f2d9932bd507f"}, + {file = "contourpy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:87ddffef1dbe5e669b5c2440b643d3fdd8622a348fe1983fad7a0f0ccb1cd67b"}, + {file = "contourpy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fa4c02abe6c446ba70d96ece336e621efa4aecae43eaa9b030ae5fb92b309ad"}, + {file = "contourpy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:834e0cfe17ba12f79963861e0f908556b2cedd52e1f75e6578801febcc6a9f49"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbc4c3217eee163fa3984fd1567632b48d6dfd29216da3ded3d7b844a8014a66"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4865cd1d419e0c7a7bf6de1777b185eebdc51470800a9f42b9e9decf17762081"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:303c252947ab4b14c08afeb52375b26781ccd6a5ccd81abcdfc1fafd14cf93c1"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637f674226be46f6ba372fd29d9523dd977a291f66ab2a74fbeb5530bb3f445d"}, + {file = "contourpy-1.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:76a896b2f195b57db25d6b44e7e03f221d32fe318d03ede41f8b4d9ba1bff53c"}, + {file = "contourpy-1.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e1fd23e9d01591bab45546c089ae89d926917a66dceb3abcf01f6105d927e2cb"}, + {file = "contourpy-1.3.0-cp311-cp311-win32.whl", hash = "sha256:d402880b84df3bec6eab53cd0cf802cae6a2ef9537e70cf75e91618a3801c20c"}, + {file = "contourpy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:6cb6cc968059db9c62cb35fbf70248f40994dfcd7aa10444bbf8b3faeb7c2d67"}, + {file = "contourpy-1.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:570ef7cf892f0afbe5b2ee410c507ce12e15a5fa91017a0009f79f7d93a1268f"}, + {file = "contourpy-1.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:da84c537cb8b97d153e9fb208c221c45605f73147bd4cadd23bdae915042aad6"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0be4d8425bfa755e0fd76ee1e019636ccc7c29f77a7c86b4328a9eb6a26d0639"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c0da700bf58f6e0b65312d0a5e695179a71d0163957fa381bb3c1f72972537c"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb8b141bb00fa977d9122636b16aa67d37fd40a3d8b52dd837e536d64b9a4d06"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3634b5385c6716c258d0419c46d05c8aa7dc8cb70326c9a4fb66b69ad2b52e09"}, + {file = "contourpy-1.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0dce35502151b6bd35027ac39ba6e5a44be13a68f55735c3612c568cac3805fd"}, + {file = "contourpy-1.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea348f053c645100612b333adc5983d87be69acdc6d77d3169c090d3b01dc35"}, + {file = "contourpy-1.3.0-cp312-cp312-win32.whl", hash = "sha256:90f73a5116ad1ba7174341ef3ea5c3150ddf20b024b98fb0c3b29034752c8aeb"}, + {file = "contourpy-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:b11b39aea6be6764f84360fce6c82211a9db32a7c7de8fa6dd5397cf1d079c3b"}, + {file = "contourpy-1.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3e1c7fa44aaae40a2247e2e8e0627f4bea3dd257014764aa644f319a5f8600e3"}, + {file = "contourpy-1.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:364174c2a76057feef647c802652f00953b575723062560498dc7930fc9b1cb7"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b238b3b3b649e09ce9aaf51f0c261d38644bdfa35cbaf7b263457850957a84"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d51fca85f9f7ad0b65b4b9fe800406d0d77017d7270d31ec3fb1cc07358fdea0"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:732896af21716b29ab3e988d4ce14bc5133733b85956316fb0c56355f398099b"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d73f659398a0904e125280836ae6f88ba9b178b2fed6884f3b1f95b989d2c8da"}, + {file = "contourpy-1.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c6c7c2408b7048082932cf4e641fa3b8ca848259212f51c8c59c45aa7ac18f14"}, + {file = "contourpy-1.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f317576606de89da6b7e0861cf6061f6146ead3528acabff9236458a6ba467f8"}, + {file = "contourpy-1.3.0-cp313-cp313-win32.whl", hash = "sha256:31cd3a85dbdf1fc002280c65caa7e2b5f65e4a973fcdf70dd2fdcb9868069294"}, + {file = "contourpy-1.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4553c421929ec95fb07b3aaca0fae668b2eb5a5203d1217ca7c34c063c53d087"}, + {file = "contourpy-1.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:345af746d7766821d05d72cb8f3845dfd08dd137101a2cb9b24de277d716def8"}, + {file = "contourpy-1.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3bb3808858a9dc68f6f03d319acd5f1b8a337e6cdda197f02f4b8ff67ad2057b"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:420d39daa61aab1221567b42eecb01112908b2cab7f1b4106a52caaec8d36973"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d63ee447261e963af02642ffcb864e5a2ee4cbfd78080657a9880b8b1868e18"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:167d6c890815e1dac9536dca00828b445d5d0df4d6a8c6adb4a7ec3166812fa8"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:710a26b3dc80c0e4febf04555de66f5fd17e9cf7170a7b08000601a10570bda6"}, + {file = "contourpy-1.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:75ee7cb1a14c617f34a51d11fa7524173e56551646828353c4af859c56b766e2"}, + {file = "contourpy-1.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:33c92cdae89ec5135d036e7218e69b0bb2851206077251f04a6c4e0e21f03927"}, + {file = "contourpy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a11077e395f67ffc2c44ec2418cfebed032cd6da3022a94fc227b6faf8e2acb8"}, + {file = "contourpy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e8134301d7e204c88ed7ab50028ba06c683000040ede1d617298611f9dc6240c"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e12968fdfd5bb45ffdf6192a590bd8ddd3ba9e58360b29683c6bb71a7b41edca"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fd2a0fc506eccaaa7595b7e1418951f213cf8255be2600f1ea1b61e46a60c55f"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfb5c62ce023dfc410d6059c936dcf96442ba40814aefbfa575425a3a7f19dc"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68a32389b06b82c2fdd68276148d7b9275b5f5cf13e5417e4252f6d1a34f72a2"}, + {file = "contourpy-1.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:94e848a6b83da10898cbf1311a815f770acc9b6a3f2d646f330d57eb4e87592e"}, + {file = "contourpy-1.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d78ab28a03c854a873787a0a42254a0ccb3cb133c672f645c9f9c8f3ae9d0800"}, + {file = "contourpy-1.3.0-cp39-cp39-win32.whl", hash = "sha256:81cb5ed4952aae6014bc9d0421dec7c5835c9c8c31cdf51910b708f548cf58e5"}, + {file = "contourpy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:14e262f67bd7e6eb6880bc564dcda30b15e351a594657e55b7eec94b6ef72843"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fe41b41505a5a33aeaed2a613dccaeaa74e0e3ead6dd6fd3a118fb471644fd6c"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca7e17a65f72a5133bdbec9ecf22401c62bcf4821361ef7811faee695799779"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ec4dc6bf570f5b22ed0d7efba0dfa9c5b9e0431aeea7581aa217542d9e809a4"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:00ccd0dbaad6d804ab259820fa7cb0b8036bda0686ef844d24125d8287178ce0"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ca947601224119117f7c19c9cdf6b3ab54c5726ef1d906aa4a69dfb6dd58102"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6ec93afeb848a0845a18989da3beca3eec2c0f852322efe21af1931147d12cb"}, + {file = "contourpy-1.3.0.tar.gz", hash = "sha256:7ffa0db17717a8ffb127efd0c95a4362d996b892c2904db72428d5b52e1938a4"}, +] + +[package.dependencies] +numpy = ">=1.23" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.11.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] + +[[package]] +name = "cycler" +version = "0.12.1" +description = "Composable style cycles" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "docutils" +version = "0.21.2" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.9" +files = [ + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, +] + +[[package]] +name = "fonttools" +version = "4.54.1" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.54.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ed7ee041ff7b34cc62f07545e55e1468808691dddfd315d51dd82a6b37ddef2"}, + {file = "fonttools-4.54.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41bb0b250c8132b2fcac148e2e9198e62ff06f3cc472065dff839327945c5882"}, + {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7965af9b67dd546e52afcf2e38641b5be956d68c425bef2158e95af11d229f10"}, + {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:278913a168f90d53378c20c23b80f4e599dca62fbffae4cc620c8eed476b723e"}, + {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0e88e3018ac809b9662615072dcd6b84dca4c2d991c6d66e1970a112503bba7e"}, + {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4aa4817f0031206e637d1e685251ac61be64d1adef111060df84fdcbc6ab6c44"}, + {file = "fonttools-4.54.1-cp310-cp310-win32.whl", hash = "sha256:7e3b7d44e18c085fd8c16dcc6f1ad6c61b71ff463636fcb13df7b1b818bd0c02"}, + {file = "fonttools-4.54.1-cp310-cp310-win_amd64.whl", hash = "sha256:dd9cc95b8d6e27d01e1e1f1fae8559ef3c02c76317da650a19047f249acd519d"}, + {file = "fonttools-4.54.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5419771b64248484299fa77689d4f3aeed643ea6630b2ea750eeab219588ba20"}, + {file = "fonttools-4.54.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:301540e89cf4ce89d462eb23a89464fef50915255ece765d10eee8b2bf9d75b2"}, + {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ae5091547e74e7efecc3cbf8e75200bc92daaeb88e5433c5e3e95ea8ce5aa7"}, + {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82834962b3d7c5ca98cb56001c33cf20eb110ecf442725dc5fdf36d16ed1ab07"}, + {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d26732ae002cc3d2ecab04897bb02ae3f11f06dd7575d1df46acd2f7c012a8d8"}, + {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58974b4987b2a71ee08ade1e7f47f410c367cdfc5a94fabd599c88165f56213a"}, + {file = "fonttools-4.54.1-cp311-cp311-win32.whl", hash = "sha256:ab774fa225238986218a463f3fe151e04d8c25d7de09df7f0f5fce27b1243dbc"}, + {file = "fonttools-4.54.1-cp311-cp311-win_amd64.whl", hash = "sha256:07e005dc454eee1cc60105d6a29593459a06321c21897f769a281ff2d08939f6"}, + {file = "fonttools-4.54.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:54471032f7cb5fca694b5f1a0aaeba4af6e10ae989df408e0216f7fd6cdc405d"}, + {file = "fonttools-4.54.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fa92cb248e573daab8d032919623cc309c005086d743afb014c836636166f08"}, + {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a911591200114969befa7f2cb74ac148bce5a91df5645443371aba6d222e263"}, + {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93d458c8a6a354dc8b48fc78d66d2a8a90b941f7fec30e94c7ad9982b1fa6bab"}, + {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5eb2474a7c5be8a5331146758debb2669bf5635c021aee00fd7c353558fc659d"}, + {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9c563351ddc230725c4bdf7d9e1e92cbe6ae8553942bd1fb2b2ff0884e8b714"}, + {file = "fonttools-4.54.1-cp312-cp312-win32.whl", hash = "sha256:fdb062893fd6d47b527d39346e0c5578b7957dcea6d6a3b6794569370013d9ac"}, + {file = "fonttools-4.54.1-cp312-cp312-win_amd64.whl", hash = "sha256:e4564cf40cebcb53f3dc825e85910bf54835e8a8b6880d59e5159f0f325e637e"}, + {file = "fonttools-4.54.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6e37561751b017cf5c40fce0d90fd9e8274716de327ec4ffb0df957160be3bff"}, + {file = "fonttools-4.54.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:357cacb988a18aace66e5e55fe1247f2ee706e01debc4b1a20d77400354cddeb"}, + {file = "fonttools-4.54.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e953cc0bddc2beaf3a3c3b5dd9ab7554677da72dfaf46951e193c9653e515a"}, + {file = "fonttools-4.54.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58d29b9a294573d8319f16f2f79e42428ba9b6480442fa1836e4eb89c4d9d61c"}, + {file = "fonttools-4.54.1-cp313-cp313-win32.whl", hash = "sha256:9ef1b167e22709b46bf8168368b7b5d3efeaaa746c6d39661c1b4405b6352e58"}, + {file = "fonttools-4.54.1-cp313-cp313-win_amd64.whl", hash = "sha256:262705b1663f18c04250bd1242b0515d3bbae177bee7752be67c979b7d47f43d"}, + {file = "fonttools-4.54.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ed2f80ca07025551636c555dec2b755dd005e2ea8fbeb99fc5cdff319b70b23b"}, + {file = "fonttools-4.54.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9dc080e5a1c3b2656caff2ac2633d009b3a9ff7b5e93d0452f40cd76d3da3b3c"}, + {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d152d1be65652fc65e695e5619e0aa0982295a95a9b29b52b85775243c06556"}, + {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8583e563df41fdecef31b793b4dd3af8a9caa03397be648945ad32717a92885b"}, + {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0d1d353ef198c422515a3e974a1e8d5b304cd54a4c2eebcae708e37cd9eeffb1"}, + {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:fda582236fee135d4daeca056c8c88ec5f6f6d88a004a79b84a02547c8f57386"}, + {file = "fonttools-4.54.1-cp38-cp38-win32.whl", hash = "sha256:e7d82b9e56716ed32574ee106cabca80992e6bbdcf25a88d97d21f73a0aae664"}, + {file = "fonttools-4.54.1-cp38-cp38-win_amd64.whl", hash = "sha256:ada215fd079e23e060157aab12eba0d66704316547f334eee9ff26f8c0d7b8ab"}, + {file = "fonttools-4.54.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f5b8a096e649768c2f4233f947cf9737f8dbf8728b90e2771e2497c6e3d21d13"}, + {file = "fonttools-4.54.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e10d2e0a12e18f4e2dd031e1bf7c3d7017be5c8dbe524d07706179f355c5dac"}, + {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31c32d7d4b0958600eac75eaf524b7b7cb68d3a8c196635252b7a2c30d80e986"}, + {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c39287f5c8f4a0c5a55daf9eaf9ccd223ea59eed3f6d467133cc727d7b943a55"}, + {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a7a310c6e0471602fe3bf8efaf193d396ea561486aeaa7adc1f132e02d30c4b9"}, + {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d3b659d1029946f4ff9b6183984578041b520ce0f8fb7078bb37ec7445806b33"}, + {file = "fonttools-4.54.1-cp39-cp39-win32.whl", hash = "sha256:e96bc94c8cda58f577277d4a71f51c8e2129b8b36fd05adece6320dd3d57de8a"}, + {file = "fonttools-4.54.1-cp39-cp39-win_amd64.whl", hash = "sha256:e8a4b261c1ef91e7188a30571be6ad98d1c6d9fa2427244c545e2fa0a2494dd7"}, + {file = "fonttools-4.54.1-py3-none-any.whl", hash = "sha256:37cddd62d83dc4f72f7c3f3c2bcf2697e89a30efb152079896544a93907733bd"}, + {file = "fonttools-4.54.1.tar.gz", hash = "sha256:957f669d4922f92c171ba01bef7f29410668db09f6c02111e22b2bce446f3285"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "pycairo", "scipy"] +lxml = ["lxml (>=4.0)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.1.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] + +[[package]] +name = "hawkmoth" +version = "0.19.0" +description = "Hawkmoth - Sphinx Autodoc for C" +optional = false +python-versions = "~=3.9" +files = [ + {file = "hawkmoth-0.19.0-py3-none-any.whl", hash = "sha256:7eb42a235274ea5ed383af9c2ea4b4a53466152ec8c3af90f145b731d493814f"}, + {file = "hawkmoth-0.19.0.tar.gz", hash = "sha256:3718d2520fd9ce7b80288b736dcfec2276466d0c492d7cb41cbc822f12caf32a"}, +] + +[package.dependencies] +sphinx = ">=3" + +[package.extras] +dev = ["flake8", "mypy", "pytest", "pytest-cov", "pytest-xdist", "restructuredtext-lint", "strictyaml", "types-docutils"] + +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + +[[package]] +name = "jinja2" +version = "3.1.4" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "kiwisolver" +version = "1.4.7" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.8" +files = [ + {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6"}, + {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17"}, + {file = "kiwisolver-1.4.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aa0abdf853e09aff551db11fce173e2177d00786c688203f52c87ad7fcd91ef9"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8d53103597a252fb3ab8b5845af04c7a26d5e7ea8122303dd7a021176a87e8b9"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:88f17c5ffa8e9462fb79f62746428dd57b46eb931698e42e990ad63103f35e6c"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a9ca9c710d598fd75ee5de59d5bda2684d9db36a9f50b6125eaea3969c2599"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4d742cb7af1c28303a51b7a27aaee540e71bb8e24f68c736f6f2ffc82f2bf05"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28c7fea2196bf4c2f8d46a0415c77a1c480cc0724722f23d7410ffe9842c407"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e968b84db54f9d42046cf154e02911e39c0435c9801681e3fc9ce8a3c4130278"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0c18ec74c0472de033e1bebb2911c3c310eef5649133dd0bedf2a169a1b269e5"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8f0ea6da6d393d8b2e187e6a5e3fb81f5862010a40c3945e2c6d12ae45cfb2ad"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:f106407dda69ae456dd1227966bf445b157ccc80ba0dff3802bb63f30b74e895"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84ec80df401cfee1457063732d90022f93951944b5b58975d34ab56bb150dfb3"}, + {file = "kiwisolver-1.4.7-cp310-cp310-win32.whl", hash = "sha256:71bb308552200fb2c195e35ef05de12f0c878c07fc91c270eb3d6e41698c3bcc"}, + {file = "kiwisolver-1.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:44756f9fd339de0fb6ee4f8c1696cfd19b2422e0d70b4cefc1cc7f1f64045a8c"}, + {file = "kiwisolver-1.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:78a42513018c41c2ffd262eb676442315cbfe3c44eed82385c2ed043bc63210a"}, + {file = "kiwisolver-1.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d2b0e12a42fb4e72d509fc994713d099cbb15ebf1103545e8a45f14da2dfca54"}, + {file = "kiwisolver-1.4.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95"}, + {file = "kiwisolver-1.4.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46707a10836894b559e04b0fd143e343945c97fd170d69a2d26d640b4e297935"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef97b8df011141c9b0f6caf23b29379f87dd13183c978a30a3c546d2c47314cb"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:803b8e1459341c1bb56d1c5c010406d5edec8a0713a0945851290a7930679b51"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9a9e8a507420fe35992ee9ecb302dab68550dedc0da9e2880dd88071c5fb052"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6af936f79086a89b3680a280c47ea90b4df7047b5bdf3aa5c524bbedddb9e545"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3abc5b19d24af4b77d1598a585b8a719beb8569a71568b66f4ebe1fb0449460b"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:933d4de052939d90afbe6e9d5273ae05fb836cc86c15b686edd4b3560cc0ee36"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:65e720d2ab2b53f1f72fb5da5fb477455905ce2c88aaa671ff0a447c2c80e8e3"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3bf1ed55088f214ba6427484c59553123fdd9b218a42bbc8c6496d6754b1e523"}, + {file = "kiwisolver-1.4.7-cp311-cp311-win32.whl", hash = "sha256:4c00336b9dd5ad96d0a558fd18a8b6f711b7449acce4c157e7343ba92dd0cf3d"}, + {file = "kiwisolver-1.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b"}, + {file = "kiwisolver-1.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:e33e8fbd440c917106b237ef1a2f1449dfbb9b6f6e1ce17c94cd6a1e0d438376"}, + {file = "kiwisolver-1.4.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5360cc32706dab3931f738d3079652d20982511f7c0ac5711483e6eab08efff2"}, + {file = "kiwisolver-1.4.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942216596dc64ddb25adb215c3c783215b23626f8d84e8eff8d6d45c3f29f75a"}, + {file = "kiwisolver-1.4.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:48b571ecd8bae15702e4f22d3ff6a0f13e54d3d00cd25216d5e7f658242065ee"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad42ba922c67c5f219097b28fae965e10045ddf145d2928bfac2eb2e17673640"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:612a10bdae23404a72941a0fc8fa2660c6ea1217c4ce0dbcab8a8f6543ea9e7f"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e838bba3a3bac0fe06d849d29772eb1afb9745a59710762e4ba3f4cb8424483"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22f499f6157236c19f4bbbd472fa55b063db77a16cd74d49afe28992dff8c258"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693902d433cf585133699972b6d7c42a8b9f8f826ebcaf0132ff55200afc599e"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4e77f2126c3e0b0d055f44513ed349038ac180371ed9b52fe96a32aa071a5107"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:657a05857bda581c3656bfc3b20e353c232e9193eb167766ad2dc58b56504948"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4bfa75a048c056a411f9705856abfc872558e33c055d80af6a380e3658766038"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:34ea1de54beef1c104422d210c47c7d2a4999bdecf42c7b5718fbe59a4cac383"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:90da3b5f694b85231cf93586dad5e90e2d71b9428f9aad96952c99055582f520"}, + {file = "kiwisolver-1.4.7-cp312-cp312-win32.whl", hash = "sha256:18e0cca3e008e17fe9b164b55735a325140a5a35faad8de92dd80265cd5eb80b"}, + {file = "kiwisolver-1.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:58cb20602b18f86f83a5c87d3ee1c766a79c0d452f8def86d925e6c60fbf7bfb"}, + {file = "kiwisolver-1.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:f5a8b53bdc0b3961f8b6125e198617c40aeed638b387913bf1ce78afb1b0be2a"}, + {file = "kiwisolver-1.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2e6039dcbe79a8e0f044f1c39db1986a1b8071051efba3ee4d74f5b365f5226e"}, + {file = "kiwisolver-1.4.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a1ecf0ac1c518487d9d23b1cd7139a6a65bc460cd101ab01f1be82ecf09794b6"}, + {file = "kiwisolver-1.4.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ab9ccab2b5bd5702ab0803676a580fffa2aa178c2badc5557a84cc943fcf750"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f816dd2277f8d63d79f9c8473a79fe54047bc0467754962840782c575522224d"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf8bcc23ceb5a1b624572a1623b9f79d2c3b337c8c455405ef231933a10da379"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dea0bf229319828467d7fca8c7c189780aa9ff679c94539eed7532ebe33ed37c"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c06a4c7cf15ec739ce0e5971b26c93638730090add60e183530d70848ebdd34"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913983ad2deb14e66d83c28b632fd35ba2b825031f2fa4ca29675e665dfecbe1"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5337ec7809bcd0f424c6b705ecf97941c46279cf5ed92311782c7c9c2026f07f"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c26ed10c4f6fa6ddb329a5120ba3b6db349ca192ae211e882970bfc9d91420b"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c619b101e6de2222c1fcb0531e1b17bbffbe54294bfba43ea0d411d428618c27"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:073a36c8273647592ea332e816e75ef8da5c303236ec0167196793eb1e34657a"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3ce6b2b0231bda412463e152fc18335ba32faf4e8c23a754ad50ffa70e4091ee"}, + {file = "kiwisolver-1.4.7-cp313-cp313-win32.whl", hash = "sha256:f4c9aee212bc89d4e13f58be11a56cc8036cabad119259d12ace14b34476fd07"}, + {file = "kiwisolver-1.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:8a3ec5aa8e38fc4c8af308917ce12c536f1c88452ce554027e55b22cbbfbff76"}, + {file = "kiwisolver-1.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:76c8094ac20ec259471ac53e774623eb62e6e1f56cd8690c67ce6ce4fcb05650"}, + {file = "kiwisolver-1.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5d5abf8f8ec1f4e22882273c423e16cae834c36856cac348cfbfa68e01c40f3a"}, + {file = "kiwisolver-1.4.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:aeb3531b196ef6f11776c21674dba836aeea9d5bd1cf630f869e3d90b16cfade"}, + {file = "kiwisolver-1.4.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7d755065e4e866a8086c9bdada157133ff466476a2ad7861828e17b6026e22c"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08471d4d86cbaec61f86b217dd938a83d85e03785f51121e791a6e6689a3be95"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bbfcb7165ce3d54a3dfbe731e470f65739c4c1f85bb1018ee912bae139e263b"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d34eb8494bea691a1a450141ebb5385e4b69d38bb8403b5146ad279f4b30fa3"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9242795d174daa40105c1d86aba618e8eab7bf96ba8c3ee614da8302a9f95503"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a0f64a48bb81af7450e641e3fe0b0394d7381e342805479178b3d335d60ca7cf"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8e045731a5416357638d1700927529e2b8ab304811671f665b225f8bf8d8f933"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4322872d5772cae7369f8351da1edf255a604ea7087fe295411397d0cfd9655e"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e1631290ee9271dffe3062d2634c3ecac02c83890ada077d225e081aca8aab89"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:edcfc407e4eb17e037bca59be0e85a2031a2ac87e4fed26d3e9df88b4165f92d"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:4d05d81ecb47d11e7f8932bd8b61b720bf0b41199358f3f5e36d38e28f0532c5"}, + {file = "kiwisolver-1.4.7-cp38-cp38-win32.whl", hash = "sha256:b38ac83d5f04b15e515fd86f312479d950d05ce2368d5413d46c088dda7de90a"}, + {file = "kiwisolver-1.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:d83db7cde68459fc803052a55ace60bea2bae361fc3b7a6d5da07e11954e4b09"}, + {file = "kiwisolver-1.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f9362ecfca44c863569d3d3c033dbe8ba452ff8eed6f6b5806382741a1334bd"}, + {file = "kiwisolver-1.4.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e8df2eb9b2bac43ef8b082e06f750350fbbaf2887534a5be97f6cf07b19d9583"}, + {file = "kiwisolver-1.4.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f32d6edbc638cde7652bd690c3e728b25332acbadd7cad670cc4a02558d9c417"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e2e6c39bd7b9372b0be21456caab138e8e69cc0fc1190a9dfa92bd45a1e6e904"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dda56c24d869b1193fcc763f1284b9126550eaf84b88bbc7256e15028f19188a"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79849239c39b5e1fd906556c474d9b0439ea6792b637511f3fe3a41158d89ca8"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e3bc157fed2a4c02ec468de4ecd12a6e22818d4f09cde2c31ee3226ffbefab2"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3da53da805b71e41053dc670f9a820d1157aae77b6b944e08024d17bcd51ef88"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8705f17dfeb43139a692298cb6637ee2e59c0194538153e83e9ee0c75c2eddde"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:82a5c2f4b87c26bb1a0ef3d16b5c4753434633b83d365cc0ddf2770c93829e3c"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce8be0466f4c0d585cdb6c1e2ed07232221df101a4c6f28821d2aa754ca2d9e2"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:409afdfe1e2e90e6ee7fc896f3df9a7fec8e793e58bfa0d052c8a82f99c37abb"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b9c3f4ee0b9a439d2415012bd1b1cc2df59e4d6a9939f4d669241d30b414327"}, + {file = "kiwisolver-1.4.7-cp39-cp39-win32.whl", hash = "sha256:a79ae34384df2b615eefca647a2873842ac3b596418032bef9a7283675962644"}, + {file = "kiwisolver-1.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:cf0438b42121a66a3a667de17e779330fc0f20b0d97d59d2f2121e182b0505e4"}, + {file = "kiwisolver-1.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:764202cc7e70f767dab49e8df52c7455e8de0df5d858fa801a11aa0d882ccf3f"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:94252291e3fe68001b1dd747b4c0b3be12582839b95ad4d1b641924d68fd4643"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b7dfa3b546da08a9f622bb6becdb14b3e24aaa30adba66749d38f3cc7ea9706"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd3de6481f4ed8b734da5df134cd5a6a64fe32124fe83dde1e5b5f29fe30b1e6"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a91b5f9f1205845d488c928e8570dcb62b893372f63b8b6e98b863ebd2368ff2"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40fa14dbd66b8b8f470d5fc79c089a66185619d31645f9b0773b88b19f7223c4"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:eb542fe7933aa09d8d8f9d9097ef37532a7df6497819d16efe4359890a2f417a"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bfa1acfa0c54932d5607e19a2c24646fb4c1ae2694437789129cf099789a3b00"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:eee3ea935c3d227d49b4eb85660ff631556841f6e567f0f7bda972df6c2c9935"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f3160309af4396e0ed04db259c3ccbfdc3621b5559b5453075e5de555e1f3a1b"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a17f6a29cf8935e587cc8a4dbfc8368c55edc645283db0ce9801016f83526c2d"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10849fb2c1ecbfae45a693c070e0320a91b35dd4bcf58172c023b994283a124d"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:ac542bf38a8a4be2dc6b15248d36315ccc65f0743f7b1a76688ffb6b5129a5c2"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8b01aac285f91ca889c800042c35ad3b239e704b150cfd3382adfc9dcc780e39"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48be928f59a1f5c8207154f935334d374e79f2b5d212826307d072595ad76a2e"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f37cfe618a117e50d8c240555331160d73d0411422b59b5ee217843d7b693608"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:599b5c873c63a1f6ed7eead644a8a380cfbdf5db91dcb6f85707aaab213b1674"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:801fa7802e5cfabe3ab0c81a34c323a319b097dfb5004be950482d882f3d7225"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0c6c43471bc764fad4bc99c5c2d6d16a676b1abf844ca7c8702bdae92df01ee0"}, + {file = "kiwisolver-1.4.7.tar.gz", hash = "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60"}, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.9" +files = [ + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, +] + +[[package]] +name = "matplotlib" +version = "3.9.2" +description = "Python plotting package" +optional = false +python-versions = ">=3.9" +files = [ + {file = "matplotlib-3.9.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9d78bbc0cbc891ad55b4f39a48c22182e9bdaea7fc0e5dbd364f49f729ca1bbb"}, + {file = "matplotlib-3.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c375cc72229614632c87355366bdf2570c2dac01ac66b8ad048d2dabadf2d0d4"}, + {file = "matplotlib-3.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d94ff717eb2bd0b58fe66380bd8b14ac35f48a98e7c6765117fe67fb7684e64"}, + {file = "matplotlib-3.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab68d50c06938ef28681073327795c5db99bb4666214d2d5f880ed11aeaded66"}, + {file = "matplotlib-3.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:65aacf95b62272d568044531e41de26285d54aec8cb859031f511f84bd8b495a"}, + {file = "matplotlib-3.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:3fd595f34aa8a55b7fc8bf9ebea8aa665a84c82d275190a61118d33fbc82ccae"}, + {file = "matplotlib-3.9.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772"}, + {file = "matplotlib-3.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41"}, + {file = "matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f"}, + {file = "matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447"}, + {file = "matplotlib-3.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7741f26a58a240f43bee74965c4882b6c93df3e7eb3de160126d8c8f53a6ae6e"}, + {file = "matplotlib-3.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7"}, + {file = "matplotlib-3.9.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ac43031375a65c3196bee99f6001e7fa5bdfb00ddf43379d3c0609bdca042df9"}, + {file = "matplotlib-3.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be0fc24a5e4531ae4d8e858a1a548c1fe33b176bb13eff7f9d0d38ce5112a27d"}, + {file = "matplotlib-3.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf81de2926c2db243c9b2cbc3917619a0fc85796c6ba4e58f541df814bbf83c7"}, + {file = "matplotlib-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ee45bc4245533111ced13f1f2cace1e7f89d1c793390392a80c139d6cf0e6c"}, + {file = "matplotlib-3.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:306c8dfc73239f0e72ac50e5a9cf19cc4e8e331dd0c54f5e69ca8758550f1e1e"}, + {file = "matplotlib-3.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:5413401594cfaff0052f9d8b1aafc6d305b4bd7c4331dccd18f561ff7e1d3bd3"}, + {file = "matplotlib-3.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:18128cc08f0d3cfff10b76baa2f296fc28c4607368a8402de61bb3f2eb33c7d9"}, + {file = "matplotlib-3.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4876d7d40219e8ae8bb70f9263bcbe5714415acfdf781086601211335e24f8aa"}, + {file = "matplotlib-3.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d9f07a80deab4bb0b82858a9e9ad53d1382fd122be8cde11080f4e7dfedb38b"}, + {file = "matplotlib-3.9.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7c0410f181a531ec4e93bbc27692f2c71a15c2da16766f5ba9761e7ae518413"}, + {file = "matplotlib-3.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:909645cce2dc28b735674ce0931a4ac94e12f5b13f6bb0b5a5e65e7cea2c192b"}, + {file = "matplotlib-3.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:f32c7410c7f246838a77d6d1eff0c0f87f3cb0e7c4247aebea71a6d5a68cab49"}, + {file = "matplotlib-3.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:37e51dd1c2db16ede9cfd7b5cabdfc818b2c6397c83f8b10e0e797501c963a03"}, + {file = "matplotlib-3.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b82c5045cebcecd8496a4d694d43f9cc84aeeb49fe2133e036b207abe73f4d30"}, + {file = "matplotlib-3.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f053c40f94bc51bc03832a41b4f153d83f2062d88c72b5e79997072594e97e51"}, + {file = "matplotlib-3.9.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbe196377a8248972f5cede786d4c5508ed5f5ca4a1e09b44bda889958b33f8c"}, + {file = "matplotlib-3.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5816b1e1fe8c192cbc013f8f3e3368ac56fbecf02fb41b8f8559303f24c5015e"}, + {file = "matplotlib-3.9.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:cef2a73d06601437be399908cf13aee74e86932a5ccc6ccdf173408ebc5f6bb2"}, + {file = "matplotlib-3.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e0830e188029c14e891fadd99702fd90d317df294c3298aad682739c5533721a"}, + {file = "matplotlib-3.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ba9c1299c920964e8d3857ba27173b4dbb51ca4bab47ffc2c2ba0eb5e2cbc5"}, + {file = "matplotlib-3.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cd93b91ab47a3616b4d3c42b52f8363b88ca021e340804c6ab2536344fad9ca"}, + {file = "matplotlib-3.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6d1ce5ed2aefcdce11904fc5bbea7d9c21fff3d5f543841edf3dea84451a09ea"}, + {file = "matplotlib-3.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:b2696efdc08648536efd4e1601b5fd491fd47f4db97a5fbfd175549a7365c1b2"}, + {file = "matplotlib-3.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d52a3b618cb1cbb769ce2ee1dcdb333c3ab6e823944e9a2d36e37253815f9556"}, + {file = "matplotlib-3.9.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:039082812cacd6c6bec8e17a9c1e6baca230d4116d522e81e1f63a74d01d2e21"}, + {file = "matplotlib-3.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6758baae2ed64f2331d4fd19be38b7b4eae3ecec210049a26b6a4f3ae1c85dcc"}, + {file = "matplotlib-3.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:050598c2b29e0b9832cde72bcf97627bf00262adbc4a54e2b856426bb2ef0697"}, + {file = "matplotlib-3.9.2.tar.gz", hash = "sha256:96ab43906269ca64a6366934106fa01534454a69e471b7bf3d79083981aaab92"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +kiwisolver = ">=1.3.1" +numpy = ">=1.23" +packaging = ">=20.0" +pillow = ">=8" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + +[package.extras] +dev = ["meson-python (>=0.13.1)", "numpy (>=1.25)", "pybind11 (>=2.6)", "setuptools (>=64)", "setuptools_scm (>=7)"] + +[[package]] +name = "numpy" +version = "2.1.3" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.10" +files = [ + {file = "numpy-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c894b4305373b9c5576d7a12b473702afdf48ce5369c074ba304cc5ad8730dff"}, + {file = "numpy-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b47fbb433d3260adcd51eb54f92a2ffbc90a4595f8970ee00e064c644ac788f5"}, + {file = "numpy-2.1.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:825656d0743699c529c5943554d223c021ff0494ff1442152ce887ef4f7561a1"}, + {file = "numpy-2.1.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:6a4825252fcc430a182ac4dee5a505053d262c807f8a924603d411f6718b88fd"}, + {file = "numpy-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e711e02f49e176a01d0349d82cb5f05ba4db7d5e7e0defd026328e5cfb3226d3"}, + {file = "numpy-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78574ac2d1a4a02421f25da9559850d59457bac82f2b8d7a44fe83a64f770098"}, + {file = "numpy-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c7662f0e3673fe4e832fe07b65c50342ea27d989f92c80355658c7f888fcc83c"}, + {file = "numpy-2.1.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fa2d1337dc61c8dc417fbccf20f6d1e139896a30721b7f1e832b2bb6ef4eb6c4"}, + {file = "numpy-2.1.3-cp310-cp310-win32.whl", hash = "sha256:72dcc4a35a8515d83e76b58fdf8113a5c969ccd505c8a946759b24e3182d1f23"}, + {file = "numpy-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:ecc76a9ba2911d8d37ac01de72834d8849e55473457558e12995f4cd53e778e0"}, + {file = "numpy-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4d1167c53b93f1f5d8a139a742b3c6f4d429b54e74e6b57d0eff40045187b15d"}, + {file = "numpy-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c80e4a09b3d95b4e1cac08643f1152fa71a0a821a2d4277334c88d54b2219a41"}, + {file = "numpy-2.1.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:576a1c1d25e9e02ed7fa5477f30a127fe56debd53b8d2c89d5578f9857d03ca9"}, + {file = "numpy-2.1.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:973faafebaae4c0aaa1a1ca1ce02434554d67e628b8d805e61f874b84e136b09"}, + {file = "numpy-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:762479be47a4863e261a840e8e01608d124ee1361e48b96916f38b119cfda04a"}, + {file = "numpy-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f24b3d1ecc1eebfbf5d6051faa49af40b03be1aaa781ebdadcbc090b4539b"}, + {file = "numpy-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:17ee83a1f4fef3c94d16dc1802b998668b5419362c8a4f4e8a491de1b41cc3ee"}, + {file = "numpy-2.1.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15cb89f39fa6d0bdfb600ea24b250e5f1a3df23f901f51c8debaa6a5d122b2f0"}, + {file = "numpy-2.1.3-cp311-cp311-win32.whl", hash = "sha256:d9beb777a78c331580705326d2367488d5bc473b49a9bc3036c154832520aca9"}, + {file = "numpy-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:d89dd2b6da69c4fff5e39c28a382199ddedc3a5be5390115608345dec660b9e2"}, + {file = "numpy-2.1.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f55ba01150f52b1027829b50d70ef1dafd9821ea82905b63936668403c3b471e"}, + {file = "numpy-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13138eadd4f4da03074851a698ffa7e405f41a0845a6b1ad135b81596e4e9958"}, + {file = "numpy-2.1.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:a6b46587b14b888e95e4a24d7b13ae91fa22386c199ee7b418f449032b2fa3b8"}, + {file = "numpy-2.1.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:0fa14563cc46422e99daef53d725d0c326e99e468a9320a240affffe87852564"}, + {file = "numpy-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8637dcd2caa676e475503d1f8fdb327bc495554e10838019651b76d17b98e512"}, + {file = "numpy-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2312b2aa89e1f43ecea6da6ea9a810d06aae08321609d8dc0d0eda6d946a541b"}, + {file = "numpy-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a38c19106902bb19351b83802531fea19dee18e5b37b36454f27f11ff956f7fc"}, + {file = "numpy-2.1.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02135ade8b8a84011cbb67dc44e07c58f28575cf9ecf8ab304e51c05528c19f0"}, + {file = "numpy-2.1.3-cp312-cp312-win32.whl", hash = "sha256:e6988e90fcf617da2b5c78902fe8e668361b43b4fe26dbf2d7b0f8034d4cafb9"}, + {file = "numpy-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:0d30c543f02e84e92c4b1f415b7c6b5326cbe45ee7882b6b77db7195fb971e3a"}, + {file = "numpy-2.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96fe52fcdb9345b7cd82ecd34547fca4321f7656d500eca497eb7ea5a926692f"}, + {file = "numpy-2.1.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f653490b33e9c3a4c1c01d41bc2aef08f9475af51146e4a7710c450cf9761598"}, + {file = "numpy-2.1.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dc258a761a16daa791081d026f0ed4399b582712e6fc887a95af09df10c5ca57"}, + {file = "numpy-2.1.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:016d0f6f5e77b0f0d45d77387ffa4bb89816b57c835580c3ce8e099ef830befe"}, + {file = "numpy-2.1.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c181ba05ce8299c7aa3125c27b9c2167bca4a4445b7ce73d5febc411ca692e43"}, + {file = "numpy-2.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5641516794ca9e5f8a4d17bb45446998c6554704d888f86df9b200e66bdcce56"}, + {file = "numpy-2.1.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ea4dedd6e394a9c180b33c2c872b92f7ce0f8e7ad93e9585312b0c5a04777a4a"}, + {file = "numpy-2.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0df3635b9c8ef48bd3be5f862cf71b0a4716fa0e702155c45067c6b711ddcef"}, + {file = "numpy-2.1.3-cp313-cp313-win32.whl", hash = "sha256:50ca6aba6e163363f132b5c101ba078b8cbd3fa92c7865fd7d4d62d9779ac29f"}, + {file = "numpy-2.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:747641635d3d44bcb380d950679462fae44f54b131be347d5ec2bce47d3df9ed"}, + {file = "numpy-2.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:996bb9399059c5b82f76b53ff8bb686069c05acc94656bb259b1d63d04a9506f"}, + {file = "numpy-2.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:45966d859916ad02b779706bb43b954281db43e185015df6eb3323120188f9e4"}, + {file = "numpy-2.1.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:baed7e8d7481bfe0874b566850cb0b85243e982388b7b23348c6db2ee2b2ae8e"}, + {file = "numpy-2.1.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f7f672a3388133335589cfca93ed468509cb7b93ba3105fce780d04a6576a0"}, + {file = "numpy-2.1.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7aac50327da5d208db2eec22eb11e491e3fe13d22653dce51b0f4109101b408"}, + {file = "numpy-2.1.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4394bc0dbd074b7f9b52024832d16e019decebf86caf909d94f6b3f77a8ee3b6"}, + {file = "numpy-2.1.3-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:50d18c4358a0a8a53f12a8ba9d772ab2d460321e6a93d6064fc22443d189853f"}, + {file = "numpy-2.1.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:14e253bd43fc6b37af4921b10f6add6925878a42a0c5fe83daee390bca80bc17"}, + {file = "numpy-2.1.3-cp313-cp313t-win32.whl", hash = "sha256:08788d27a5fd867a663f6fc753fd7c3ad7e92747efc73c53bca2f19f8bc06f48"}, + {file = "numpy-2.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2564fbdf2b99b3f815f2107c1bbc93e2de8ee655a69c261363a1172a79a257d4"}, + {file = "numpy-2.1.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4f2015dfe437dfebbfce7c85c7b53d81ba49e71ba7eadbf1df40c915af75979f"}, + {file = "numpy-2.1.3-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:3522b0dfe983a575e6a9ab3a4a4dfe156c3e428468ff08ce582b9bb6bd1d71d4"}, + {file = "numpy-2.1.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c006b607a865b07cd981ccb218a04fc86b600411d83d6fc261357f1c0966755d"}, + {file = "numpy-2.1.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e14e26956e6f1696070788252dcdff11b4aca4c3e8bd166e0df1bb8f315a67cb"}, + {file = "numpy-2.1.3.tar.gz", hash = "sha256:aa08e04e08aaf974d4458def539dece0d28146d866a39da5639596f4921fd761"}, +] + +[[package]] +name = "packaging" +version = "24.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, +] + +[[package]] +name = "pillow" +version = "11.0.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pillow-11.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947"}, + {file = "pillow-11.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba"}, + {file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086"}, + {file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9"}, + {file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488"}, + {file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f"}, + {file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb"}, + {file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97"}, + {file = "pillow-11.0.0-cp310-cp310-win32.whl", hash = "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50"}, + {file = "pillow-11.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c"}, + {file = "pillow-11.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1"}, + {file = "pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc"}, + {file = "pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a"}, + {file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3"}, + {file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5"}, + {file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b"}, + {file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa"}, + {file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306"}, + {file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9"}, + {file = "pillow-11.0.0-cp311-cp311-win32.whl", hash = "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5"}, + {file = "pillow-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291"}, + {file = "pillow-11.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9"}, + {file = "pillow-11.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923"}, + {file = "pillow-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903"}, + {file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4"}, + {file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f"}, + {file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"}, + {file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7"}, + {file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6"}, + {file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc"}, + {file = "pillow-11.0.0-cp312-cp312-win32.whl", hash = "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6"}, + {file = "pillow-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47"}, + {file = "pillow-11.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25"}, + {file = "pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699"}, + {file = "pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38"}, + {file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2"}, + {file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2"}, + {file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527"}, + {file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa"}, + {file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f"}, + {file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb"}, + {file = "pillow-11.0.0-cp313-cp313-win32.whl", hash = "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798"}, + {file = "pillow-11.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de"}, + {file = "pillow-11.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84"}, + {file = "pillow-11.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b"}, + {file = "pillow-11.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003"}, + {file = "pillow-11.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2"}, + {file = "pillow-11.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a"}, + {file = "pillow-11.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8"}, + {file = "pillow-11.0.0-cp313-cp313t-win32.whl", hash = "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8"}, + {file = "pillow-11.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904"}, + {file = "pillow-11.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3"}, + {file = "pillow-11.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2e46773dc9f35a1dd28bd6981332fd7f27bec001a918a72a79b4133cf5291dba"}, + {file = "pillow-11.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2679d2258b7f1192b378e2893a8a0a0ca472234d4c2c0e6bdd3380e8dfa21b6a"}, + {file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda2616eb2313cbb3eebbe51f19362eb434b18e3bb599466a1ffa76a033fb916"}, + {file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ec184af98a121fb2da42642dea8a29ec80fc3efbaefb86d8fdd2606619045d"}, + {file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:8594f42df584e5b4bb9281799698403f7af489fba84c34d53d1c4bfb71b7c4e7"}, + {file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:c12b5ae868897c7338519c03049a806af85b9b8c237b7d675b8c5e089e4a618e"}, + {file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:70fbbdacd1d271b77b7721fe3cdd2d537bbbd75d29e6300c672ec6bb38d9672f"}, + {file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5178952973e588b3f1360868847334e9e3bf49d19e169bbbdfaf8398002419ae"}, + {file = "pillow-11.0.0-cp39-cp39-win32.whl", hash = "sha256:8c676b587da5673d3c75bd67dd2a8cdfeb282ca38a30f37950511766b26858c4"}, + {file = "pillow-11.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:94f3e1780abb45062287b4614a5bc0874519c86a777d4a7ad34978e86428b8dd"}, + {file = "pillow-11.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:290f2cc809f9da7d6d622550bbf4c1e57518212da51b6a30fe8e0a270a5b78bd"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316"}, + {file = "pillow-11.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5bd2d3bdb846d757055910f0a59792d33b555800813c3b39ada1829c372ccb06"}, + {file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:375b8dd15a1f5d2feafff536d47e22f69625c1aa92f12b339ec0b2ca40263273"}, + {file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:daffdf51ee5db69a82dd127eabecce20729e21f7a3680cf7cbb23f0829189790"}, + {file = "pillow-11.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7326a1787e3c7b0429659e0a944725e1b03eeaa10edd945a86dead1913383944"}, + {file = "pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=8.1)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyparsing" +version = "3.2.0" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84"}, + {file = "pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "sphinx" +version = "8.1.3" +description = "Python documentation generator" +optional = false +python-versions = ">=3.10" +files = [ + {file = "sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2"}, + {file = "sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927"}, +] + +[package.dependencies] +alabaster = ">=0.7.14" +babel = ">=2.13" +colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} +docutils = ">=0.20,<0.22" +imagesize = ">=1.3" +Jinja2 = ">=3.1" +packaging = ">=23.0" +Pygments = ">=2.17" +requests = ">=2.30.0" +snowballstemmer = ">=2.2" +sphinxcontrib-applehelp = ">=1.0.7" +sphinxcontrib-devhelp = ">=1.0.6" +sphinxcontrib-htmlhelp = ">=2.0.6" +sphinxcontrib-jsmath = ">=1.0.1" +sphinxcontrib-qthelp = ">=1.0.6" +sphinxcontrib-serializinghtml = ">=1.1.9" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["flake8 (>=6.0)", "mypy (==1.11.1)", "pyright (==1.1.384)", "pytest (>=6.0)", "ruff (==0.6.9)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-Pillow (==10.2.0.20240822)", "types-Pygments (==2.18.0.20240506)", "types-colorama (==0.4.15.20240311)", "types-defusedxml (==0.7.0.20240218)", "types-docutils (==0.21.0.20241005)", "types-requests (==2.32.0.20240914)", "types-urllib3 (==1.26.25.14)"] +test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] + +[[package]] +name = "sphinx-mathjax-offline" +version = "0.0.2" +description = "MathJax offline support for Sphinx" +optional = false +python-versions = "*" +files = [ + {file = "sphinx-mathjax-offline-0.0.2.tar.gz", hash = "sha256:7dfbcbd6dc60efd8d8f1aac0718f0ee5913a5cea03cb0e03ffa77ff0dfbfe5bd"}, + {file = "sphinx_mathjax_offline-0.0.2-py3-none-any.whl", hash = "sha256:206418155b2ff2f57496fb8501fdccae3da978e53031ff296c73729ba16062c4"}, +] + +[package.dependencies] +sphinx = "*" + +[[package]] +name = "sphinx-rtd-theme" +version = "3.0.1" +description = "Read the Docs theme for Sphinx" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinx_rtd_theme-3.0.1-py2.py3-none-any.whl", hash = "sha256:921c0ece75e90633ee876bd7b148cfaad136b481907ad154ac3669b6fc957916"}, + {file = "sphinx_rtd_theme-3.0.1.tar.gz", hash = "sha256:a4c5745d1b06dfcb80b7704fe532eb765b44065a8fad9851e4258c8804140703"}, +] + +[package.dependencies] +docutils = ">0.18,<0.22" +sphinx = ">=6,<9" +sphinxcontrib-jquery = ">=4,<5" + +[package.extras] +dev = ["bump2version", "transifex-client", "twine", "wheel"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, + {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, + {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, + {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jquery" +version = "4.1" +description = "Extension to include jQuery on newer Sphinx releases" +optional = false +python-versions = ">=2.7" +files = [ + {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, + {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, +] + +[package.dependencies] +Sphinx = ">=1.8" + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, + {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["defusedxml (>=0.7.1)", "pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, + {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "urllib3" +version = "2.2.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "d69e16533f4f5745ba226d3781ce00bc4a0db82bdbaf24690e6605bcb22e37b8" diff --git a/libm/libmcs/pyproject.toml b/libm/libmcs/pyproject.toml new file mode 100644 index 00000000..727cb78a --- /dev/null +++ b/libm/libmcs/pyproject.toml @@ -0,0 +1,21 @@ +[tool.poetry] +name = "libmcs" +version = "1.3.0" +description = "Qualified Mathematical Library for Critical Systems, based on Newlib" +authors = ["GTD GmbH "] +license = "BSD" +readme = "README.md" +package-mode = false + +[tool.poetry.dependencies] +python = "^3.11" +sphinx-rtd-theme = "^3.0.1" +sphinx-mathjax-offline = "^0.0.2" +hawkmoth = "^0.19.0" +clang = "^14.0.0" +matplotlib = "^3.9.2" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/libm/libmcs/sw-quality/au-misra3.lnt b/libm/libmcs/sw-quality/au-misra3.lnt new file mode 100644 index 00000000..b5b66921 --- /dev/null +++ b/libm/libmcs/sw-quality/au-misra3.lnt @@ -0,0 +1,2173 @@ +/* Date Stamp */ -d"_lint_au_misra3_lnt=au-misra3.lnt modified 12-Jun-2014" +/* To document usage use: -message( "Using " _lint_au_misra3_lnt ) */ + +// --------------------------------------------------------------------- +// This file is provided by Gimpel Software (www.gimpel.com) for use with +// its products PC-lint and FlexeLint. +// +// Redistribution and use of this file, with or without modification, is +// permitted provided that any such redistribution retains this notice. +// --------------------------------------------------------------------- + +// au-misra3.lnt -- Author options - MISRA C 2012 + +/* + This options file can be used to explicitly activate those + checks advocated by the Motor Industry Software Reliability + Association. + + You can use this file directly when linting your programs as in: + + lin au-misra3 files + + Gimpel Software relies on the document, "MISRA-C:2012 + Guidelines for the use of the C language in critical systems", + copyright 2012 by MIRA Limited, as the primary source for this + file. Gimpel Software makes no warranty as to the completeness + or applicability of this options file and reserves the right to + amend or alter the official contents of such at any time. + + "MISRA" is a registered trademark of MIRA Limited, held on + behalf of the MISRA Consortium. + + */ + -misra(3) // Activate MISRA Essential Type model + +/**** Dir 1.1 (Req) ************/ + + /* not statically checkable */ + +/**** Dir 2.1 (Req) ************/ + + -A(C99) /* strict ISO C99 */ + /* Note: if you code to the C90 standard instead, you may + want to comment out the above option and uncomment the + following option. You will also want to do likewise for + other uses of the '-A(C99)' option throughout this file. */ + // -A(C90) /* strict ANSI */ + +e950 /* flag non-standard word or construct */ + +elib(950) + -append(950,[MISRA 2012 Directive 2.1, required]) + +/**** Dir 3.1 (Req) ************/ + + /* not statically checkable */ + +/**** Dir 4.1 (Req) ************/ + + /* not statically checkable */ + +/**** Dir 4.2 (Adv) ************/ + + /* not statically checkable */ + +/**** Dir 4.3 (Req) ************/ + + +e586 /* to activate the deprecation message */ + +elib(586) + -deprecate(keyword,asm,[MISRA 2012 4.3, required]) + +/**** Dir 4.4 (Adv) ************/ + + /* This requirement (that there be no commented-out code) is, in + principle, not statically checkable. The reason given for the + requirement is that comments do not nest. Thus a commented + out section of code that happens to use slash-star commenting + could inadvertently introduce unwanted code. Rule 3.1, however, + addresses the nested comment issue and hence the major concern + that this requirement seeks to address is indeed checkable. + */ + -fnc /* flag nested comments */ + +e602 /* comment within comment */ + +elib(602) + -append(602,[MISRA 2012 Directive 4.4, advisory]) + +/**** Dir 4.5 (Adv) ************/ + + // While Lint can enforce this directive with the following four + // options, doing so can increase the run time of Lint depending + // upon the number of identifiers in your program. If you want + // this checking, uncomment each of the following four options. + // + // +fta + // +e9046 /* typographical ambiguity */ + // +elib(9046) + // -append(9046,[MISRA 2012 Directive 4.5, advisory]) + +/**** Dir 4.6 (Adv) ************/ + + +e970 /* flag modifiers used outside of typedefs */ + +elib(970) + -append(970,[MISRA 2012 Directive 4.6, advisory]) + // For the duration, we are presuming MISRA does not want + // diagnostics for the bool type. + -esym(970,bool) + -esym(970,char) + +/**** Dir 4.7 (Req) ************/ + + +e534 /* ignoring return value of function */ + +elib(534) + -append(534,[MISRA 2012 Directive 4.7, required]) + +/**** Dir 4.8 (Adv) ************/ + + +e9045 /* non-hidden definition of type */ + +elib(9045) + -append(9045,[MISRA 2012 Directive 4.8, advisory]) + +/**** Dir 4.9 (Adv) ************/ + + +e9026 /* function-like macro defined */ + +elib(9026) + -append(9026,[MISRA 2012 Directive 4.9, advisory]) + +/**** Dir 4.10 (Req) ************/ + + +e451 /* Header repeatedly included without guard */ + +elib(451) + -append(451,[MISRA 2012 Directive 4.10, required]) + +/**** Dir 4.11 (Req) ************/ + + /* The arguments to over 100 calls to standard library functions + are monitored; users can specify additional constraints for + other functions. + */ + +/**** Dir 4.12 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(function,calloc,[MISRA 2012 Directive 4.12, required]) + -deprecate(function,malloc,[MISRA 2012 Directive 4.12, required]) + -deprecate(function,realloc,[MISRA 2012 Directive 4.12, required]) + -deprecate(function,free,[MISRA 2012 Directive 4.12, required]) + +/**** Dir 4.13 (Adv) ************/ + + /* supported by uncommenting the next six options and use of the + -function_pair() option */ + // +e480 + // +elib(480) + // -append(480,[MISRA 2012 Directive 4.13, advisory]) + // +e481 + // +elib(481) + // -append(481,[MISRA 2012 Directive 4.13, advisory]) + +/**** Rule 1.1 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + -A(C99) /* strict ISO C99 */ + /* Note: if you code to the C90 standard instead, you may + want to comment out the above option and uncomment the + following option. You will also want to do likewise for + other uses of the '-A(C99)' option throughout this file. */ + // -A(C90) /* strict ANSI */ + +e950 /* flag non-standard word or construct */ + +elib(950) + -append(950,[MISRA 2012 Rule 1.1, required]) + +/**** Rule 1.2 (Adv) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + -A(C99) /* strict ISO C99 */ + /* Note: if you code to the C90 standard instead, you may + want to comment out the above option and uncomment the + following option. You will also want to do likewise for + other uses of the '-A(C99)' option throughout this file. */ + // -A(C90) /* strict ANSI */ + +e950 /* flag non-ANSI word or construct */ + +elib(950) + -append(950,[MISRA 2012 Rule 1.2, advisory]) + +/**** Rule 1.3 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + + /* Avoid the use of undefined or unspecified behavior as described + in ISO C, Appendix A.6.1 and Appendix A.6.2 */ + + /* Source file not ending in a new-line character, ending in + new-line character immediately preceded by a backslash + character, or ending in a partial preprocessing token or + comment (ISO C, Appendix A.6.2, point 1). + */ + +e406 /* unclosed comment */ + +elib(406) + -append(406,[MISRA 2012 Rule 1.3, required]) + + /* Non-standard character usage (ISO C, Appendix A.6.2, point 2). + */ + +e27 /* illegal character */ + +elib(27) + -append(27,[MISRA 2012 Rule 1.3, required]) + + /* Unclosed quotes (ISO C, Appendix A.6.2, point 4). + */ + +e2 /* unclosed quote */ + +elib(2) + -append(2,[MISRA 2012 Rule 1.3, required]) + + /* Repeated label within a function (ISO C, Appendix A.6.2, point + 5). + */ + +e31 /* symbol redefinition */ + +elib(31) + -append(31,[MISRA 2012 Rule 1.3, required]) + + /* Non-visible identifier used (ISO C, Appendix A.6.2, point 6). + */ + +e40 /* undeclared identifier */ + +elib(40) + -append(40,[MISRA 2012 Rule 1.3, required]) + + /* Identifiers for the same entity differ beyond the minimal + significant characters (ISO C, Appendix A.6.2, point 7). + See Rules 5.1, 5.2, 5.4, and 5.5. + */ + + /* The same identifier has both internal and external linkage in + the same translation unit (ISO C, Appendix A.6.2, point 8). + */ + +e401 /* symbol not previously declared static */ + +elib(401) + -append(401,[MISRA 2012 Rule 1.3, required]) + + /* Multiple definitions for the same externally linked identifier + (ISO C, Appendix A.6.2, point 9). + */ + +e31 /* symbol redefinition */ + +elib(31) + + /* Using automatic storage data via a pointer after the data's + lifetime (ISO C, Appendix A.6.2, point 10). + */ + +e604 /* returning address of auto variable */ + +elib(604) + -append(604,[MISRA 2012 Rule 1.3, required]) + +e934 /* taking address of near auto variable */ + +elib(934) + -append(934,[MISRA 2012 Rule 1.3, required]) + + /* Incompatible redeclarations (ISO C, Appendix A.6.2, point 11). + See Rule 8.3 + */ + + /* Non-standard escape sequence (ISO C, Appendix A.6.2, point 12). + */ + +e606 /* non-ANSI escape sequence */ + +elib(606) + -append(606,[MISRA 2012 Rule 1.3, required]) + + /* Non-standard character in header name (ISO C, Appendix A.6.2, + point 15). + See Rule 20.2 + */ + +e9020 /* header name with non-standard character */ + +elib(9020) + -append(9020,[MISRA 2012 Rule 1.3, required]) + + /* No complete type available (ISO C, Appendix A.6.2, point 16). + */ + +e86 /* structure has no data elements */ + +elib(86) + -append(86,[MISRA 2012 Rule 1.3, required]) + + /* Using or converting a void expression (ISO C, Appendix A.6.2, + point 17). + */ + +e64 /* type mismatch */ + +elib(64) + -append(64,[MISRA 2012 Rule 1.3, required]) + +e67 /* cannot cast between types */ + +elib(67) + -append(67,[MISRA 2012 Rule 1.3, required]) + +e144 /* non-existent return value */ + +elib(144) + -append(144,[MISRA 2012 Rule 1.3, required]) + + /* Modifying an object more than once or modifying and accessing + between two sequence points (ISO C, Appendix A.6.2, point 18). + See Rule 13.2 + */ + +e564 /* variable depends on order of evaluation */ + +elib(564) + -append(564,[MISRA 2012 Rule 1.3, required]) + + /* Invalid arithmetic operations or unrepresentable results + (ISO C, Appendix A.6.2, point 19). + */ + +e54 /* division by 0 */ + +elib(54) + -append(54,[MISRA 2012 Rule 1.3, required]) + +e414 /* possible division by 0 */ + +elib(414) + -append(414,[MISRA 2012 Rule 1.3, required]) + +e795 /* conceivable division by 0 */ + +elib(795) + -append(795,[MISRA 2012 Rule 1.3, required]) + /* Also, see Rule 12.4 */ + + /* Passing a void argument to a function (ISO C, Appendix A.6.2, + point 20). + */ + +e64 /* type mismatch */ + +elib(64) + + /* Incompatible function redeclaration (ISO C, Appendix A.6.2, + point 22). + See Rule 8.3 + */ + + /* An invalid array reference, null pointer reference, or + reference to an object declared with automatic storage duration in + a terminated block occurs (ISO C, Appendix A.6.2, point 24). + */ + +e64 /* type mismatch */ + +elib(64) + +e413 /* likely use of null pointer */ + +elib(413) + -append(413,[MISRA 2012 Rule 1.3, required]) + +e415 /* out-of-bounds pointer */ + +elib(415) + -append(415,[MISRA 2012 Rule 1.3, required]) + +e416 /* out-of-bounds pointer */ + +elib(416) + -append(416,[MISRA 2012 Rule 1.3, required]) + +e428 /* negative subscript */ + +elib(428) + -append(428,[MISRA 2012 Rule 1.3, required]) + /* Also, see Rule 17.6 */ + + /* A pointer to a function is converted to a pointer to an object + or a pointer to an object is converted to a pointer to a function + (ISO C, Appendix A.6.2, point 26). + */ + +e64 /* type mismatch */ + +elib(64) + +e740 /* unusual pointer cast */ + +elib(740) + -append(740,[MISRA 2012 Rule 1.3, required]) + /* Also, see Rule 11.1 and 11.2 */ + + /* A pointer is converted to other than an integral or pointer + type (ISO C, Appendix A.6.2, point 27). + */ + +e64 /* type mismatch */ + +elib(64) + +e71 /* cannot cast */ + +elib(71) + + /* An expression is shifted by a negative number or by an amount + greater than or equal to the width in bits of the expression being + shifted (ISO C, Appendix A.6.2, point 30). + */ + +e504 /* unusual shift */ + +elib(504) + -append(504,[MISRA 2012 Rule 1.3, required]) + + /* An identifier for an object is declared with no linkage and the + type of the object is incomplete after its declarator, or after its + init-declarator if it has an initializer (ISO C, Appendix + A.6.2, point 33). + */ + +e86 /* structure has no data elements */ + +elib(86) + + /* Declaring a function at block scope with a storage-class + specifier other than extern (ISO C, Appendix A.6.2, point 34). + */ + +e629 /* static class for function */ + +elib(629) + -append(629,[MISRA 2012 Rule 1.3, required]) + + /* A bit-field is declared with a type other than int, signed int, + or unsigned int (ISO C, Appendix A.6.2, point 35). + See Rule 6.1. + */ + + /* Attempting to modify an object with const-qualified type by + means of an lvalue with non-const-qualified type (ISO C, + Appendix A.6.2, point 36). + */ + +e158 /* assignment increases capability */ + +elib(158) + -append(158,[MISRA 2012 Rule 1.3, required]) + + /* Attempting to refer to an object with volatile-qualified type + by means of an lvalue with non-volatile-qualified type (ISO C, + Appendix A.6.2, point 37). + */ + +e158 /* assignment increases capability */ + +elib(158) + + /* Using the value of uninitialized automatic object (ISO C, + Appendix A.6.2, point 38). + See Rule 9.1 + */ + + /* An object with aggregate or union type with static storage + duration has a non-brace-enclosed initializer, or an object + with aggregate or union type with automatic storage duration + has either a single expression initializer with a type other + than that of the object or a non-brace-enclosed initializer + (ISO C, Appendix A.6.2, point 39). + Also, see Rule 9.2 + */ + +e64 /* type mismatch */ + +elib(64) + + /* The value of a function is used, but no value was returned + (ISO C, Appendix A.6.2, point 40). + See Rule 17.4. + */ + + /* A function that accepts a variable number of arguments is + defined without a parameter type list that ends with the + ellipsis notation (ISO C, Appendix A.6.2, point 41). + */ + + /* An identifier for an object with internal linkage and an + incomplete type is declared with a tentative definition (ISO C, + Appendix A.6.2, point 42). + */ + +e86 /* structure has no data elements */ + +elib(86) + + /* Non-standard #include preprocessing directive (ISO C, Appendix + A.6.2, point 44). + See Rule 20.3. + */ + + /* Non-standard #line directive (ISO C, Appendix A.6.2, point 49). + */ + +"estring(10,a numeric constant)" /* expecting a numeric constant */ + + /* #defining or #undefing any of: defined, __LINE__, __FILE__, + __DATE__, __TIME__, or __STDC__ (ISO C, Appendix A.6.2, point 50). + */ + +e136 /* illegal macro name */ + +elib(136) + -append(136,[MISRA 2012 Rule 1.3, required]) + + /* Format-argument mismatch in an fprintf or fscanf type of + function (ISO C, Appendix A.6.2, point 75). + */ + +e558 /* too few arguments */ + +elib(558) + -append(558,[MISRA 2012 Rule 1.3, required]) + +e719 /* too many arguments */ + +elib(719) + -append(719,[MISRA 2012 Rule 1.3, required]) + + /* A %% conversion specification for the fprintf or fscanf + function contains characters between the pair of % characters + (ISO C, Appendix A.6.2, point 77). + */ + +e557 /* unrecognized format */ + +elib(557) + -append(557,[MISRA 2012 Rule 1.3, required]) + + /* An aggregate or union, or a pointer to an aggregate or union is + an argument to the fprintf function, except for the conversion + specifiers %s (for an array of character type) or %p (for a pointer + to void) (ISO C, Appendix A.6.2, point 81). + */ + +e437 /* passing struct to ellipsis */ + +elib(437) + -append(437,[MISRA 2012 Rule 1.3, required]) + + /* Referring to deallocated space (ISO C, Appendix A.6.2, point + 87). + */ + +e449 /* previously deallocated pointer */ + +elib(449) + -append(449,[MISRA 2012 Rule 1.3, required]) + + /* Misuse of free or realloc (ISO C, Appendix A.6.2, point 88). + */ + +esym(424,free) /* inappropriate deallocation */ + -append(424,[MISRA 2012 Rule 1.3, required]) + + /* An array written to by a copying or concatenation function is + too small (ISO C, Appendix A.6.2, point 91). + */ + +e419 /* data overrun */ + +elib(419) + -append(419,[MISRA 2012 Rule 1.3, required]) + + /* Order of evaluation (ISO C, Appendix A.6.1, point 7). + */ + +e564 /* variable depends on order of evaluation */ + +elib(564) + -append(564,[MISRA 2012 Rule 1.3, required]) + + /* Side effects order (ISO C, Appendix A.6.1, point 8). + */ + +e931 /* both sides of an expression have side-effects */ + +elib(931) + -append(931,[MISRA 2012 Rule 1.3, required]) + + /* Function argument evaluation (ISO C, Appendix A.6.1, point 9). + */ + +e564 /* variable depends on order of evaluation */ + +elib(564) + + /* The order in which # and ## operations are evaluated during + macro substitution (ISO C, Appendix A.6.1, point 12). + */ + +e9023 /* multiple '#/##' operators in macro definition */ + +elib(9023) + -append(9023,[MISRA 2012 Rule 1.3, required]) + + /* Whether setjmp is a macro or an external identifier (ISO C, + Appendix A.6.1, point 14). + See Rule 21.2. + */ + +/**** Rule 2.1 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e506 /* constant value boolean */ + +elib(506) + -append(506,[MISRA 2012 Rule 2.1, required]) + +e527 /* unreachable */ + +elib(527) + -append(527,[MISRA 2012 Rule 2.1, required]) + +e681 /* loop not entered */ + +elib(681) + -append(681,[MISRA 2012 Rule 2.1, required]) + +e827 /* loop not reachable */ + +elib(827) + -append(827,[MISRA 2012 Rule 2.1, required]) + +/**** Rule 2.2 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e438 /* value not used */ + +elib(438) + -append(438,[MISRA 2012 Rule 2.2, required]) + +e505 /* redundant argument to comma */ + +elib(505) + -append(505,[MISRA 2012 Rule 2.2, required]) + +e520 /* highest operator has no side effects */ + +elib(520) + -append(520,[MISRA 2012 Rule 2.2, required]) + +e521 /* highest operator has no side effects */ + +elib(521) + -append(521,[MISRA 2012 Rule 2.2, required]) + +e522 /* highest operator has no side effects */ + +elib(522) + -append(522,[MISRA 2012 Rule 2.2, required]) + +/**** Rule 2.3 (Adv) ************/ + + +e751 /* local typedef not referenced */ + +elib(751) + -append(751,[MISRA 2012 Rule 2.3, advisory]) + +e756 /* global not referenced */ + +elib(756) + -append(756,[MISRA 2012 Rule 2.3, advisory]) + +/**** Rule 2.4 (Adv) ************/ + + +e753 /* local tag not referenced */ + +elib(753) + -append(753,[MISRA 2012 Rule 2.4, advisory]) + +e9058 + +elibsym(9058) + -append(9058,[MISRA 2012 Rule 2.4, advisory]) + +/**** Rule 2.5 (Adv) ************/ + + +e750 /* local macro not referenced */ + +elib(750) + -append(750,[MISRA 2012 Rule 2.5, advisory]) + +e755 /* global macro not referenced */ + +elib(755) + -append(755,[MISRA 2012 Rule 2.5, advisory]) + +/**** Rule 2.6 (Adv) ************/ + + +e563 /* label not referenced */ + +elib(563) + -append(563,[MISRA 2012 Rule 2.6, advisory]) + +/**** Rule 2.7 (Adv) ************/ + + +e715 /* not referenced */ + +elib(715) + -append(715,[MISRA 2012 Rule 2.7, advisory]) + +/**** Rule 3.1 (Req) ************/ + + -fnc /* flag nested comments */ + +e602 /* comment within comment */ + +elib(602) + -append(602,[MISRA 2012 Rule 3.1, required]) + +e9059 + +elib(9059) + -append(9059,[MISRA 2012 Rule 3.1, required]) + +e9066 + +elib(9066) + -append(9066,[MISRA 2012 Rule 3.1, required]) + +/**** Rule 3.2 (Req) ************/ + + +e427 /* C++ comment ends in \\ */ + +elib(427) + -append(427,[MISRA 2012 Rule 3.2, required]) + +/**** Rule 4.1 (Req) ************/ + + +e9039 /* prohibited escape sequence */ + +elib(9039) + -append(9039,[MISRA 2012 Rule 4.1, required]) + +/**** Rule 4.2 (Adv) ************/ + + -ftg /* inhibit use of trigraphs */ + +e584 /* activate trigraph detected message */ + +elib(584) + -append(584,[MISRA 2012 Rule 4.2, advisory]) + +e739 /* activate trigraph in string message */ + +elib(739) + -append(739,[MISRA 2012 Rule 4.2, advisory]) + +e9060 /* trigraph in comment */ + +elib(9060) + -append(9060,[MISRA 2012 Rule 4.2, advisory]) + +/**** Rule 5.1 (Req) ************/ + + -idlen(31) /* flag names identical in the first 31 characters */ + +e621 /* Identifier clash - length set by -idlen */ + +elib(621) + -append(621,[MISRA 2012 Rule 5.1, required]) + +/**** Rule 5.2 (Req) ************/ + + -idlen(31) /* flag names identical in the first 31 characters */ + +e621 /* Identifier clash - length set by -idlen */ + +elib(621) + -append(621,[MISRA 2012 Rule 5.2, required]) + +/**** Rule 5.3 (Req) ************/ + + +e578 /* enable reports of name hiding */ + +elib(578) + -append(578,[MISRA 2012 Rule 5.3, required]) + +/**** Rule 5.4 (Req) ************/ + + -idlen(31) /* flag names identical in the first 31 characters */ + +e621 /* Identifier clash - length set by -idlen */ + +elib(621) + -append(621,[MISRA 2012 Rule 5.4, required]) + +/**** Rule 5.5 (Req) ************/ + + +e123 /* macro defined with arguments */ + +elib(123) + -append(123,[MISRA 2012 Rule 5.5, required]) + -idlen(31) /* flag names identical in the first 31 characters */ + +e621 /* Identifier clash - length set by -idlen */ + +elib(621) + -append(621,[MISRA 2012 Rule 5.5, required]) + +e9061 /* non-distinct identifier */ + +elib(9061) + -append(9061,[MISRA 2012 Rule 5.5, required]) + +/**** Rule 5.6 (Req) ************/ + + +e578 /* enable reports of name hiding */ + +elib(578) + -append(578,[MISRA 2012 Rule 5.6, required]) + +e623 /* redefining the storage class of symbol */ + +elib(623) + -append(623,[MISRA 2012 Rule 5.6, required]) + +estring(9062,typedef) /* non-unique typedef */ + +elib(9062) + -append(9062(typedef),[MISRA 2012 Rule 5.6, required]) + +/**** Rule 5.7 (Req) ************/ + + +e407 /* Inconsistent use of tag */ + +elib(407) + -append(407,[MISRA 2012 Rule 5.7, required]) + +e578 /* Declaration of Symbol hides Symbol */ + +elib(578) + -append(578,[MISRA 2012 Rule 5.7, required]) + +e14 /* Symbol previously defined */ + +elib(14) + -append(14,[MISRA 2012 Rule 5.7, required]) + +e15 /* Symbol redeclared */ + +elib(15) + -append(15,[MISRA 2012 Rule 5.7, required]) + +e631 /* Tag defined differently */ + +elib(631) + -append(631,[MISRA 2012 Rule 5.7, required]) + +e9062 /* non-unique tag */ + +elib(9062) + -append(9062(tag),[MISRA 2012 Rule 5.7, required]) + +/**** Rule 5.8 (Req) ************/ + + +e401 /* Symbol not previously declared static */ + +elib(401) + -append(401,[MISRA 2012 Rule 5.8, required]) + +e578 /* Declaration of Symbol hides Symbol */ + +elib(578) + -append(578,[MISRA 2012 Rule 5.8, required]) + +e580 /* enable reports of name hiding */ + +elib(580) + -append(580,[MISRA 2012 Rule 5.8, required]) + +/**** Rule 5.9 (Adv) ************/ + + +e578 /* enable reports of name hiding */ + +elib(578) + -append(578,[MISRA 2012 Rule 5.9, advisory]) + +e580 /* enable reports of name hiding */ + +elib(580) + -append(580,[MISRA 2012 Rule 5.9, advisory]) + +/**** Rule 6.1 (Req) ************/ + + +e46 /* field type should be int */ + +elib(46) + -append(46,[MISRA 2012 Rule 6.1, required]) + +e806 /* small bit field is signed rather than unsigned */ + +elib(806) + -append(806,[MISRA 2012 Rule 6.1, required]) + +/**** Rule 6.2 (Req) ************/ + + +e9088 /* named signed single-bit bit-field */ + +elib(9088) + -append(9088,[MISRA 2012 Rule 6.2, required]) + +/**** Rule 7.1 (Req) ************/ + + +e9001 /* Octal constant used */ + +elib(9001) + -append(9001,[MISRA 2012 Rule 7.1, required]) + +/**** Rule 7.2 (Req) ************/ + + +e9048 /* unsigned literal without 'U' suffix */ + +elib(9048) + -append(9048,[MISRA 2012 Rule 7.2, required]) + +/**** Rule 7.3 (Req) ************/ + + +e620 /* suspicious constant */ + +elib(620) + -append(620,[MISRA 2012 Rule 7.3, required]) + +e9057 /* "l" after "u" in literal suffix */ + +elib(9057) + -append(9057,[MISRA 2012 Rule 7.3, required]) + +/**** Rule 7.4 (Req) ************/ + + +fsc + +e489 /* attempting to modify a string literal */ + +elib(489) + -append(489,[MISRA 2012 Rule 7.4, required]) + +e1776 /* string literal not const safe */ + +elib(1776) + -append(1776,[MISRA 2012 Rule 7.4, required]) + +e1778 /* assignment of string literal not const safe */ + +elib(1778) + -append(1778,[MISRA 2012 Rule 7.4, required]) + +/**** Rule 8.1 (Req) ************/ + + +e601 /* no explicit type */ + +elib(601) + -append(601,[MISRA 2012 Rule 8.1, required]) + +e745 /* function has no explicit type */ + +elib(745) + -append(745,[MISRA 2012 Rule 8.1, required]) + +e808 /* no explicit type */ + +elib(808) + -append(808,[MISRA 2012 Rule 8.1, required]) + +e832 /* parameter has no explicit type */ + +elib(832) + -append(832,[MISRA 2012 Rule 8.1, required]) + +e939 /* return type defaults to int */ + +elib(939) + -append(939,[MISRA 2012 Rule 8.1, required]) + +/**** Rule 8.2 (Req) ************/ + + +e937 /* old-style function declaration */ + +elib(937) + -append(937,[MISRA 2012 Rule 8.2, required]) + +e745 /* function has no explicit type */ + +elib(745) + -append(745,[MISRA 2012 Rule 8.2, required]) + +e939 /* return type defaults to int */ + +elib(939) + -append(939,[MISRA 2012 Rule 8.2, required]) + -fvr /* varying return mode not allowed */ + -strong() /* enable strong typing for + declarations */ + +e18 /* symbol redeclared */ + +elib(18) + -append(18,[MISRA 2012 Rule 8.2, required]) + + +e936 /* old-style function definition */ + +elib(936) + -append(936,[MISRA 2012 Rule 8.2, required]) + + +e955 /* param name missing from prototype */ + +elib(955) + -append(955,[MISRA 2012 Rule 8.2, required]) + +/**** Rule 8.3 (Req) ************/ + + -fvr /* varying return mode not allowed */ + -strong() /* enable strong typing for declarations */ + +e18 /* symbol redeclared */ + +elib(18) + -append(18,[MISRA 2012 Rule 8.3, required]) + +e516 /* argument type conflict */ + +elib(516) + -append(516,[MISRA 2012 Rule 8.3, required]) + +e532 /* return mode of symbol inconsistent */ + +elib(532) + -append(532,[MISRA 2012 Rule 8.3, required]) + +e9072 /* parameter list differs */ + +elib(9072) + -append(9072,[MISRA 2012 Rule 8.3, required]) + +/**** Rule 8.4 (Req) ************/ + + +e15 /* symbol redeclared */ + +elib(15) + -append(15,[MISRA 2012 Rule 8.4, required]) + +e64 /* flag type mismatch */ + +elib(64) + -append(64,[MISRA 2012 Rule 8.4, required]) + +e516 /* argument type mismatch */ + +elib(516) + -append(516,[MISRA 2012 Rule 8.4, required]) + +e9075 /* extern defined without prior declaration */ + +elib(9075) + -append(9075,[MISRA 2012 Rule 8.4, required]) + +/**** Rule 8.5 (Req) ************/ + + +e9004 /* object/function previously declared */ + +elib(9004) + -append(9004,[MISRA 2012 Rule 8.5, required]) + +/**** Rule 8.6 (Req) ************/ + + --fmd /* diallow multiple definitions */ + +e14 /* Symbol previously defined */ + +elib(14) + -append(14,[MISRA 2012 Rule 8.6, required]) + +/**** Rule 8.7 (Adv) ************/ + + +e765 /* could be made static */ + +elib(765) + -append(765,[MISRA 2012 Rule 8.7, advisory]) + +/**** Rule 8.8 (Req) ************/ + + +e839 /* storage class assumed static */ + +elib(839) + -append(839,[MISRA 2012 Rule 8.8, required]) + +/**** Rule 8.9 (Adv) ************/ + + +e9003 /* could define variable at block scope */ + +elib(9003) + -append(9003,[MISRA 2012 Rule 8.9, advisory]) + +/**** Rule 8.10 (Req) ************/ + + +e695 /* inline function without storage-class specifier */ + +elib(695) + -append(695,[MISRA 2012 Rule 8.10, required]) + +estring(9056,extern) /* inline function defined with extern */ + -append(9056,[MISRA 2012 Rule 8.10, required]) + +/**** Rule 8.11 (Adv) ************/ + + +e9067 /* array has no dimension or initializer */ + +elib(9067) + -append(9067,[MISRA 2012 Rule 8.11, advisory]) + +/**** Rule 8.12 (Req) ************/ + + +e488 /* duplicate enumerator values */ + +elib(488) + -append(488,[MISRA 2012 Rule 8.12, required]) + +/**** Rule 8.13 (Adv) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e818 /* pointer could be declared pointing to const */ + +elib(818) + -append(818,[MISRA 2012 Rule 8.13, advisory]) + +e844 /* pointer could be declared pointing to const */ + +elib(844) + -append(844,[MISRA 2012 Rule 8.13, advisory]) + +e954 /* pointer could be declared pointing to const */ + +elib(954) + -append(954,[MISRA 2012 Rule 8.13, advisory]) + +/**** Rule 8.14 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(keyword,restrict,[MISRA 2012 Rule 8.14, required]) + +/**** Rule 9.1 (Mand) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e644 /* Symbol may not have been initialized */ + +elib(644) + -append(644,[MISRA 2012 Rule 9.1, mandatory]) + +e771 /* Symbol conceivably not initialized */ + +elib(771) + -append(771,[MISRA 2012 Rule 9.1, mandatory]) + +e530 /* Symbol not initialized */ + +elib(530) + -append(530,[MISRA 2012 Rule 9.1, mandatory]) + -specific(+e644 +e771 +e530,) + +/**** Rule 9.2 (Req) ************/ + + +e9069 /* omitted braces within an initializer */ + +elib(9069) + -append(9069,[MISRA 2012 Rule 9.2, required]) + +/**** Rule 9.3 (Req) ************/ + + +e9068 /* too few initializers */ + +elib(9068) + -append(9068,[MISRA 2012 Rule 9.3, required]) + +/**** Rule 9.4 (Req) ************/ + + +e485 /* duplicate initialization */ + +elib(485) + -append(485,[MISRA 2012 Rule 9.4, required]) + +/**** Rule 9.5 (Req) ************/ + + +e9054 /* designated initializer and dimensionless array */ + +elib(9054) + -append(9054,[MISRA 2012 Rule 9.5, required]) + +/**** Rule 10.1 (Req) ************/ + + +e48 /* bad type */ + +elib(48) + -append(48,[MISRA 2012 Rule 10.1, required]) + +e9027 /* unpermitted operand */ + +elib(9027) + -append(9027,[MISRA 2012 Rule 10.1, required]) + +/**** Rule 10.2 (Req) ************/ + + +e9028 /* unpermitted arithmetic */ + +elib(9028) + -append(9028,[MISRA 2012 Rule 10.2, required]) + +/**** Rule 10.3 (Req) ************/ + + +e9034 /* expression assigned to narrower or different essential type */ + +elib(9034) + // Note: the following -d options for true and false don't apply + // to C90 and should be commented out if not using C99 + +"dtrue=/*lint -save -e921 */(_Bool) 1/*lint -restore */" // exception + +"dfalse=/*lint -save -e921 */(_Bool) 0/*lint -restore */" // exception + -append(9034,[MISRA 2012 Rule 10.3, required]) + +/**** Rule 10.4 (Req) ************/ + + +e9029 /* mismatched essential type */ + +elib(9029) + -append(9029,[MISRA 2012 Rule 10.4, required]) + +/**** Rule 10.5 (Adv) ************/ + + +e9030 /* impermissible cast */ + +elib(9030) + -append(9030,[MISRA 2012 Rule 10.5, advisory]) + +/**** Rule 10.6 (Req) ************/ + + +e9031 /* composite expression assigned to wider essential type */ + +elib(9031) + -append(9031,[MISRA 2012 Rule 10.6, required]) + +/**** Rule 10.7 (Req) ************/ + + +e9032 /* composite expression with smaller essential type than other operand*/ + +elib(9032) + -append(9032,[MISRA 2012 Rule 10.7, required]) + +/**** Rule 10.8 (Req) ************/ + + +e9033 /* impermissible cast of composite expression */ + +elib(9033) + -append(9033,[MISRA 2012 Rule 10.8, required]) + +/**** Rule 11.1 (Req) ************/ + + +e9074 /* conversion between a pointer to function and another type */ + +elib(9074) + --emacro((9074),NULL) /* explicit exception */ + -append(9074,[MISRA 2012 Rule 11.1, required]) + +/**** Rule 11.2 (Req) ************/ + + +e9076 /* conversion between a pointer to incomplete type and another type */ + +elib(9076) + --emacro((9076),NULL) /* explicit exception */ + -append(9076,[MISRA 2012 Rule 11.2, required]) + +/**** Rule 11.3 (Req) ************/ + + +e9087 /* cast from pointer to pointer */ + +elib(9087) + -append(9087,[MISRA 2012 Rule 11.3, required]) + +/**** Rule 11.4 (Adv) ************/ + + +e9078 /* cast pointer/integer */ + +elib(9078) + -append(9078,[MISRA 2012 Rule 11.4, advisory]) + +/**** Rule 11.5 (Adv) ************/ + + +e9079 /* cast from pointer to pointer */ + +elib(9079) + -append(9079,[MISRA 2012 Rule 11.5, advisory]) + +/**** Rule 11.6 (Req) ************/ + + +e923 /* cast pointer/non-pointer */ + +elib(923) + -append(923,[MISRA 2012 Rule 11.6, required]) + +/**** Rule 11.7 (Req) ************/ + + +e68 /* cast pointer/float */ + +elib(68) + -append(68,[MISRA 2012 Rule 11.7, required]) + +e70 /* cast pointer/float */ + +elib(70) + -append(70,[MISRA 2012 Rule 11.7, required]) + +/**** Rule 11.8 (Req) ************/ + + +e9005 /* attempt to cast away const/volatile from pointer or reference */ + +elib(9005) + -append(9005,[MISRA 2012 Rule 11.8, required]) + +/**** Rule 11.9 (Req) ************/ + + +e910 /* conversion from 0 to pointer */ + +elib(910) + --emacro((910),NULL) /* explicit exception */ + -append(910,[MISRA 2012 Rule 11.9, required]) + +e9080 /* integer null pointer constant */ + +elib(9080) + -append(9080,[MISRA 2012 Rule 11.9, required]) + +/**** Rule 12.1 (Adv) ************/ + + +e9050 /* dependence placed on precedence */ + +elib(9050) + -append(9050,[MISRA 2012 Rule 12.1, advisory]) + +/**** Rule 12.2 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e598 /* excessive left shift */ + +elib(598) + -append(598,[MISRA 2012 Rule 12.2, required]) + +e9053 /* shift value exceeds size of LHS */ + +elib(9053) + -append(9053,[MISRA 2012 Rule 12.2, required]) + +/**** Rule 12.3 (Adv) ************/ + + +e9008 /* comma operator used */ + +elib(9008) + -append(9008,[MISRA 2012 Rule 12.3, advisory]) + +/**** Rule 12.4 (Adv) ************/ + + +elib(648) /* Overflow in computing constant */ + +estring(648,unsigned addition) + +estring(648,unsigned multiplication) + +estring(648,unsigned sub.) + +estring(648,unsigned shift left) + +estring(648,unsigned shift right) + -append(648,[MISRA 2012 Rule 12.4, advisory]) + +/**** Rule 13.1 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e446 /* side effect in initializer */ + +elib(446) + -append(446,[MISRA 2012 Rule 13.1, required]) + +/**** Rule 13.2 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e564 /* variable depends on order of evaluation */ + +elib(564) + -append(564,[MISRA 2012 Rule 13.2, required]) + +e864 /* variable possibly depends on order of evaluation */ + +elib(864) + -append(864,[MISRA 2012 Rule 13.2, required]) + +e931 /* both sides have side effects */ + +elib(931) + -append(931,[MISRA 2012 Rule 13.2, required]) + +/**** Rule 13.3 (Adv) ************/ + + +e9049 /* increment/decrement combined with other operations */ + +elib(9049) + -append(9049,[MISRA 2012 Rule 13.3, advisory]) + +/**** Rule 13.4 (Adv) ************/ + + +e720 /* Boolean test of assignment */ + +elib(720) + -append(720,[MISRA 2012 Rule 13.4, advisory]) + +e820 /* Boolean test of parenthesized assignment */ + +elib(820) + -append(820,[MISRA 2012 Rule 13.4, advisory]) + +e9084 /* assignment used inside larger + expression */ + +elib(9084) + -append(9084,[MISRA 2012 Rule 13.4, advisory]) + +/**** Rule 13.5 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e9007 /* side effects on right hand side of logical operator */ + +elib(9007) + -append(9007,[MISRA 2012 Rule 13.5, required]) + +/**** Rule 13.6 (Mand) ************/ + + +e9006 /* sizeof used with expression with side effect */ + +elib(9006) + -append(9006,[MISRA 2012 Rule 13.6, mandatory]) + +e9089 /* potential side-effect in argument to sizeof */ + +elib(9089) + -append(9089,[MISRA 2012 Rule 13.6, mandatory]) + +/**** Rule 14.1 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e9009 /* floating point variable used as loop counter */ + +elib(9009) + -append(9009,[MISRA 2012 Rule 14.1, required]) + +/**** Rule 14.2 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e850 /* index variable modified in body of for loop */ + +elib(850) + -append(850,[MISRA 2012 Rule 14.2, required]) + +/**** Rule 14.3 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e685 /* relational always evaluates to true/false */ + +elib(685) + -append(685,[MISRA 2012 Rule 14.3, required]) + +e774 /* boolean always evaluates to true/false */ + +elib(774) + -append(774,[MISRA 2012 Rule 14.3, required]) + +e650 /* constant out of range for operator */ + +elib(650) + -append(650,[MISRA 2012 Rule 14.3, required]) + +/**** Rule 14.4 (Req) ************/ + + +e9036 /* condition should have essentially Boolean type */ + +elib(9036) + -append(9036,[MISRA 2012 Rule 14.4, required]) + +/**** Rule 15.1 (Adv) ************/ + + +e801 /* use of 'goto' is deprecated */ + +elib(801) + -append(801,[MISRA 2012 Rule 15.1, advisory]) + +/**** Rule 15.2 (Req) ************/ + + +e9064 /* goto references earlier label */ + +elib(9064) + -append(9064,[MISRA 2012 Rule 15.2, required]) + +/**** Rule 15.3 (Req) ************/ + + +e9041 /* goto not nested in the same block as label */ + +elib(9041) + -append(9041,[MISRA 2012 Rule 15.3, required]) + +/**** Rule 15.4 (Adv) ************/ + + +e9011 /* more than one 'break' terminates loop */ + +elib(9011) + -append(9011,[MISRA 2012 Rule 15.4, advisory]) + +/**** Rule 15.5 (Adv) ************/ + + +e904 /* return before function end */ + +elib(904) + -append(904,[MISRA 2012 Rule 15.5, advisory]) + +/**** Rule 15.6 (Req) ************/ + + +e9012 /* sub-statement should be a compound statement */ + +elib(9012) + -append(9012,[MISRA 2012 Rule 15.6, required]) + +/**** Rule 15.7 (Req) ************/ + + +e9013 /* no 'else' at end of 'if ... else if' chain */ + +elib(9013) + -append(9013,[MISRA 2012 Rule 15.7, required]) + +e9063 /* no comment or action in else-branch */ + +elib(9063) + -append(9063,[MISRA 2012 Rule 15.7, required]) + +/**** Rule 16.1 (Req) ************/ + + +e616 /* control flows into case/default */ + +elib(616) + -append(616,[MISRA 2012 Rule 16.1, required]) + +e744 /* switch statement has no default */ + +elib(744) + -append(744,[MISRA 2012 Rule 16.1, required]) + +e764 /* switch does not have a case */ + +elib(764) + -append(764,[MISRA 2012 Rule 16.1, required]) + +e825 /* control flows into case/default without -fallthrough comment */ + +elib(825) + -append(825,[MISRA 2012 Rule 16.1, required]) + +e9014 /* default missing from switch */ + +elib(9014) + -append(9014,[MISRA 2012 Rule 16.1, required]) + +e9042 /* departure from MISRA switch syntax */ + +elib(9042) + -append(9042,[MISRA 2012 Rule 16.1, required]) + +e9077 /* missing unconditional break */ + +elib(9077) + -append(9077,[MISRA 2012 Rule 16.1, required]) + +e9081 /* too few independent cases for switch */ + +elib(9081) + -append(9081,[MISRA 2012 Rule 16.1, required]) + +e9082 /* switch statement should either begin or end with default label */ + +elib(9082) + -append(9082,[MISRA 2012 Rule 16.1, required]) + +e9085 /* statement or comment should appear in default case */ + +elib(9085) + -append(9085,[MISRA 2012 Rule 16.1, required]) + +/**** Rule 16.2 (Req) ************/ + + +e44 /* Need a switch */ + +elib(44) + -append(44,[MISRA 2012 Rule 16.2, required]) + +e9055 /* enclosing statement is not a switch */ + +elib(9055) + -append(9055,[MISRA 2012 Rule 16.2, required]) + +/**** Rule 16.3 (Req) ************/ + + +e616 /* control flows into case/default */ + +elib(616) + -append(616,[MISRA 2012 Rule 16.3, required]) + +e825 /* control flows into case/default without -fallthrough comment */ + +elib(825) + -append(825,[MISRA 2012 Rule 16.3, required]) + +e9077 /* missing unconditional break */ + +elib(9077) + -append(9077,[MISRA 2012 Rule 16.3, required]) + +e9090 /* missing unconditional break */ + +elib(9090) + -append(9090,[MISRA 2012 Rule 16.3, required]) + +/**** Rule 16.4 (Req) ************/ + + +e744 /* switch statement has no default */ + +elib(744) + -append(744,[MISRA 2012 Rule 16.4, required]) + +e9014 /* switch statement has no default */ + +elib(9014) + -append(9014,[MISRA 2012 Rule 16.4, required]) + +e9085 /* default case has no statement nor comment */ + +elib(9085) + -append(9085,[MISRA 2012 Rule 16.4, required]) + +/**** Rule 16.5 (Req) ************/ + + +e9082 /* default should be first or last */ + +elib(9082) + -append(9082,[MISRA 2012 Rule 16.5, required]) + +/**** Rule 16.6 (Req) ************/ + + +e764 /* switch does not have a case */ + +elib(764) + -append(764,[MISRA 2012 Rule 16.6, required]) + +e9081 /* too few cases */ + +elib(9081) + -append(9081,[MISRA 2012 Rule 16.6, required]) + +/**** Rule 16.7 (Req) ************/ + + +e483 /* boolean value in switch expression */ + +elib(483) + -append(483,[MISRA 2012 Rule 16.7, required]) + +/**** Rule 17.1 (Req) ************/ + + +e829 /* warn on header usage */ + +elib(829) + +headerwarn(stdarg.h) + -append(829(stdarg.h),[MISRA 2012 Rule 17.1, required]) + -deprecate(macro,va_arg,[MISRA 2012 Rule 17.1, required]) + -deprecate(macro,va_start,[MISRA 2012 Rule 17.1, required]) + -deprecate(macro,va_end,[MISRA 2012 Rule 17.1, required]) + -deprecate(macro,va_copy,[MISRA 2012 Rule 17.1, required]) + +/**** Rule 17.2 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e9070 + -append(9070,[MISRA 2012 Rule 17.2, required]) + +/**** Rule 17.3 (Mand) ************/ + + +e718 /* symbol undeclared, assumed to return int */ + +elib(718) + -append(718,[MISRA 2012 Rule 17.3, mandatory]) + +/**** Rule 17.4 (Mand) ************/ + + +e533 /* function should return a value */ + +elib(533) + -append(533,[MISRA 2012 Rule 17.4, mandatory]) + +/**** Rule 17.5 (Adv) ************/ + + /* MISRA has declared this rule to be "undecidable". */ + +/**** Rule 17.6 (Mand) ************/ + + +e9043 /* static between brackets of array declaration */ + +elib(9043) + -append(9043,[MISRA 2012 Rule 17.6, mandatory]) + +/**** Rule 17.7 (Req) ************/ + + +e534 /* ignoring return value of function */ + +elib(534) + -append(534,[MISRA 2012 Rule 17.7, required]) + +/**** Rule 17.8 (Adv) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e9044 /* function parameter modified */ + +elib(9044) + -append(9044,[MISRA 2012 Rule 17.8, advisory]) + +/**** Rule 18.1 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e415 /* out-of-bounds pointer */ + +elib(415) + -append(415,[MISRA 2012 Rule 18.1, required]) + +e416 /* out-of-bounds pointer */ + +elib(416) + -append(416,[MISRA 2012 Rule 18.1, required]) + +e428 /* out-of-bounds pointer */ + +elib(428) + -append(428,[MISRA 2012 Rule 18.1, required]) + +e661 /* out-of-bounds pointer */ + +elib(661) + -append(661,[MISRA 2012 Rule 18.1, required]) + +e662 /* out-of-bounds pointer */ + +elib(662) + -append(662,[MISRA 2012 Rule 18.1, required]) + +e676 /* out-of-bounds pointer */ + +elib(676) + -append(676,[MISRA 2012 Rule 18.1, required]) + +e796 /* out-of-bounds pointer */ + +elib(796) + -append(796,[MISRA 2012 Rule 18.1, required]) + +e797 /* out-of-bounds pointer */ + +elib(797) + -append(797,[MISRA 2012 Rule 18.1, required]) + +e817 /* out-of-bounds pointer */ + +elib(817) + -append(817,[MISRA 2012 Rule 18.1, required]) + +/**** Rule 18.2 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e946 /* relational or subtract operator applied to pointers */ + +elib(946) + -append(946,[MISRA 2012 Rule 18.2, required]) + +e947 /* relational or subtract operator applied to pointers */ + +elib(947) + -append(947,[MISRA 2012 Rule 18.2, required]) + +/**** Rule 18.3 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e946 /* relational or subtract operator applied to pointers */ + +elib(946) + -append(946,[MISRA 2012 Rule 18.3, required]) + +e947 /* relational or subtract operator applied to pointers */ + +elib(947) + -append(947,[MISRA 2012 Rule 18.3, required]) + +/**** Rule 18.4 (Adv) ************/ + + +e9016 /* pointer arithmetic other than array indexing used */ + +elib(9016) + -append(9016,[MISRA 2012 Rule 18.4, advisory]) + +/**** Rule 18.5 (Adv) ************/ + + +e9025 /* more than two pointer indirection levels used */ + +elib(9025) + -append(9025,[MISRA 2012 Rule 18.5, advisory]) + +/**** Rule 18.6 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e733 /* assigning address of auto to outer scope symbol */ + +elib(733) + -append(733,[MISRA 2012 Rule 18.6, required]) + +e789 /* assigning address of auto to static */ + +elib(789) + -append(789,[MISRA 2012 Rule 18.6, required]) + +e604 /* returning address of auto variable */ + +elib(604) + -append(604,[MISRA 2012 Rule 18.6, required]) + +/**** Rule 18.7 (Req) ************/ + + +e9038 /* flexible array member declared */ + +elib(9038) + -append(9038,[MISRA 2012 Rule 18.7, required]) + +/**** Rule 18.8 (Req) ************/ + + +e9035 /* variable length array declared */ + +elib(9035) + -append(9035,[MISRA 2012 Rule 18.8, required]) + +/**** Rule 19.1 (Mand) ************/ + + /* MISRA has declared this rule to be "undecidable". */ + +/**** Rule 19.2 (Adv) ************/ + + +e9018 /* union type/object declared */ + +elib(9018) + -append(9018,[MISRA 2012 Rule 19.2, advisory]) + +/**** Rule 20.1 (Adv) ************/ + + +e9019 /* declaration before #include */ + +elib(9019) + -append(9019,[MISRA 2012 Rule 20.1, advisory]) + +/**** Rule 20.2 (Req) ************/ + + +e9020 /* header file name with non-standard character */ + +elib(9020) + -append(9020,[MISRA 2012 Rule 20.2, required]) + /* Note: If your system requires the '\' be used as a directory + separator, uncomment the following option. + */ + // -estring(9020,\) + +/**** Rule 20.3 (Req) ************/ + + +e12 /* Need < or " after #include */ + +elib(12) + -append(12,[MISRA 2012 Rule 20.3, required]) + +e9086 /* multiple arguments after #include */ + +elib(9086) + -append(9086,[MISRA 2012 Rule 20.3, required]) + +/**** Rule 20.4 (Req) ************/ + + +e9051 /* macro with same name as a keyword */ + +elib(9051) + -append(9051,[MISRA 2012 Rule 20.4, required]) + +/**** Rule 20.5 (Adv) ************/ + + +e9021 /* use of '#undef' is discouraged */ + +elib(9021) + -append(9021,[MISRA 2012 Rule 20.5, advisory]) + +/**** Rule 20.6 (Req) ************/ + + +e436 /* preprocessor directive in invocation of macro */ + +elib(436) + -append(436,[MISRA 2012 Rule 20.6, required]) + +/**** Rule 20.7 (Req) ************/ + + +e665 /* expression passed to unparenthesized macro */ + +elib(665) + -append(665,[MISRA 2012 Rule 20.7, required]) + +/**** Rule 20.8 (Req) ************/ + + +e9037 /* conditional of #if/#elif does not evaluate to 0 or 1 */ + +elib(9037) + -append(9037,[MISRA 2012 Rule 20.8, required]) + +/**** Rule 20.9 (Req) ************/ + + +e553 /* Undefined preprocessor variable, assumed 0 */ + +elib(553) + -append(553,[MISRA 2012 Rule 20.9, required]) + +/**** Rule 20.10 (Adv) ************/ + + +e9024 /* '#/##' operators used */ + +elib(9024) + -append(9024,[MISRA 2012 Rule 20.10, advisory]) + +/**** Rule 20.11 (Req) ************/ + + +e484 /* stringize operator followed by macro parameter followed by pasting operator */ + +elib(484) + -append(484,[MISRA 2012 Rule 20.11, required]) + +/**** Rule 20.12 (Req) ************/ + + +e9015 /* macro argument is used both with and without '#/##' and is subject to further replacement */ + +elib(9015) + -append(9015,[MISRA 2012 Rule 20.12, required]) + +/**** Rule 20.13 (Req) ************/ + + +e544 /* endif or else not followed by EOL */ + +elib(544) + -append(544,[MISRA 2012 Rule 20.13, required]) + +e16 /* # directive not followed by recognizable word */ + +elib(16) + -append(16,[MISRA 2012 Rule 20.13, required]) + /* other parts of this rule such as a syntax check of the disabled + portions of the code do not seem to be statically checkable + */ + +/**** Rule 20.14 (Req) ************/ + + +e405 /* #if/#ifdef/#ifndef not closed off */ + +elib(405) + -append(405,[MISRA 2012 Rule 20.14, required]) + +/**** Rule 21.1 (Req) ************/ + + +e136 /* Illegal macro name */ + +elib(136) + -append(136,[MISRA 2012 Rule 21.1, required]) + /* Undefining standard library macros is covered by rule 20.5. */ + /* Defining/redefining reserved/standard identifiers is covered + by rules 20.4 and 21.2. + */ + +e9071 /* defined macro reserved to the compiler */ + +elib(9071) + -append(9071,[MISRA 2012 Rule 21.1, required]) + // explicit exemptions + -estring(9071,* because *) + -estring(9071,cerf) + -estring(9071,cerfc) + -estring(9071,cexp2) + -estring(9071,cexpm1) + -estring(9071,clog10) + -estring(9071,clog1p) + -estring(9071,clog2) + -estring(9071,clgamma) + -estring(9071,ctgamma) + -estring(9071,cerff) + -estring(9071,cerfcf) + -estring(9071,cexp2f) + -estring(9071,cexpm1f) + -estring(9071,clog10f) + -estring(9071,clog1pf) + -estring(9071,clog2f) + -estring(9071,clgammaf) + -estring(9071,ctgammaf) + -estring(9071,cerfl) + -estring(9071,cerfcl) + -estring(9071,cexp2l) + -estring(9071,cexpm1l) + -estring(9071,clog10l) + -estring(9071,clog1pl) + -estring(9071,clog2l) + -estring(9071,clgammal) + -estring(9071,ctgammal) + -estring(9071,E0*) + -estring(9071,E1*) + -estring(9071,E2*) + -estring(9071,E3*) + -estring(9071,E4*) + -estring(9071,E5*) + -estring(9071,E6*) + -estring(9071,E7*) + -estring(9071,E8*) + -estring(9071,E9*) + -estring(9071,NDEBUG) + -estring(9071,PRIa*) + -estring(9071,PRIb*) + -estring(9071,PRIc*) + -estring(9071,PRId*) + -estring(9071,PRIe*) + -estring(9071,PRIf*) + -estring(9071,PRIg*) + -estring(9071,PRIh*) + -estring(9071,PRIi*) + -estring(9071,PRIj*) + -estring(9071,PRIk*) + -estring(9071,PRIl*) + -estring(9071,PRIm*) + -estring(9071,PRIn*) + -estring(9071,PRIo*) + -estring(9071,PRIp*) + -estring(9071,PRIq*) + -estring(9071,PRIr*) + -estring(9071,PRIs*) + -estring(9071,PRIt*) + -estring(9071,PRIu*) + -estring(9071,PRIv*) + -estring(9071,PRIw*) + -estring(9071,PRIx*) + -estring(9071,PRIy*) + -estring(9071,PRIz*) + -estring(9071,PRIX*) + -estring(9071,SCNa*) + -estring(9071,SCNb*) + -estring(9071,SCNc*) + -estring(9071,SCNd*) + -estring(9071,SCNe*) + -estring(9071,SCNf*) + -estring(9071,SCNg*) + -estring(9071,SCNh*) + -estring(9071,SCNi*) + -estring(9071,SCNj*) + -estring(9071,SCNk*) + -estring(9071,SCNl*) + -estring(9071,SCNm*) + -estring(9071,SCNn*) + -estring(9071,SCNo*) + -estring(9071,SCNp*) + -estring(9071,SCNq*) + -estring(9071,SCNr*) + -estring(9071,SCNs*) + -estring(9071,SCNt*) + -estring(9071,SCNu*) + -estring(9071,SCNv*) + -estring(9071,SCNw*) + -estring(9071,SCNx*) + -estring(9071,SCNy*) + -estring(9071,SCNz*) + -estring(9071,SCNX*) + +e9083 /* undefined macro reserved to the compiler */ + +elib(9083) + -append(9083,[MISRA 2012 Rule 21.1, required]) + // explicit exemptions + -estring(9083,* because *) + -estring(9083,cerf) + -estring(9083,cerfc) + -estring(9083,cexp2) + -estring(9083,cexpm1) + -estring(9083,clog10) + -estring(9083,clog1p) + -estring(9083,clog2) + -estring(9083,clgamma) + -estring(9083,ctgamma) + -estring(9083,cerff) + -estring(9083,cerfcf) + -estring(9083,cexp2f) + -estring(9083,cexpm1f) + -estring(9083,clog10f) + -estring(9083,clog1pf) + -estring(9083,clog2f) + -estring(9083,clgammaf) + -estring(9083,ctgammaf) + -estring(9083,cerfl) + -estring(9083,cerfcl) + -estring(9083,cexp2l) + -estring(9083,cexpm1l) + -estring(9083,clog10l) + -estring(9083,clog1pl) + -estring(9083,clog2l) + -estring(9083,clgammal) + -estring(9083,ctgammal) + -estring(9083,E0*) + -estring(9083,E1*) + -estring(9083,E2*) + -estring(9083,E3*) + -estring(9083,E4*) + -estring(9083,E5*) + -estring(9083,E6*) + -estring(9083,E7*) + -estring(9083,E8*) + -estring(9083,E9*) + -estring(9083,NDEBUG) + -estring(9083,PRIa*) + -estring(9083,PRIb*) + -estring(9083,PRIc*) + -estring(9083,PRId*) + -estring(9083,PRIe*) + -estring(9083,PRIf*) + -estring(9083,PRIg*) + -estring(9083,PRIh*) + -estring(9083,PRIi*) + -estring(9083,PRIj*) + -estring(9083,PRIk*) + -estring(9083,PRIl*) + -estring(9083,PRIm*) + -estring(9083,PRIn*) + -estring(9083,PRIo*) + -estring(9083,PRIp*) + -estring(9083,PRIq*) + -estring(9083,PRIr*) + -estring(9083,PRIs*) + -estring(9083,PRIt*) + -estring(9083,PRIu*) + -estring(9083,PRIv*) + -estring(9083,PRIw*) + -estring(9083,PRIx*) + -estring(9083,PRIy*) + -estring(9083,PRIz*) + -estring(9083,PRIX*) + -estring(9083,SCNa*) + -estring(9083,SCNb*) + -estring(9083,SCNc*) + -estring(9083,SCNd*) + -estring(9083,SCNe*) + -estring(9083,SCNf*) + -estring(9083,SCNg*) + -estring(9083,SCNh*) + -estring(9083,SCNi*) + -estring(9083,SCNj*) + -estring(9083,SCNk*) + -estring(9083,SCNl*) + -estring(9083,SCNm*) + -estring(9083,SCNn*) + -estring(9083,SCNo*) + -estring(9083,SCNp*) + -estring(9083,SCNq*) + -estring(9083,SCNr*) + -estring(9083,SCNs*) + -estring(9083,SCNt*) + -estring(9083,SCNu*) + -estring(9083,SCNv*) + -estring(9083,SCNw*) + -estring(9083,SCNx*) + -estring(9083,SCNy*) + -estring(9083,SCNz*) + -estring(9083,SCNX*) + +/**** Rule 21.2 (Req) ************/ + + +e683 /* complain about #define standard functions */ + +elib(683) + -append(683,[MISRA 2012 Rule 21.2, required]) + /* Undefining standard library macros is covered by rule 20.5. */ + /* Defining/redefining reserved/standard identifiers is covered + by rule 20.4 and 21.2. + */ + +/**** Rule 21.3 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(function,calloc,[MISRA 2012 Rule 21.3, required]) + -deprecate(macro,calloc,[MISRA 2012 Rule 21.3, required]) + -deprecate(function,malloc,[MISRA 2012 Rule 21.3, required]) + -deprecate(macro,malloc,[MISRA 2012 Rule 21.3, required]) + -deprecate(function,realloc,[MISRA 2012 Rule 21.3, required]) + -deprecate(macro,realloc,[MISRA 2012 Rule 21.3, required]) + -deprecate(function,free,[MISRA 2012 Rule 21.3, required]) + -deprecate(macro,free,[MISRA 2012 Rule 21.3, required]) + +/**** Rule 21.4 (Req) ************/ + + +e829 /* warn on header usage */ + +elib(829) + +headerwarn(setjmp.h) + -append(829(setjmp.h),[MISRA 2012 Rule 21.4, required]) + -deprecate(function,setjmp,[MISRA 2012 Rule 21.4, required]) + -deprecate(function,longjmp,[MISRA 2012 Rule 21.4, required]) + -deprecate(macro,setjmp,[MISRA 2012 Rule 21.4, required]) + -deprecate(macro,longjmp,[MISRA 2012 Rule 21.4, required]) + +/**** Rule 21.5 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(function,signal,[MISRA 2012 Rule 21.5, required]) + -deprecate(function,raise,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIGABRT,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIGFPE,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIGILL,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIGINT,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIGSEGV,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIGTERM,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIG_DFL,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIG_ERR,[MISRA 2012 Rule 21.5, required]) + -deprecate(macro,SIG_IGN,[MISRA 2012 Rule 21.5, required]) + +e829 /* warn on header usage */ + +elib(829) + +headerwarn(signal.h) + -append(829(signal.h),[MISRA 2012 Rule 21.5, required]) + +/**** Rule 21.6 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(function,clearerr,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fclose,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,feof,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,ferror,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fflush,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fgetc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fgetpos,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fgets,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fgetwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fgetws,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fopen,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fputc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fputs,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fputwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fputws,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fread,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fseek,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fsetpos,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,freopen,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,ftell,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fwide,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fwprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fwrite,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,fwscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,getc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,getchar,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,gets,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,getwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,getwchar,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,perror,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,printf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,putc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,putchar,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,puts,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,putwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,putwchar,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,remove,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,rename,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,rewind,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,scanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,setbuf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,setvbuf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,snprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,sprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,sscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,swprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,swscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,tmpfile,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,tmpnam,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,ungetc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,ungetwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vfprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vfscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vfwprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vfwscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vsnprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vsprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vsscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vswprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vswscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vwprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,vwscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,wprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(function,wscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,clearerr,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fclose,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,feof,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,ferror,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fflush,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fgetc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fgets,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fgetpos,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fgetwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fgetws,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fopen,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fputc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fputs,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fputwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fputws,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fread,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fseek,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fsetpos,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,freopen,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,ftell,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fwide,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fwprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fwrite,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,fwscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,getc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,getchar,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,gets,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,getwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,getwchar,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,perror,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,printf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,putc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,putchar,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,puts,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,putwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,putwchar,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,remove,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,rename,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,rewind,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,scanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,setbuf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,setvbuf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,snprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,sprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,sscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,swprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,swscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,tmpfile,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,tmpnam,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,ungetc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,ungetwc,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vfprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vfscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vfwprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vfwscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vsnprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vsprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vsscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vswprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vswscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vwprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,vwscanf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,wprintf,[MISRA 2012 Rule 21.6, required]) + -deprecate(macro,wscanf,[MISRA 2012 Rule 21.6, required]) + +/**** Rule 21.7 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(function,atof,[MISRA 2012 Rule 21.7, required]) + -deprecate(function,atoi,[MISRA 2012 Rule 21.7, required]) + -deprecate(function,atol,[MISRA 2012 Rule 21.7, required]) + -deprecate(function,atoll,[MISRA 2012 Rule 21.7, required]) + -deprecate(macro,atof,[MISRA 2012 Rule 21.7, required]) + -deprecate(macro,atoi,[MISRA 2012 Rule 21.7, required]) + -deprecate(macro,atol,[MISRA 2012 Rule 21.7, required]) + -deprecate(macro,atoll,[MISRA 2012 Rule 21.7, required]) + +/**** Rule 21.8 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(function,abort,[MISRA 2012 Rule 21.8, required]) + -deprecate(function,exit,[MISRA 2012 Rule 21.8, required]) + -deprecate(function,getenv,[MISRA 2012 Rule 21.8, required]) + -deprecate(function,system,[MISRA 2012 Rule 21.8, required]) + -deprecate(macro,abort,[MISRA 2012 Rule 21.8, required]) + -deprecate(macro,exit,[MISRA 2012 Rule 21.8, required]) + -deprecate(macro,getenv,[MISRA 2012 Rule 21.8, required]) + -deprecate(macro,system,[MISRA 2012 Rule 21.8, required]) + +/**** Rule 21.9 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(function,bsearch,[MISRA 2012 Rule 21.9, required]) + -deprecate(function,qsort,[MISRA 2012 Rule 21.9, required]) + -deprecate(macro,bsearch,[MISRA 2012 Rule 21.9, required]) + -deprecate(macro,qsort,[MISRA 2012 Rule 21.9, required]) + +/**** Rule 21.10 (Req) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(macro,wcsftime,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,wcsftime,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,clock,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,clock,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,difftime,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,difftime,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,mktime,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,mktime,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,time,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,time,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,asctime,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,asctime,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,ctime,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,ctime,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,gmtime,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,gmtime,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,localtime,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,localtime,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,strftime,[MISRA 2012 Rule 21.10, required]) + -deprecate(function,strftime,[MISRA 2012 Rule 21.10, required]) + -deprecate(macro,CLOCKS_PER_SEC,[MISRA 2012 Rule 21.10, required]) + +e829 /* warn on header usage */ + +elib(829) + +headerwarn(time.h) + -append(829(time.h),[MISRA 2012 Rule 21.10, required]) + +/**** Rule 21.11 (Req) ************/ + + +e829 /* warn on header usage */ + +elib(829) + +headerwarn(tgmath.h) + -append(829(tgmath.h),[MISRA 2012 Rule 21.11, required]) + +/**** Rule 21.12 (Adv) ************/ + + +e586 /* Symbol is deprecated */ + +elib(586) + -deprecate(function,feclearexcept,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,feclearexcept,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(function,fegetexceptflag,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,fegetexceptflag,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(function,feraiseexcept,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,feraiseexcept,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(function,fesetexceptflag,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,fesetexceptflag,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(function,fetestexcept,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,fetestexcept,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,FE_INEXACT,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,FE_DIVBYZERO,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,FE_UNDERFLOW,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,FE_OVERFLOW,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,FE_INVALID,[MISRA 2012 Rule 21.12, advisory]) + -deprecate(macro,FE_ALL_EXCEPT,[MISRA 2012 Rule 21.12, advisory]) + +/**** Rule 22.1 (Req) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e429 /* custodial pointer neither free'd nor returned */ + +elib(429) + -append(429,[MISRA 2012 Rule 22.1, required]) + -function_pair(fopen,fclose) + +e480 /* no balancing call */ + +elib(480) + -append(480,[MISRA 2012 Rule 22.1, required]) + +e481 /* different balance call states */ + +elib(481) + -append(481,[MISRA 2012 Rule 22.1, required]) + +/**** Rule 22.2 (Mand) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e424 /* inappropriate deallocation */ + +elib(424) + -append(424,[MISRA 2012 Rule 22.2, mandatory]) + +e449 /* pointer previously deallocated */ + +elib(449) + -append(449,[MISRA 2012 Rule 22.2, mandatory]) + +/**** Rule 22.3 (Req) ************/ + + /* MISRA has declared this rule to be "undecidable". */ + +/**** Rule 22.4 (Mand) ************/ + + /* MISRA has declared this rule to be "undecidable". */ + +/**** Rule 22.5 (Mand) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + Software provides the following message to assist: + */ + +e9047 /* FILE pointer dereferenced */ + +elib(9047) + -append(9047,[MISRA 2012 Rule 22.5, mandatory]) + + +/**** Rule 22.6 (Mand) ************/ + + /* While MISRA has declared this rule to be "undecidable", Gimpel + * Software provides the following options to assist: + */ + +e449 /* previously deallocated pointer */ + +elib(449) + -append(449,[MISRA 2012 Rule 22.6, mandatory]) diff --git a/libm/libmcs/sw-quality/co-gcc.h b/libm/libmcs/sw-quality/co-gcc.h new file mode 100644 index 00000000..92f9f995 --- /dev/null +++ b/libm/libmcs/sw-quality/co-gcc.h @@ -0,0 +1,129 @@ +// --------------------------------------------------------------------- +// This file is provided by Gimpel Software (www.gimpel.com) for use with +// its products PC-lint and FlexeLint. +// +// Redistribution and use of this file, with or without modification, is +// permitted provided that any such redistribution retains this notice. +// --------------------------------------------------------------------- + +#ifndef CO_GCC_H_ +#define CO_GCC_H_ +/*lint -save -w1 */ + +#ifdef _lint /* Make sure no compiler comes this way */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Standard library headers typically define the assert macro so that it + expands to a complicated conditional expression that uses special + funtions that Lint does not know about by default. For linting + purposes, we can simplify things a bit by forcing assert() to expand to + a call to a special function that has the appropriate 'assert' + semantics. + */ +//lint -function( __assert, __lint_assert ) +void __lint_assert( int ); +//lint ++d"assert(e)=__lint_assert(!!(e))" +//(++d makes this definition permanently immutable for the Lint run.) +//Now that we've made our own 'assert', we need to keep people from being +//punished when the marco in 'assert.h' appears not to be used: +//lint -efile(766,*assert.h) + +typedef char *__builtin_va_list; + +/*lint -e{171} */ +__builtin_va_list __lint_init_va(...); + +void __builtin_va_end( __builtin_va_list ); + /*lint +++d"__builtin_va_start(ap,parmN)=((ap)=__lint_init_va(parmN))" +++d"__builtin_va_arg(a,b)=(*( ((b) *) ( (((a) += sizeof(b)) - sizeof(b) )))" + */ + + +/* + The headers included below must be generated; For C++, generate + with: + + g++ [usual build options] -E -dM t.cpp >lint_cppmac.h + + For C, generate with: + + gcc [usual build options] -E -dM t.c >lint_cmac.h + + ...where "t.cpp" and "t.c" are empty source files. + + It's important to use the same compiler options used when compiling + project code because they can affect the existence and precise + definitions of certain predefined macros. See gcc-readme.txt for + details and a tutorial. + */ +#if defined(__cplusplus) +# include "lint_cppmac.h" // DO NOT COMMENT THIS OUT. DO NOT SUPPRESS ERROR 322. (If you see an error here, your Lint configuration is broken; check -i options and ensure that you have generated lint_cppmac.h as documented in gcc-readme.txt. Otherwise Gimpel Software cannot support your configuration.) +#else +# include "lint_cmac.h" // DO NOT COMMENT THIS OUT. DO NOT SUPPRESS ERROR 322. (If you see an error here, your Lint configuration is broken; check -i options and ensure that you have generated lint_cmac.h as documented in gcc-readme.txt. Otherwise Gimpel Software cannot support your configuration.) +#endif + +/* If the macro set given by the generated macro files must be adjusted in + order for Lint to cope, then you can make those adjustments here. + */ + +#define LINT_CO_GCC_H_GCC_VERSION ( __GNUC__ * 10000 + \ + __GNUC_MINOR__ * 100 + \ + __GNUC_PATCHLEVEL__ ) + +/* The following is a workaround for versions of GCC with bug 25717, in + which the preprocessor does not dump a #define directive for __STDC__ + when -dM is given: + http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25717 + + We know the unconditional definition of __STDC__ was introduced no + later than version 3.0; the preprocessor bug was fixed no later than + version 4.1.0. + */ +#if ( LINT_CO_GCC_H_GCC_VERSION >= 30000 && \ + LINT_CO_GCC_H_GCC_VERSION < 40100 ) +# define __STDC__ 1 +#endif + +#if !__cplusplus && !__STRICT_ANSI__ && __STDC_VERSION__ < 199901L +/* apparently, the code is compiled with -std=gnu89 (as opposed to -std=c89), + so: */ +/*lint -rw_asgn(inline,__inline) */ +#endif + +#if LINT_CO_GCC_H_GCC_VERSION >= 40300 +# define __COUNTER__ __lint__COUNTER__ +//lint +rw( *type_traits ) // Enable type traits support +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#if _lint >= 909 // For 9.00i and later: + //// __attribute__ is GCC's __attribute__: + // + //lint -rw_asgn(__attribute__,__gcc_attribute__) + //lint -rw_asgn(__attribute, __gcc_attribute__) + // + //// Prevent "__attribute__" from being defined as a macro: + // + //lint --u"__attribute__" + //lint --u"__attribute" + // + //// Because an attribute-specifier is a form of + //// declaration-modifier, and because it can appear at the + //// beginning of a decl-specifier-seq, we must enable "Early + //// Modifiers": + // + //lint +fem +#else // for 9.00h and earlier: + //lint -d__attribute__()= + //lint -d__attribute()= +#endif + +#endif /* _lint */ +/*lint -restore */ +#endif /* CO_GCC_H_ */ diff --git a/libm/libmcs/sw-quality/co-gcc.lnt b/libm/libmcs/sw-quality/co-gcc.lnt new file mode 100644 index 00000000..13187da2 --- /dev/null +++ b/libm/libmcs/sw-quality/co-gcc.lnt @@ -0,0 +1,211 @@ +/* Date Stamp */ -d"_lint_co_gcc_lnt=co-gcc.lnt modified 12-Jun-2014" +/* To document usage use: -message( "Using " _lint_co_gcc_lnt ) */ +// --------------------------------------------------------------------- +// This file is provided by Gimpel Software (www.gimpel.com) for use with +// its products PC-lint and FlexeLint. +// +// Redistribution and use of this file, with or without modification, is +// permitted provided that any such redistribution retains this notice. +// --------------------------------------------------------------------- +/* co-gcc.lnt: This is the seed file for configuring Lint for use with + GCC versions 2.95.3 and later. + + Like all compiler options files this file is intended to be used + as follows: + + lint co-gcc.lnt source-files-to-be-linted + + Some of the information that co-gcc.lnt requires needs to be furnished + with the help of the gcc system itself. The easiest way to generate + this information is to use the makefile co-gcc.mak (supplied with the + Lint distribution) in an invocation of GNU Make; for details, see the + commentary at the top of co-gcc.mak. +*/ + +-cgnu // Notifies FlexeLint that gcc is being used. + +// =========================== +// Preprocessor Configuration: ++fdi // GCC starts its #include search in the directory of the including + // file. + +++fln // Allow: + // # digit-sequence " [s-char-sequence] " new-line + // as a synonym for: + // # line digit-sequence " [s-char-sequence] " new-line + // GCC additionally allows flag values to follow the + // s-char-sequence, but currently Lint ignores them. + +-header(sw-quality/co-gcc.h) // Includes headers generated by GCC (bringing in + // predefined macros). ++libh(sw-quality/co-gcc.h) // Marks that header as library code. + +sw-quality/gcc-include-path.lnt // This .lnt file should contain --i options + // and should be generated by invoking gcc with its '-v' option. + // (GCC's implicit #include search path is presented in the output.) + // This happens automatically when 'make -f co-gcc.mak' is invoked. + +// Assertion directives (a feature of GCC's preprocessor) have been +// considered obsolete in GCC's documentation since version 3.0, so we do +// not use them here. If support for #assert is needed in the form of a +// lint option, one may use '-a#' like so: +// -a#machine(i386) // #assert's machine(i386) (SVR4 facility). + +// File extensions: +// From the GCC man page: +// +// file.cc +// file.cp +// file.cxx +// file.cpp +// file.CPP +// file.c++ +// file.C +// C++ source code that must be preprocessed. Note that in .cxx, the +// last two letters must both be literally x. Likewise, .C refers to +// a literal capital C. +// +// We emulate this with: + + +cpp(.cc) + +cpp(.cp) + +cpp(.cxx) + +cpp(.cpp) + +cpp(.c++) + // Note the exceptions: + // +cpp(.CPP) + // +cpp(.C) + // These are commented out for the default config because they seem to + // cause trouble more often than not. For starters, it is problematic + // with filesystems that are case-insensitive (which has become common + // even on some POSIX systems). + +// ============= +// Size Options: +// +fwc // wchar_t might be builtin; if so, uncomment this option. (NOTE: +// // this option needs to be set before a size option is given for +// // wchar_t; see the documentation for -sw# in the Lint manual.) + +sw-quality/size-options.lnt // This .lnt file should be generated (preferrably + // by a program created by invoking GCC with the compile options that + // are used in the compilation of the project to be linted). This + // happens automatically when 'make -f co-gcc.mak' is invoked. + + +// =========================================== +// +rw and -d options to cope with GNU syntax: ++ppw(ident) // Tolerate #ident ++ppw(warning) + +// GCC provides alternative spellings of certain keywords: ++rw(__inline) +-rw_asgn(__inline__,__inline) +-rw_asgn(__header_always_inline,__inline) +-rw_asgn(__header_inline,__inline) + +-rw_asgn(__signed__,signed) +-rw_asgn(__signed,signed) +-rw_asgn( __volatile__, volatile ) +-rw_asgn( __volatile, volatile ) ++rw(restrict) +-rw_asgn(__restrict,restrict) +-rw_asgn(__restrict__,restrict) +++d"__const=const" // gconv.h uses __const rather than const +++d"const=const" // ensure const expands to const. + +-rw_asgn( asm, _up_to_brackets ) +-rw_asgn( __asm, _up_to_brackets ) +-rw_asgn( __asm__, _up_to_brackets ) +// This re-definition of the various spellings of the asm keyword enables +// Lint to pass gracefully over expression-statements like: +// __asm __volatile ("fsqrt" : "=t" (__result) : "0" (__x)); +// But it may be necessary to suppress certain error messages that are +// triggered by tokens that are part of an assembly declaration or +// statement. For example: + + -d"__asm__(p...)=/*lint -e{19}*/ __asm__(p)" + +// ...causes Lint to be quiet about the semicolon that follows an +// __asm__() declaration. Note, the -e{N} form of suppression takes +// effect only for the forward-declaration, definition or +// [possibly-compound] statement that immediately follows. Because a +// semicolon is seen as a declaration-terminator, Error 19 will be +// re-enabled immediately after the semicolon in '__asm__(...);'. +// (The elipsis after the macro parameter p allows zero or more commas to +// appear in the operand.) +// +// If you encounter other diagnostics that appear to need suppression in +// or near assembly regions, please let us know! +// +-esym(123,__asm__) + +-rw_asgn(__alignof__,__alignof) + +// "__extension__" is GCC's way of allowing the use of non-standard +// constructs in a strict Standard-conforming mode. We don't currently +// have explicit support for it, but we can use local suppressions. For +// example, we can use -e(160) so that we will not see any Errors about +// GNU statement-expressions wrapped in __extension__(). +++d"__extension__=/*lint -e(160) */" + +++d"I=1.0f" + +++d"__null=0" ++rw(_to_semi) // needed for the two macros above. ++rw(__typeof__) // activate __typeof__ keyword +-d"__typeof=__typeof__" // an alternative to using __typeof__ + +-rw(__except) // This MS reserved word is used as an identifier ++rw( __complex__, __real__, __imag__, _Complex ) // reserved words that can be ignored. +++d"__builtin_strchr=(char*)" // permits the inline definition ... +++d"__builtin_strpbrk=(char*)" // of these functions to be linted ... +++d"__builtin_strrchr=(char*)" // without drawing a complaint +++d"__builtin_strstr=(char*)" // about the use of a non-standard name +++d"__PRETTY_FUNCTION__=___function___" // lint defines ___function___ internally +++d"__FUNCTION__=___function___" // lint defines ___function___ internally +++d"__func__=___function___" // Some C++ modes suport the implicit __func__ + // identifier. +-ident($) + +// ========================================================= +// Other options supporting GNU C/C++ syntax: ++fld // enables the processing of _L_abel _D_esignators E.g.: + // union { double d; int i; } u = { d: 3.141 }; + +// ========================================================= +// Generally useful suppressions: +-wlib(1) // sets the warning level within library headers to 1 + // (no warnings, just syntax errors). Comment out if you + // are actually linting library headers. +-elib(123) // 123 is really a warning, but it's in the "Error" range. +-elib(93) // allow newlines within quoted string arguments to macros +-elib(46) // allow bit fields to have integral types other than + // '_Bool' and 'int'. +-elibsym(628) // Suppress 628 for __builtin symbols. + +-esym(528,__huge_val,__nan,__qnan,__qnanf,__snan,__snanf) + // We don't care if we don't reference some GNU functions +-esym(528,__gnu_malloc,__gnu_calloc) + +// The following functions exhibit variable return modes. +// That is, they may equally-usefully be called for a value +// as called just for their effects. Accordingly we inhibit +// Warning 534 for these functions. +// Feel free to add to or subtract from this list. + +-esym(534,close,creat,fclose,fprintf,fputc) +-esym(534,fputs,fscanf,fseek,fwrite,lseek,memcpy,memmove,memset) +-esym(534,printf,puts,scanf,sprintf,sscanf,strcat,strcpy) +-esym(534,strncat,strncpy,unlink,write) + +// For non-ANSI compilers we suppress messages 515 and 516 +// for functions known to have variable argument lists. +// For ANSI compilers, header files should take care of this. + +-esym(515,fprintf,printf,sprintf,fscanf,scanf,sscanf) +-esym(516,fprintf,printf,sprintf,fscanf,scanf,sscanf) +-esym(1702,*operator<<,*operator>>) +-esym(534,*operator<<,*operator>>) +-esym(1055,*__builtin*) +-esym(718,*__builtin*) // The compiler does not need these ... +-esym(746,*__builtin*) // declared and it knows their prototypes. diff --git a/libm/libmcs/sw-quality/co-gcc.mak b/libm/libmcs/sw-quality/co-gcc.mak new file mode 100644 index 00000000..c82c5faf --- /dev/null +++ b/libm/libmcs/sw-quality/co-gcc.mak @@ -0,0 +1,173 @@ +# This Makefile enables the automatic generation of macro definition +# headers, --i options and size options for Lint based on command-line +# switches passed to GCC. +# +# Usage: +# +# make -f co-gcc.mak \ +# GCC_BIN='name of the gcc binary' \ +# GXX_BIN='name of the g++ binary' \ +# CFLAGS='[usual C compile switches here]' \ +# CXXFLAGS='[usual C++ compile switches here]' \ +# CPPFLAGS='[usual common preprocessor switches here]' \ +# COMMON_FLAGS='[usual C & C++ compile switches here]' \ +# +# ... where 'make' is the name of the GNU Make program on your system. +# That invocation should generate the following files: +# +# lint_cmac.h +# lint_cppmac.h +# gcc-include-path.lnt +# size-options.lnt +# +# Note, if you do not supply the options that you actually compile with, +# you may see undesired results. Examples: +# +# 1) If you usually compile with -m64 but do not pass this in the +# COMMON_FLAGS variable when you run `make -f co-gcc.mak` then Lint may +# see the wrong size options (so it may think e.g. that sizeof(void*) is +# 4, which of course is inappropriate if you compile your code in 64-bit +# mode). +# +# 2) The set of compile switches (even non-preprocessor switches like -O3) +# can affect the configuration of GCC's preprocessor, which means it can +# affect how the preprocessor views the contents of system headers (and +# hence the token sequence it generates). So if we don't see the right +# set of compile switches here then the program you Lint might not be the +# program you compile (even though the same .c and .cpp files are +# involved). +# +# See also the file gcc-readme.txt (supplied with the Lint distribution). + +COMMON_GCC_OPTS:= $(COMMON_FLAGS) $(CPPFLAGS) -Wno-long-long +# We want to enable 'long long' for the purpose of extracting the value of +# 'sizeof(long long)'; see the 'size-options.lnt' target below. + +C_OPTS:= $(CFLAGS) $(COMMON_GCC_OPTS) +CXX_OPTS:=$(CXXFLAGS) $(COMMON_GCC_OPTS) +# Note, we're not *yet* able to handle some of the header contents when +# -std=c++0x is given. + +GCC_BIN:=sparc-rtems-gcc +GXX_BIN:=sparc-rtems-g++ + +GCC:=$(GCC_BIN) $(C_OPTS) +GXX:=$(GXX_BIN) $(CXX_OPTS) + +TEMP_FILE_PREFIX:=co-gcc.mak.temp + +E:=$(TEMP_FILE_PREFIX)-empty +SIZE_GEN:=$(TEMP_FILE_PREFIX)-generate-size-options + +ECHO:=echo +TOUCH:=touch +AWK:=awk + +.PHONY: config +config: preprocessor size-options.lnt + +.PHONY: preprocessor +preprocessor: lint_cmac.h lint_cppmac.h gcc-include-path.lnt + +.PHONY: dumpConfig +dumpConfig: + echo GCC_BIN=$(GCC_BIN) + echo GXX_BIN=$(GXX_BIN) + echo CFLAGS=$(CFLAGS) + echo CXXFLAGS=$(CXXFLAGS) + echo CPPFLAGS=$(CPPFLAGS) + echo COMMON_FLAGS=$(COMMON_FLAGS) + +lint_cmac.h: + set -e ; $(TOUCH) $(E)$$$$.c ; $(GCC) -E -dM $(E)$$$$.c -o $@ ; $(RM) $(E)$$$$.c + +lint_cppmac.h: + set -e ; $(TOUCH) $(E)$$$$.cpp ; $(GXX) -E -dM $(E)$$$$.cpp -o $@ ; $(RM) $(E)$$$$.cpp + +gcc-include-path.lnt: + @# Here we make options for the #include search path. + @# Note, frameworks (a feature of Apple's GCC) are not supported + @# yet so for now we filter them out. Each remaining search + @# directory 'foo' is transformed into '--i"foo"' after + @# superfluous directory separators are removed (as well as each + @# CR character appearing immediately before a newline): + $(TOUCH) $(E)$$$$.cpp ; \ + $(GXX) -v -c $(E)$$$$.cpp >$(E)$$$$.tmp 2>&1 ; \ + <$(E)$$$$.tmp $(AWK) ' \ + BEGIN {S=0} \ + /search starts here:/ {S=1;next;} \ + S && /Library\/Frameworks/ {next;} \ + S && /^ / { \ + sub("^ ",""); \ + gsub("//*","/"); \ + sub("\xd$$",""); \ + sub("/$$",""); \ + printf("--i\"%s\"\n", $$0); \ + next; \ + } \ + S {exit;} \ + ' >gcc-include-path.lnt ; \ + $(RM) $(E)$$$$.cpp $(E)$$$$.tmp $(E)$$$$.o + @# Note, we deliberately use '--i' instead of '-i' here; the effect + @# is that the directories named with the double-dash form are + @# searched after directories named with the single-dash form. + @# (See also the entry for '--i' in section 5.7 of the Lint + @# manual.) + @# + @# We typically use '--i' when we want to name a system include + @# directory, which GCC searches only after it searches all + @# directories named in a '-I' option. The upshot is that the + @# correct search order (i.e., project includes before system + @# includes) is preserved even when double-dash-i options are given + @# before single-dash-i options. + @# + @# Also note, no harm is done if '-I' options are passed to GCC + @# here: directories named with '-I' will appear before the + @# sys-include-dirs in GCC's output, so even though Lint might then + @# see a project-include directory named with a '--i' option, that + @# directory will still be searched before the sys-includes because + @# of the ordering of '--i' options. (Just make sure you don't use + @# the double-dash form with project include dirs outside of this + @# limited & generated sub-sequence of options because this is the + @# only place where we are certain that project directories always + @# come before system directories.) + + +size-options.lnt: + @# 'echo' seems to vary in behavior with respect to its handling + @# of '\n'. (Is it a newline, or a literal backslash followed by + @# a literal 'n'? It seems to depend on your platform.) So we + @# deliberately avoid the use of explicit newline characters here. + @$(ECHO) '\ +extern "C" int printf(const char*, ...);\ +int main() {\ +printf( "-ss%zu ", sizeof(short) );\ +printf( "-si%zu ", sizeof(int) );\ +printf( "-sl%zu ", sizeof(long) );\ +printf( "-sll%zu ", sizeof(long long) );\ +printf( "-sf%zu ", sizeof(float) );\ +printf( "-sd%zu ", sizeof(double) );\ +printf( "-sld%zu ", sizeof(long double) );\ +printf( "-sp%zu ", sizeof(void*) );\ +printf( "-sw%zu ", sizeof(wchar_t) );\ +}' >$(SIZE_GEN).cc + $(GXX) $(SIZE_GEN).cc -o $(SIZE_GEN) + ./$(SIZE_GEN) >size-options.lnt + @# ... and make it newline-terminated: + @$(ECHO) "" >>size-options.lnt + $(RM) $(SIZE_GEN)* + +.PHONY: clean_temps +clean_temps: + $(RM) $(TEMP_FILE_PREFIX)* + +.PHONY: clean +clean: clean_temps + $(RM) \ + lint_cppmac.h \ + lint_cmac.h \ + gcc-include-path.lnt \ + size-options.lnt + +# vim:ts=8 + diff --git a/libm/libmcs/sw-quality/dummy_includes/config.h b/libm/libmcs/sw-quality/dummy_includes/config.h new file mode 100644 index 00000000..3ccf0998 --- /dev/null +++ b/libm/libmcs/sw-quality/dummy_includes/config.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GTDGmbH */ +/* Copyright 2020-2022 by GTD GmbH. */ + +#ifndef LIBMCS_CONFIG_H +#define LIBMCS_CONFIG_H + +#ifdef LIBMCS_FPU_DAZ + #undef LIBMCS_FPU_DAZ +#endif /* LIBMCS_FPU_DAZ */ +#ifndef LIBMCS_LONG_DOUBLE_IS_64BITS + #define LIBMCS_LONG_DOUBLE_IS_64BITS +#endif /* !LIBMCS_LONG_DOUBLE_IS_64BITS */ +#ifndef LIBMCS_WANT_COMPLEX + #define LIBMCS_WANT_COMPLEX +#endif /* !LIBMCS_WANT_COMPLEX */ + +#endif /* !LIBMCS_CONFIG_H */ diff --git a/libm/libmcs/sw-quality/gcc-include-path.lnt b/libm/libmcs/sw-quality/gcc-include-path.lnt new file mode 100644 index 00000000..3be358e7 --- /dev/null +++ b/libm/libmcs/sw-quality/gcc-include-path.lnt @@ -0,0 +1,4 @@ +--i"../gcc/gcc/ginclude/" +--i"libm/include" +--i"libm/common" +--i"sw-quality/dummy_includes" diff --git a/libm/libmcs/sw-quality/lint.sh b/libm/libmcs/sw-quality/lint.sh new file mode 100755 index 00000000..f4a41b68 --- /dev/null +++ b/libm/libmcs/sw-quality/lint.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -xe + +mkdir -p sw-quality/misra-c +find libm/common libm/complex* libm/math* -name "*.c" | grep -v "fenv.c" > sw-quality/misra-c/files.lnt +wine ~/lint-nt.exe sw-quality/std.lnt sw-quality/misra-c/files.lnt | sed 's#\\#/#g' > sw-quality/misra-c/lint.txt || true +python3 -m sqarg -c sw-quality/sqarg-config.toml diff --git a/libm/libmcs/sw-quality/lint_cmac.h b/libm/libmcs/sw-quality/lint_cmac.h new file mode 100644 index 00000000..61923dee --- /dev/null +++ b/libm/libmcs/sw-quality/lint_cmac.h @@ -0,0 +1,116 @@ +#define __DBL_MIN_EXP__ (-1021) +#define __FLT_MIN__ 1.17549435e-38F +#define __CHAR_BIT__ 8 +#define __WCHAR_MAX__ 2147483647 +#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 +#define __FLT_EVAL_METHOD__ 0 +#define __DBL_MIN_10_EXP__ (-307) +#define __FINITE_MATH_ONLY__ 0 +#define __GNUC_PATCHLEVEL__ 6 +#define __DEC64_MAX_EXP__ 385 +#define sparc 1 +#define __SHRT_MAX__ 32767 +#define __LDBL_MAX__ 1.7976931348623157e+308L +#define __UINTMAX_TYPE__ long long unsigned int +#define __DEC32_EPSILON__ 1E-6DF +#define __LDBL_MAX_EXP__ 1024 +#define __SCHAR_MAX__ 127 +#define __DBL_DIG__ 15 +#define __SIZEOF_INT__ 4 +#define __SIZEOF_POINTER__ 4 +#define __USER_LABEL_PREFIX__ +#define __STDC_HOSTED__ 1 +#define __LDBL_HAS_INFINITY__ 1 +#define __FLT_EPSILON__ 1.19209290e-7F +#define __LDBL_MIN__ 2.2250738585072014e-308L +#define __DEC32_MAX__ 9.999999E96DF +#define __SIZEOF_LONG__ 4 +#define __DECIMAL_DIG__ 17 +#define __LDBL_HAS_QUIET_NAN__ 1 +#define __GNUC__ 4 +#define __FLT_HAS_DENORM__ 1 +#define __SIZEOF_LONG_DOUBLE__ 8 +#define __BIGGEST_ALIGNMENT__ 8 +#define __DBL_MAX__ 1.7976931348623157e+308 +#define __DBL_HAS_INFINITY__ 1 +#define __DEC32_MIN_EXP__ (-94) +#define __LDBL_HAS_DENORM__ 1 +#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL +#define __DEC32_MIN__ 1E-95DF +#define __DBL_MAX_EXP__ 1024 +#define __DEC128_EPSILON__ 1E-33DL +#define __LONG_LONG_MAX__ 9223372036854775807LL +#define __SIZEOF_SIZE_T__ 4 +#define __sparc__ 1 +#define __SIZEOF_WINT_T__ 4 +#define __GXX_ABI_VERSION 1002 +#define __FLT_MIN_EXP__ (-125) +#define __DBL_MIN__ 2.2250738585072014e-308 +#define __USE_INIT_FINI__ 1 +#define __DEC128_MIN__ 1E-6143DL +#define __REGISTER_PREFIX__ +#define __DBL_HAS_DENORM__ 1 +#define __NO_INLINE__ 1 +#define __FLT_MANT_DIG__ 24 +#define __VERSION__ "4.4.6" +#define __sparc 1 +#define __DEC64_EPSILON__ 1E-15DD +#define __DEC128_MIN_EXP__ (-6142) +#define __SIZE_TYPE__ unsigned int +#define __ELF__ 1 +#define __rtems__ 1 +#define __FLT_RADIX__ 2 +#define __LDBL_EPSILON__ 2.2204460492503131e-16L +#define __SIZEOF_PTRDIFF_T__ 4 +#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF +#define __FLT_HAS_QUIET_NAN__ 1 +#define __FLT_MAX_10_EXP__ 38 +#define __LONG_MAX__ 2147483647L +#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL +#define __FLT_HAS_INFINITY__ 1 +#define __DEC64_MAX__ 9.999999999999999E384DD +#define __CHAR16_TYPE__ short unsigned int +#define __DEC64_MANT_DIG__ 16 +#define __DEC32_MAX_EXP__ 97 +#define __LDBL_MANT_DIG__ 53 +#define __DBL_HAS_QUIET_NAN__ 1 +#define __WCHAR_TYPE__ int +#define __SIZEOF_FLOAT__ 4 +#define __DEC64_MIN_EXP__ (-382) +#define __FLT_DIG__ 6 +#define __INT_MAX__ 2147483647 +#define __FLT_MAX_EXP__ 128 +#define __DBL_MANT_DIG__ 53 +#define __DEC64_MIN__ 1E-383DD +#define __WINT_TYPE__ unsigned int +#define __SIZEOF_SHORT__ 2 +#define __LDBL_MIN_EXP__ (-1021) +#define __LDBL_MAX_10_EXP__ 308 +#define __DBL_EPSILON__ 2.2204460492503131e-16 +#define __SIZEOF_WCHAR_T__ 4 +#define __DEC_EVAL_METHOD__ 2 +#define __INTMAX_MAX__ 9223372036854775807LL +#define __FLT_DENORM_MIN__ 1.40129846e-45F +#define __CHAR32_TYPE__ unsigned int +#define __FLT_MAX__ 3.40282347e+38F +#define __SIZEOF_DOUBLE__ 8 +#define __FLT_MIN_10_EXP__ (-37) +#define __INTMAX_TYPE__ long long int +#define __DEC128_MAX_EXP__ 6145 +#define __GNUC_MINOR__ 4 +#define __DEC32_MANT_DIG__ 7 +#define __DBL_MAX_10_EXP__ 308 +#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L +#define __STDC__ 1 +#define __PTRDIFF_TYPE__ int +#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD +#define __DEC128_MANT_DIG__ 34 +#define __LDBL_MIN_10_EXP__ (-307) +#define __SIZEOF_LONG_LONG__ 8 +#define __LDBL_DIG__ 15 +#define __GNUC_GNU_INLINE__ 1 +#define _GCC_LIMITS_H_ +#define _MATH_CONFIG_H +#define _LDBL_EQ_DBL +#define __ORDER_BIG_ENDIAN__ 1 +#define __BYTE_ORDER__ 1 \ No newline at end of file diff --git a/libm/libmcs/sw-quality/lint_cppmac.h b/libm/libmcs/sw-quality/lint_cppmac.h new file mode 100644 index 00000000..e22054a5 --- /dev/null +++ b/libm/libmcs/sw-quality/lint_cppmac.h @@ -0,0 +1,118 @@ +#define __DBL_MIN_EXP__ (-1021) +#define __FLT_MIN__ 1.17549435e-38F +#define __CHAR_BIT__ 8 +#define __WCHAR_MAX__ 2147483647 +#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 +#define __FLT_EVAL_METHOD__ 0 +#define __DBL_MIN_10_EXP__ (-307) +#define __FINITE_MATH_ONLY__ 0 +#define __GNUC_PATCHLEVEL__ 6 +#define __DEC64_MAX_EXP__ 385 +#define sparc 1 +#define __SHRT_MAX__ 32767 +#define __LDBL_MAX__ 1.7976931348623157e+308L +#define __UINTMAX_TYPE__ long long unsigned int +#define __DEC32_EPSILON__ 1E-6DF +#define __LDBL_MAX_EXP__ 1024 +#define __SCHAR_MAX__ 127 +#define __DBL_DIG__ 15 +#define __SIZEOF_INT__ 4 +#define __SIZEOF_POINTER__ 4 +#define __USER_LABEL_PREFIX__ +#define __STDC_HOSTED__ 1 +#define __LDBL_HAS_INFINITY__ 1 +#define __FLT_EPSILON__ 1.19209290e-7F +#define __GXX_WEAK__ 1 +#define __LDBL_MIN__ 2.2250738585072014e-308L +#define __DEC32_MAX__ 9.999999E96DF +#define __SIZEOF_LONG__ 4 +#define __DECIMAL_DIG__ 17 +#define __LDBL_HAS_QUIET_NAN__ 1 +#define __GNUC__ 4 +#define __GXX_RTTI 1 +#define __FLT_HAS_DENORM__ 1 +#define __SIZEOF_LONG_DOUBLE__ 8 +#define __BIGGEST_ALIGNMENT__ 8 +#define __DBL_MAX__ 1.7976931348623157e+308 +#define __DBL_HAS_INFINITY__ 1 +#define __DEC32_MIN_EXP__ (-94) +#define __LDBL_HAS_DENORM__ 1 +#define __cplusplus 1 +#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL +#define __DEC32_MIN__ 1E-95DF +#define __DEPRECATED 1 +#define __DBL_MAX_EXP__ 1024 +#define __DEC128_EPSILON__ 1E-33DL +#define __GNUG__ 4 +#define __LONG_LONG_MAX__ 9223372036854775807LL +#define __SIZEOF_SIZE_T__ 4 +#define __sparc__ 1 +#define __SIZEOF_WINT_T__ 4 +#define __GCC_HAVE_DWARF2_CFI_ASM 1 +#define __GXX_ABI_VERSION 1002 +#define __FLT_MIN_EXP__ (-125) +#define __DBL_MIN__ 2.2250738585072014e-308 +#define __FLT_MIN_10_EXP__ (-37) +#define __USE_INIT_FINI__ 1 +#define __DEC128_MIN__ 1E-6143DL +#define __REGISTER_PREFIX__ +#define __DBL_HAS_DENORM__ 1 +#define __NO_INLINE__ 1 +#define __FLT_MANT_DIG__ 24 +#define __VERSION__ "4.4.6" +#define __sparc 1 +#define __DEC64_EPSILON__ 1E-15DD +#define __DEC128_MIN_EXP__ (-6142) +#define __SIZE_TYPE__ unsigned int +#define __ELF__ 1 +#define __FLT_RADIX__ 2 +#define __LDBL_EPSILON__ 2.2204460492503131e-16L +#define __SIZEOF_PTRDIFF_T__ 4 +#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF +#define __FLT_HAS_QUIET_NAN__ 1 +#define __FLT_MAX_10_EXP__ 38 +#define __LONG_MAX__ 2147483647L +#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL +#define __FLT_HAS_INFINITY__ 1 +#define __DEC64_MAX__ 9.999999999999999E384DD +#define __CHAR16_TYPE__ short unsigned int +#define __DEC64_MANT_DIG__ 16 +#define __DEC32_MAX_EXP__ 97 +#define __EXCEPTIONS 1 +#define __LDBL_MANT_DIG__ 53 +#define __DBL_HAS_QUIET_NAN__ 1 +#define __WCHAR_TYPE__ int +#define __SIZEOF_FLOAT__ 4 +#define __DEC64_MIN_EXP__ (-382) +#define __FLT_DIG__ 6 +#define __INT_MAX__ 2147483647 +#define __FLT_MAX_EXP__ 128 +#define __DBL_MANT_DIG__ 53 +#define __DEC64_MIN__ 1E-383DD +#define __WINT_TYPE__ unsigned int +#define __SIZEOF_SHORT__ 2 +#define __LDBL_MIN_EXP__ (-1021) +#define __LDBL_MAX_10_EXP__ 308 +#define __DBL_EPSILON__ 2.2204460492503131e-16 +#define __rtems__ 1 +#define __SIZEOF_WCHAR_T__ 4 +#define __DEC_EVAL_METHOD__ 2 +#define __INTMAX_MAX__ 9223372036854775807LL +#define __FLT_DENORM_MIN__ 1.40129846e-45F +#define __CHAR32_TYPE__ unsigned int +#define __FLT_MAX__ 3.40282347e+38F +#define __SIZEOF_DOUBLE__ 8 +#define __INTMAX_TYPE__ long long int +#define __DEC128_MAX_EXP__ 6145 +#define __GNUC_MINOR__ 4 +#define __DEC32_MANT_DIG__ 7 +#define __DBL_MAX_10_EXP__ 308 +#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L +#define __STDC__ 1 +#define __PTRDIFF_TYPE__ int +#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD +#define __DEC128_MANT_DIG__ 34 +#define __LDBL_MIN_10_EXP__ (-307) +#define __SIZEOF_LONG_LONG__ 8 +#define __LDBL_DIG__ 15 +#define __GNUC_GNU_INLINE__ 1 diff --git a/libm/libmcs/sw-quality/options.lnt b/libm/libmcs/sw-quality/options.lnt new file mode 100644 index 00000000..d043df94 --- /dev/null +++ b/libm/libmcs/sw-quality/options.lnt @@ -0,0 +1,13 @@ +-rw(*ms) // Disable microsoft keywords huge, far, near etc +-estring(9051,__asm__) // co-gcc.lnt defines various __asm__ spellings which makes misra complain +-e830 // Disable additonal location hints for various error messages to reduce logspam + +// Output format +// ------------- +// Vim Quickfix format +//-"format= %f%(:%l%)%(:%c:%) %t %n: %m\n\n" + +// Single line format +-width(0) // don't insert line breaks (unlimited output width). +-"format= %t %n$ %f%($%l%)%($%c$%) %m" +-h1 diff --git a/libm/libmcs/sw-quality/size-options.lnt b/libm/libmcs/sw-quality/size-options.lnt new file mode 100644 index 00000000..7947166e --- /dev/null +++ b/libm/libmcs/sw-quality/size-options.lnt @@ -0,0 +1 @@ +-ss2 -si4 -sl4 -sll8 -sf4 -sd8 -sld8 -sp4 -sw4 diff --git a/libm/libmcs/sw-quality/sqarg-config.toml b/libm/libmcs/sw-quality/sqarg-config.toml new file mode 100644 index 00000000..c54245b7 --- /dev/null +++ b/libm/libmcs/sw-quality/sqarg-config.toml @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GTDGmbH +# Copyright 2024 by GTD GmbH. + +# Section PcLint +[pc-lint] +# Path to lint file +lint-file = "sw-quality/misra-c/lint.txt" + +# Separation character in lint file +lint-file-separator = "$" + +# Path bend from current working dir to pc lint working dir +# (lint path files are relative to working dir in lint.exe) +lint-dir = "." + + +# Export directory and the required type +export-path = "sw-quality/misra-c" +export-type = ".md" + +# The String merger is a algorithm who try to squeeze list of strings into less +# by compare and add padding character into different spaces +[string-merge] +min-match = 4 # Minimum matching character +padding-char = '$' # Padding character, $ is not used in PcLint output strings +ratio-threshold = 0.7 # difflib.SequenceMatcher ratio threshold +iteration = 3 # How often is iterated over the result list to find new merges diff --git a/libm/libmcs/sw-quality/std.lnt b/libm/libmcs/sw-quality/std.lnt new file mode 100644 index 00000000..64fc2b40 --- /dev/null +++ b/libm/libmcs/sw-quality/std.lnt @@ -0,0 +1,6 @@ +// Gnu C/C++ (version 2.95.3 or later), -si4 -sp4, +// Standard lint options + +sw-quality/au-misra3.lnt +sw-quality/co-gcc.lnt +sw-quality/options.lnt diff --git a/math/common.c b/libm/phoenix/common.c similarity index 99% rename from math/common.c rename to libm/phoenix/common.c index 97c772ed..8f9d3602 100644 --- a/math/common.c +++ b/libm/phoenix/common.c @@ -19,7 +19,6 @@ #include #include "common.h" - void normalizeSub(double *x, int *exp) { conv_t *conv = (conv_t *)x; diff --git a/math/common.h b/libm/phoenix/common.h similarity index 100% rename from math/common.h rename to libm/phoenix/common.h diff --git a/libm/phoenix/compatibility.c b/libm/phoenix/compatibility.c new file mode 100644 index 00000000..b19ec2e7 --- /dev/null +++ b/libm/phoenix/compatibility.c @@ -0,0 +1,49 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * Compatibility source file for libmcs header file + * + * Copyright 2025 Phoenix Systems + * Author: Mikolaj Matalowski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ +#include + + +int __fpclassifyf(float x) +{ + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x); +} + + +int __fpclassifyd(double x) +{ + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x); +} + + +float nanf(const char *) +{ + return __builtin_nanf(""); +} + + +int __signbitf(float x) +{ + return __builtin_signbitf(x); +} + + +int __signbitd(double x) +{ + return __builtin_signbit(x); +} + + +const float __inff = __builtin_inff(); +const double __infd = __builtin_inf(); diff --git a/math/complex.c b/libm/phoenix/complex.c similarity index 100% rename from math/complex.c rename to libm/phoenix/complex.c diff --git a/math/exp.c b/libm/phoenix/exp.c similarity index 93% rename from math/exp.c rename to libm/phoenix/exp.c index 77c9c76a..6226219d 100644 --- a/math/exp.c +++ b/libm/phoenix/exp.c @@ -47,6 +47,12 @@ double frexp(double x, int *exp) } +float frexpf(float x, int *exp) +{ + return (float)frexp((double)x, exp); +} + + double ldexp(double x, int exp) { if (isnan(x) != 0) { @@ -84,6 +90,12 @@ double ldexp(double x, int exp) } +float ldexpf(float x, int exp) +{ + return (float)ldexp((double)x, exp); +} + + double log(double x) { double tmp, pow, res; @@ -129,6 +141,12 @@ double log(double x) } +float logf(float x) +{ + return (float)log((double)x); +} + + double log2(double x) { return (log(x) / M_LN2); @@ -142,6 +160,12 @@ double log10(double x) } +float log10f(float x) +{ + return (float)log10((double)x); +} + + double modf(double x, double *intpart) { conv_t *conv = (conv_t *)&x; @@ -232,6 +256,12 @@ double exp(double x) } +float expf(float x) +{ + return (float)exp((double)x); +} + + double ceil(double x) { #ifdef __IEEE754_CEIL @@ -321,6 +351,12 @@ double fmod(double number, double denom) } +float fmodf(float x, float y) +{ + return (float)fmod((double)x, (double)y); +} + + double round(double x) { #ifdef __IEEE754_ROUND diff --git a/math/hyper.c b/libm/phoenix/hyper.c similarity index 88% rename from math/hyper.c rename to libm/phoenix/hyper.c index c3afb86f..b0a55509 100644 --- a/math/hyper.c +++ b/libm/phoenix/hyper.c @@ -41,6 +41,12 @@ double cosh(double x) } +float coshf(float x) +{ + return (float)cosh((double)x); +} + + double sinh(double x) { double y, f; @@ -72,6 +78,12 @@ double sinh(double x) } +float sinhf(float x) +{ + return (double)sin((double)x); +} + + double tanh(double x) { if (isnan(x) != 0) { @@ -88,3 +100,9 @@ double tanh(double x) /* cosh is never equal to zero */ return (sinh(x) / cosh(x)); } + + +float tanhf(float x) +{ + return (float)tanh((double)x); +} diff --git a/math/power.c b/libm/phoenix/power.c similarity index 97% rename from math/power.c rename to libm/phoenix/power.c index 45837430..5ea5c583 100644 --- a/math/power.c +++ b/libm/phoenix/power.c @@ -93,6 +93,12 @@ double pow(double base, double exponent) } +float powf(float x, float exp) +{ + return (float)pow((double)x, (double)exp); +} + + double sqrt(double x) { if (isnan(x) != 0) { diff --git a/math/trig.c b/libm/phoenix/trig.c similarity index 91% rename from math/trig.c rename to libm/phoenix/trig.c index 5a9e6695..834ac314 100644 --- a/math/trig.c +++ b/libm/phoenix/trig.c @@ -71,6 +71,12 @@ double cos(double x) } +float cosf(float x) +{ + return (float)cos((double)x); +} + + /* Calculates value of sine using Maclaurin series. */ double sin(double x) { @@ -129,6 +135,12 @@ double sin(double x) } +float sinf(float x) +{ + return (float)sin((double)x); +} + + double tan(double x) { double c; @@ -153,6 +165,12 @@ double tan(double x) } +float tanf(float x) +{ + return (float)tan((double)x); +} + + /* Calculates value of arc cosine using secant method */ double acos(double x) { @@ -187,6 +205,12 @@ double acos(double x) } +float acosf(float x) +{ + return (float)acos((double)x); +} + + /* Calculates value of arc sine using asin(x) = pi/2 - acos(x) relationship. */ double asin(double x) { @@ -202,6 +226,12 @@ double asin(double x) } +float asinf(float x) +{ + return (float)asin((double)x); +} + + static const double atan_wi[] = { 0.2152638534631578, 0.2152638534631578, 0.2051984637212956, 0.2051984637212956, 0.1855383974779378, 0.1855383974779378, 0.1572031671581935, 0.1572031671581935, 0.1215185706879032, 0.1215185706879032, 0.0801580871597602, @@ -244,6 +274,12 @@ double atan(double x) } +float atanf(float x) +{ + return (float)atan((double)x); +} + + double atan2(double y, double x) { if ((isnan(y) != 0) || (isnan(x) != 0)) { @@ -299,3 +335,9 @@ double atan2(double y, double x) return 0.0; } + + +float atan2f(float y, float x) +{ + return (float)atan2((double)y, (double)x); +} diff --git a/math/Makefile b/math/Makefile deleted file mode 100644 index f8f1a967..00000000 --- a/math/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for libphoenix/math -# -# Copyright 2012-2015, 2020 Phoenix Systems -# - -OBJS += $(addprefix $(PREFIX_O)math/, trig.o power.o exp.o common.o complex.o hyper.o)