From 2c4cf81ef5a8e8517066de3115af936f5d45dd6b Mon Sep 17 00:00:00 2001 From: Yohan Chatelain Date: Fri, 17 Mar 2023 15:37:50 -0400 Subject: [PATCH] Pre-release v0.9.1 (#46) --- .github/workflows/build-fuzzy.yml | 34 +- .../Dockerfile.ubuntu-20.04-0-lapack-libmath | 2 +- .../Dockerfile.ubuntu-20.04-1-python | 2 +- .../Dockerfile.ubuntu-20.04-2-numpy | 2 +- .../Dockerfile.ubuntu-20.04-2-numpy-only | 2 +- .../Dockerfile.ubuntu-20.04-3-scipy | 6 +- .../Dockerfile.ubuntu-20.04-3-scipy-only | 8 +- .../Dockerfile.ubuntu-20.04-4-sklearn | 2 +- .../build_fuzzy_libmath_dockerfile.sh | 7 +- docker/resources/libmath/Makefile | 18 +- docker/resources/libmath/fast/Makefile | 28 + .../resources/libmath/fast/src/float_const.h | 128 ++++ .../resources/libmath/fast/src/float_struct.h | 194 ++++++ .../libmath/fast/src/wrapping_script.c | 565 ++++++++++++++++++ docker/resources/libmath/set-fuzzy-libmath.py | 18 +- docker/resources/libmath/tests/Makefile | 2 + docker/resources/libmath/tests/test.py | 3 +- 17 files changed, 979 insertions(+), 42 deletions(-) create mode 100755 docker/resources/libmath/fast/Makefile create mode 100644 docker/resources/libmath/fast/src/float_const.h create mode 100644 docker/resources/libmath/fast/src/float_struct.h create mode 100755 docker/resources/libmath/fast/src/wrapping_script.c diff --git a/.github/workflows/build-fuzzy.yml b/.github/workflows/build-fuzzy.yml index c49d3e9..141f894 100644 --- a/.github/workflows/build-fuzzy.yml +++ b/.github/workflows/build-fuzzy.yml @@ -18,32 +18,32 @@ jobs: include: - NAME: Lapack + Libmath DOCKER_FROM: "" - DOCKER_TO: fuzzy_v0.8.0-lapack - DOCKER_IMAGE: verificarlo/fuzzy:v0.8.0-lapack + DOCKER_TO: fuzzy_v0.9.1-lapack + DOCKER_IMAGE: verificarlo/fuzzy:v0.9.1-lapack DOCKER_FILE: ./docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-0-lapack-libmath - NAME: Python - DOCKER_FROM: fuzzy_v0.8.0-lapack - DOCKER_TO: fuzzy_v0.8.0-lapack-python3.8.5 - DOCKER_IMAGE: verificarlo/fuzzy:v0.8.0-lapack-python3.8.5 + DOCKER_FROM: fuzzy_v0.9.1-lapack + DOCKER_TO: fuzzy_v0.9.1-lapack-python3.8.5 + DOCKER_IMAGE: verificarlo/fuzzy:v0.9.1-lapack-python3.8.5 DOCKER_FILE: ./docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-1-python - NAME: Numpy - DOCKER_FROM: fuzzy_v0.8.0-lapack-python3.8.5 - DOCKER_TO: fuzzy_v0.8.0-lapack-python3.8.5-numpy - DOCKER_IMAGE: verificarlo/fuzzy:v0.8.0-lapack-python3.8.5-numpy + DOCKER_FROM: fuzzy_v0.9.1-lapack-python3.8.5 + DOCKER_TO: fuzzy_v0.9.1-lapack-python3.8.5-numpy + DOCKER_IMAGE: verificarlo/fuzzy:v0.9.1-lapack-python3.8.5-numpy DOCKER_FILE: ./docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy - NAME: Scipy - DOCKER_FROM: fuzzy_v0.8.0-lapack-python3.8.5-numpy - DOCKER_TO: fuzzy_v0.8.0-lapack-python3.8.5-numpy-scipy - DOCKER_IMAGE: verificarlo/fuzzy:v0.8.0-lapack-python3.8.5-numpy-scipy + DOCKER_FROM: fuzzy_v0.9.1-lapack-python3.8.5-numpy + DOCKER_TO: fuzzy_v0.9.1-lapack-python3.8.5-numpy-scipy + DOCKER_IMAGE: verificarlo/fuzzy:v0.9.1-lapack-python3.8.5-numpy-scipy DOCKER_FILE: ./docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy - NAME: Scikit-Learn - DOCKER_FROM: fuzzy_v0.8.0-lapack-python3.8.5-numpy-scipy - DOCKER_TO: fuzzy_v0.8.0-lapack-python3.8.5-numpy-scipy-sklearn - DOCKER_IMAGE: verificarlo/fuzzy:v0.8.0-lapack-python3.8.5-numpy-scipy-sklearn + DOCKER_FROM: fuzzy_v0.9.1-lapack-python3.8.5-numpy-scipy + DOCKER_TO: fuzzy_v0.9.1-lapack-python3.8.5-numpy-scipy-sklearn + DOCKER_IMAGE: verificarlo/fuzzy:v0.9.1-lapack-python3.8.5-numpy-scipy-sklearn DOCKER_FILE: ./docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-4-sklearn name: ${{ matrix.NAME }} @@ -96,7 +96,7 @@ jobs: docker build ./ -t ${{ matrix.DOCKER_IMAGE }} \ -f ${{ matrix.DOCKER_FILE }} \ - --build-arg VERIFICARLO_VERSION=v0.8.0 + --build-arg VERIFICARLO_VERSION=v0.9.1 docker save ${{ matrix.DOCKER_IMAGE }} -o /tmp/${{ matrix.DOCKER_TO }}.tar @@ -117,9 +117,9 @@ jobs: runs-on: ubuntu-20.04 env: RUN_IF_CHANGED: docker - DOCKER_FROM: fuzzy_v0.8.0-lapack-python3.8.5-numpy-scipy-sklearn + DOCKER_FROM: fuzzy_v0.9.1-lapack-python3.8.5-numpy-scipy-sklearn DOCKER_IMAGE: verificarlo/fuzzy - DOCKER_FROM_TAG: v0.8.0-lapack-python3.8.5-numpy-scipy-sklearn + DOCKER_FROM_TAG: v0.9.1-lapack-python3.8.5-numpy-scipy-sklearn steps: - name: Checkout repository diff --git a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-0-lapack-libmath b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-0-lapack-libmath index 96f6f68..48d2810 100644 --- a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-0-lapack-libmath +++ b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-0-lapack-libmath @@ -1,4 +1,4 @@ -ARG VERIFICARLO_VERSION=v0.8.0 +ARG VERIFICARLO_VERSION=v0.9.1 FROM verificarlo/verificarlo:${VERIFICARLO_VERSION} # Setup build dependencies diff --git a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-1-python b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-1-python index 21c5f1e..d708bb1 100644 --- a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-1-python +++ b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-1-python @@ -1,4 +1,4 @@ -ARG VERIFICARLO_VERSION=v0.8.0 +ARG VERIFICARLO_VERSION=v0.9.1 FROM verificarlo/fuzzy:${VERIFICARLO_VERSION}-lapack # Use IEEE mode for compiling with verificarlo diff --git a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy index 56c076e..4f293cd 100644 --- a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy +++ b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy @@ -1,4 +1,4 @@ -ARG VERIFICARLO_VERSION=v0.8.0 +ARG VERIFICARLO_VERSION=v0.9.1 FROM verificarlo/fuzzy:${VERIFICARLO_VERSION}-lapack-python3.8.5 # Use IEEE mode for compiling with verificarlo diff --git a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy-only b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy-only index ea84c63..eee8334 100644 --- a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy-only +++ b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-2-numpy-only @@ -1,4 +1,4 @@ -ARG VERIFICARLO_VERSION=v0.8.0 +ARG VERIFICARLO_VERSION=v0.9.1 FROM verificarlo/fuzzy:${VERIFICARLO_VERSION}-lapack # Use IEEE mode for compiling with verificarlo diff --git a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy index 46982e4..6b0309c 100644 --- a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy +++ b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy @@ -1,4 +1,4 @@ -ARG VERIFICARLO_VERSION=v0.8.0 +ARG VERIFICARLO_VERSION=v0.9.1 FROM verificarlo/fuzzy:${VERIFICARLO_VERSION}-lapack-python3.8.5-numpy # Load backend IEEE @@ -13,7 +13,7 @@ RUN pip3 install joblib pythran pybind11 RUN cp /usr/local/bin/verificarlo-f /usr/bin/gfortran # Remove debug flag which makes flag crash -RUN sed -i "294s/.*/ llvm_options = llvm_options.replace(\"'-g'\",'') if \"'-g'\" in llvm_options else llvm_options/" $(which verificarlo) +RUN sed -i "302s/.*/ llvm_options = llvm_options.replace(\"'-g'\",'') if \"'-g'\" in llvm_options else llvm_options/" $(which verificarlo) RUN cd /opt/build/ &&\ wget https://github.com/scipy/scipy/releases/download/v1.7.3/scipy-1.7.3.tar.gz &&\ @@ -25,7 +25,7 @@ RUN cd /opt/build/ &&\ python3 setup.py build --disable-optimization -j $(nproc) install # Restore original verificarlo -RUN sed -i "294s/ llvm_options = llvm_options.replace(\"'-g'\",'') if \"'-g'\" in llvm_options else llvm_options//" $(which verificarlo) +RUN sed -i "302s/ llvm_options = llvm_options.replace(\"'-g'\",'') if \"'-g'\" in llvm_options else llvm_options//" $(which verificarlo) # Sanity check RUN python3 /tmp/scipy-sanity-check.py diff --git a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy-only b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy-only index b335146..6a9c563 100644 --- a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy-only +++ b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-3-scipy-only @@ -1,4 +1,4 @@ -ARG VERIFICARLO_VERSION=v0.8.0 +ARG VERIFICARLO_VERSION=v0.9.1 FROM verificarlo/fuzzy:${VERIFICARLO_VERSION}-numpy # Load backend IEEE @@ -12,9 +12,6 @@ RUN pip3 install joblib pythran pybind11 # Replace gfortran with verificarlo-f RUN cp /usr/local/bin/verificarlo-f /usr/bin/gfortran -# Remove debug flag which makes flag crash -RUN sed -i "294s/.*/ llvm_options = llvm_options.replace(\"'-g'\",'') if \"'-g'\" in llvm_options else llvm_options/" $(which verificarlo) - RUN cd /opt/build/ &&\ wget https://github.com/scipy/scipy/releases/download/v1.7.3/scipy-1.7.3.tar.gz &&\ tar xvf scipy-1.7.3.tar.gz &&\ @@ -24,9 +21,6 @@ RUN cd /opt/build/ &&\ LDFLAGS="--conservative -Wunused-command-line-argument" \ python3 setup.py build --disable-optimization -j $(nproc) install -# Restore original verificarlo -RUN sed -i "294s/ llvm_options = llvm_options.replace(\"'-g'\",'') if \"'-g'\" in llvm_options else llvm_options//" $(which verificarlo) - # Sanity check RUN python3 /tmp/scipy-sanity-check.py diff --git a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-4-sklearn b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-4-sklearn index 5d5c375..9c2de8f 100644 --- a/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-4-sklearn +++ b/docker/base/ubuntu-20.04/Dockerfile.ubuntu-20.04-4-sklearn @@ -1,4 +1,4 @@ -ARG VERIFICARLO_VERSION=v0.8.0 +ARG VERIFICARLO_VERSION=v0.9.1 FROM verificarlo/fuzzy:${VERIFICARLO_VERSION}-lapack-python3.8.5-numpy-scipy # Load backend IEEE diff --git a/docker/resources/build_fuzzy_libmath_dockerfile.sh b/docker/resources/build_fuzzy_libmath_dockerfile.sh index 8f0d96b..72ba18e 100755 --- a/docker/resources/build_fuzzy_libmath_dockerfile.sh +++ b/docker/resources/build_fuzzy_libmath_dockerfile.sh @@ -1,7 +1,7 @@ #!/bin/bash DOCKERFILE=Dockerfile.mcalibmath -FUZZY_IMAGE_DEFAULT=verificarlo/fuzzy:v0.8.0-lapack +FUZZY_IMAGE_DEFAULT=verificarlo/fuzzy:v0.9.1-lapack generate_docker() { @@ -9,8 +9,9 @@ generate_docker() { # Base image FROM ${1} -RUN mkdir -p /opt/mca-libmath/{standard,quad,mpfr} +RUN mkdir -p /opt/mca-libmath/{fast,standard,quad,mpfr} COPY --from=${2} /opt/mca-libmath/set-fuzzy-libmath.py /usr/local/bin/set-fuzzy-libmath +COPY --from=${2} /opt/mca-libmath/fast/libmath.so /opt/mca-libmath/fast/libmath.so COPY --from=${2} /opt/mca-libmath/standard/libmath.so /opt/mca-libmath/standard/libmath.so COPY --from=${2} /opt/mca-libmath/quad/libmath.so /opt/mca-libmath/quad/libmath.so COPY --from=${2} /opt/mca-libmath/mpfr/libmath.so /opt/mca-libmath/mpfr/libmath.so @@ -38,7 +39,7 @@ if [[ $# < 2 ]]; then echo " : Name of the base docker image to build" echo " : Tag of the new image to build" echo " [FUZZY_IMAGE]: Name of the fuzzy image to copy from (optional)" - echo " Requires a fuzzy version >= 0.8.0" + echo " Requires a fuzzy version >= 0.9.1" exit 1 elif [[ $# == 2 ]]; then BASE_IMAGE=$1 diff --git a/docker/resources/libmath/Makefile b/docker/resources/libmath/Makefile index 0e22470..a993b4e 100755 --- a/docker/resources/libmath/Makefile +++ b/docker/resources/libmath/Makefile @@ -1,13 +1,28 @@ # Makefile for the instrumented shared library -.PHONY: tracer +.PHONY: tracer fast all: + cd fast && $(MAKE) cd standard && $(MAKE) cd quad && $(MAKE) cd mpfr && $(MAKE) +fast: + cd fast && $(MAKE) + +standard: + cd standard && $(MAKE) + +quad: + cd quad && $(MAKE) + +mpfr: + cd mfpr && $(MAKE) + + tracer: + cd fast && $(MAKE) tracer cd standard && $(MAKE) tracer cd quad && $(MAKE) tracer cd mpfr && $(MAKE) tracer @@ -19,6 +34,7 @@ perf: all cd tests && $(MAKE) perf clean: + cd fast && $(MAKE) clean cd standard && $(MAKE) clean cd quad && $(MAKE) clean cd mpfr && $(MAKE) clean diff --git a/docker/resources/libmath/fast/Makefile b/docker/resources/libmath/fast/Makefile new file mode 100755 index 0000000..84d247d --- /dev/null +++ b/docker/resources/libmath/fast/Makefile @@ -0,0 +1,28 @@ +# Makefile for the instrumented shared library + +CC = gcc +TRACER_FLAGS = --tracer --tracer-debug-mode --tracer-level=temporary +DEBUG_FLAGS = --save-temps -g +CFLAGS = -Wall -fPIC # C flags +LDFLAGS = -shared # linking flags +LIBS= -ldl +RM = rm -f + +TARGET_LIB = libmath.so # target lib + +SRCS = src/wrapping_script.c # source files +OBJS = $(SRCS:.c=.o) +ROOT = $(PWD) + + +.PHONY: tracer + +$(TARGET_LIB): $(OBJS) + $(CC) ${LDFLAGS} ${CFLAGS} -o $@ $^ ${LIBS} + +tracer: + $(CC) ${TRACER_FLAGS} ${CFLAGS} ${LDFLAGS} -o ${TARGET_LIB} $(SRCS) ${LIBS} + +clean: + -${RM} ${TARGET_LIB} ${OBJS} $(SRCS:.c=.d) .vfcwrapper* + diff --git a/docker/resources/libmath/fast/src/float_const.h b/docker/resources/libmath/fast/src/float_const.h new file mode 100644 index 0000000..1178b4d --- /dev/null +++ b/docker/resources/libmath/fast/src/float_const.h @@ -0,0 +1,128 @@ +#ifndef __FLOAT_CONST_H__ +#define __FLOAT_CONST_H__ + +// Round to nearest using cast +// Works for standard type, aka double to float, if the ieee rounding flag is +// set to nearest WARNING: For quad to double we notice that the behavior is +// always round toward zero +#define NEAREST_FLOAT(x) ((float)(x)) +#define NEAREST_DOUBLE(x) ((double)(x)) + +// Quad precision sign encoding size +#define QUAD_SIGN_SIZE 1 +// Quad precision quiet nan bit encoding size +#define QUAD_QUIET_NAN_SIZE 1 +// Quad precision exponent encoding size +#define QUAD_EXP_SIZE 15 +// Quad precision pseudo mantissa encoding size +#define QUAD_PMAN_SIZE 112 +// Quad precision pseudo mantissa encoding size in the word containing the 64 +// msb +#define QUAD_HX_PMAN_SIZE 48 +// Quad precison pseudo mantissa encoding size in the word containing the 64 lsb +#define QUAD_LX_PMAN_SIZE 64 +// Quad precision pseudo mantissa encoding size for quiet nan in the word +// containing the 64 msb +#define QUAD_HX_PMAN_QNAN_SIZE 47 +// Quad precison pseudo mantissa encoding size for quiet nan in the word +// containing the 64 lsb +#define QUAD_LX_PMAN_QNAN_SIZE 64 +// Quad precison mantissa size +#define QUAD_PREC 113 +// Quad precison exponent complement +#define QUAD_EXP_COMP 16383 +// Quad precison max exponent +#define QUAD_EXP_MAX 16383 +// Quad precison min exponent +#define QUAD_EXP_MIN 16382 +// Quad precison infinite exponent +#define QUAD_EXP_INF 0x7FFF +// Quad precison mask to remove the sign bit +#define QUAD_HX_ERASE_SIGN 0x7fffffffffffffffULL +// Quad precison 64 msb to encode plus infinity +#define QINF_hx 0x7fff000000000000ULL +// Quad precison 64 msb to encode minus infinity +#define QMINF_hx 0x7fff000000000000ULL +// Quad precison 64 lsb to encode plus infinity +#define QINF_lx 0x0000000000000000ULL +// Quad precison 64 lsb to encode minus infinity +#define QMINF_lx 0x0000000000000000ULL +// Quad precision pseudo mantissa msb set to one +#define QUAD_HX_PMAN_MSB 0x0000800000000000ULL + +// Double precision encoding size +#define DOUBLE_SIGN_SIZE 1 +// Double precision expoenent encoding size +#define DOUBLE_EXP_SIZE 11 +// Double precision pseudo-mantissa encoding size +#define DOUBLE_PMAN_SIZE 52 +// Double precision mantissa size +#define DOUBLE_PREC 53 +// Double precison exponent complement +#define DOUBLE_EXP_COMP 1023 +// Double precison max exponent for normal number +#define DOUBLE_NORMAL_EXP_MAX 1023 +// Double precison max exponent +#define DOUBLE_EXP_MAX 1024 +// Double precison min exponent +#define DOUBLE_EXP_MIN 1022 +// Double precison infinite exponent +#define DOUBLE_EXP_INF 0x7FF +// Double precision plus infinity encoding +#define DOUBLE_PLUS_INF 0x7FF0000000000000ULL +// Double precision pseudo matissa msb set to one +#define DOUBLE_PMAN_MSB 0x0008000000000000ULL +// Double precision mask to erase sign bit +#define DOUBLE_ERASE_SIGN 0x7fffffffffffffffULL +// Double precision mask to extract sign bit +#define DOUBLE_GET_SIGN 0x8000000000000000ULL +// Double precision mask to extract the exponent +#define DOUBLE_GET_EXP 0x7ff0000000000000ULL +// Double precision mask to extract the pseudo mantissa +#define DOUBLE_GET_PMAN 0x000fffffffffffffULL +// Double precision high part mantissa +#define DOUBLE_PMAN_HIGH_SIZE 20 +// Double precision low part mantissa +#define DOUBLE_PMAN_LOW_SIZE 32 +// Double precision mask of 1 +#define DOUBLE_MASK_ONE 0xffffffffffffffffULL + +// single precision encoding size +#define FLOAT_SIGN_SIZE 1 +// Single precision exponent encoding size +#define FLOAT_EXP_SIZE 8 +// Single precision pseudo mantisa encoding size +#define FLOAT_PMAN_SIZE 23 +// single precision mantissa size +#define FLOAT_PREC 24 +// single precison exponent complement +#define FLOAT_EXP_COMP 127 +// single precison max exponent for normal number +#define FLOAT_NORMAL_EXP_MAX 127 +// single precison max exponent +#define FLOAT_EXP_MAX 128 +// single precison min exponent +#define FLOAT_EXP_MIN 126 +// single precison infinite exponent +#define FLOAT_EXP_INF 0xFF +// single precision plus infinity encoding +#define FLOAT_PLUS_INF 0x7F800000 +// Single precision pseudo matissa msb set to one +#define FLOAT_PMAN_MSB 0x00400000 +// Single precision mask to erase sign bit +#define FLOAT_ERASE_SIGN 0x7fffffff +// Single precision mask to extract sign bit +#define FLOAT_GET_SIGN 0x80000000 +// Single precision mask to extract the exponent +#define FLOAT_GET_EXP 0x7F800000 +// Single precision mask to extract the pseudo mantissa +#define FLOAT_GET_PMAN 0x007fffff +// Single precision mask of 1 +#define FLOAT_MASK_ONE 0xffffffffULL + +// Sign encoding size +#define SIGN_SIZE 1 +// 64bit word with msb set to 1 +#define WORD64_MSB 0x8000000000000000ULL + +#endif /* __FLOAT_CONST_H__ */ diff --git a/docker/resources/libmath/fast/src/float_struct.h b/docker/resources/libmath/fast/src/float_struct.h new file mode 100644 index 0000000..8eb7ee7 --- /dev/null +++ b/docker/resources/libmath/fast/src/float_struct.h @@ -0,0 +1,194 @@ +#ifndef __FLOAT_STRUCT_H_ +#define __FLOAT_STRUCT_H_ + +#include "float_const.h" +#include +#include + +/* import from */ + +/* Frankly, if you have __float128, you have 64-bit integers, right? */ +#ifndef UINT64_C +#error "No way!" +#endif + +/* Main union type we use to manipulate the floating-point type. */ + +typedef union { + __float128 f128; + __uint128_t u128; + __int128_t i128; + + /* Generic fields */ + __float128 type; + __int128_t i; + __uint128_t u; + + struct +#ifdef __MINGW32__ + /* On mingw targets the ms-bitfields option is active by default. + Therefore enforce gnu-bitfield style. */ + __attribute__((gcc_struct)) +#endif + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + unsigned sign : QUAD_SIGN_SIZE; + unsigned exponent : QUAD_EXP_SIZE; + uint64_t mant_high : QUAD_HX_PMAN_SIZE; + uint64_t mant_low : QUAD_LX_PMAN_SIZE; +#else + uint64_t mant_low : QUAD_LX_PMAN_SIZE; + uint64_t mant_high : QUAD_HX_PMAN_SIZE; + unsigned exponent : QUAD_EXP_SIZE; + unsigned sign : QUAD_SIGN_SIZE; +#endif + } ieee; + + struct +#ifdef __MINGW32__ + /* On mingw targets the ms-bitfields option is active by default. + Therefore enforce gnu-bitfield style. */ + __attribute__((gcc_struct)) +#endif + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + __uint128_t sign : QUAD_SIGN_SIZE; + __uint128_t exponent : QUAD_EXP_SIZE; + __uint128_t mantissa : QUAD_PMAN_SIZE; +#else + __uint128_t mantissa : QUAD_PMAN_SIZE; + __uint128_t exponent : QUAD_EXP_SIZE; + __uint128_t sign : QUAD_SIGN_SIZE; +#endif + } ieee128; + + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint64_t high; + uint64_t low; +#else + uint64_t low; + uint64_t high; +#endif + } words64; + + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint32_t w0; + uint32_t w1; + uint32_t w2; + uint32_t w3; +#else + uint32_t w3; + uint32_t w2; + uint32_t w1; + uint32_t w0; +#endif + } words32; + + struct +#ifdef __MINGW32__ + /* Make sure we are using gnu-style bitfield handling. */ + __attribute__((gcc_struct)) +#endif + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint64_t sign : QUAD_SIGN_SIZE; + uint64_t exponent : QUAD_EXP_SIZE; + uint64_t quiet_nan : QUAD_QUIET_NAN_SIZE; + uint64_t mant_high : QUAD_HX_PMAN_QNAN_SIZE; + uint64_t mant_low : QUAD_LX_PMAN_QNAN_SIZE; +#else + uint64_t mant_low : QUAD_LX_PMAN_QNAN_SIZE; + uint64_t mant_high : QUAD_HX_PMAN_QNAN_SIZE; + uint64_t quiet_nan : QUAD_QUIET_NAN_SIZE; + uint64_t exponent : QUAD_EXP_SIZE; + uint64_t sign : QUAD_SIGN_SIZE; +#endif + } nan; + +} binary128; + +typedef union { + + double f64; + uint64_t u64; + int64_t s64; + uint32_t u32[2]; + + /* Generic fields */ + double type; + uint64_t u; + + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint64_t sign : DOUBLE_SIGN_SIZE; + uint64_t exponent : DOUBLE_EXP_SIZE; + uint64_t mantissa : DOUBLE_PMAN_SIZE; +#endif +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + uint64_t mantissa : DOUBLE_PMAN_SIZE; + uint64_t exponent : DOUBLE_EXP_SIZE; + uint64_t sign : DOUBLE_SIGN_SIZE; +#endif + } ieee; + + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint32_t sign : DOUBLE_SIGN_SIZE; + uint32_t exponent : DOUBLE_EXP_SIZE; + uint32_t mantissa_high : DOUBLE_PMAN_HIGH_SIZE; + uint32_t mantissa_low : DOUBLE_PMAN_LOW_SIZE; +#endif +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__ + uint32_t mantissa_high : DOUBLE_PMAN_HIGH_SIZE; + uint32_t exponent : DOUBLE_EXP_SIZE; + uint32_t sign : DOUBLE_SIGN_SIZE; + uint32_t mantissa_low : DOUBLE_PMAN_LOW_SIZE; +#else + uint32_t mantissa_low : DOUBLE_PMAN_LOW_SIZE; + uint32_t mantissa_high : DOUBLE_PMAN_HIGH_SIZE; + uint32_t exponent : DOUBLE_EXP_SIZE; + uint32_t sign : DOUBLE_SIGN_SIZE; +#endif +#endif + } ieee32; + +} binary64; + +typedef union { + + float f32; + uint32_t u32; + int32_t s32; + + /* Generic fields */ + float type; + uint32_t u; + + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint32_t sign : FLOAT_SIGN_SIZE; + uint32_t exponent : FLOAT_EXP_SIZE; + uint32_t mantissa : FLOAT_PMAN_SIZE; +#endif +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + uint32_t mantissa : FLOAT_PMAN_SIZE; + uint32_t exponent : FLOAT_EXP_SIZE; + uint32_t sign : FLOAT_SIGN_SIZE; +#endif + } ieee; + +} binary32; + +#define QUADFP_NAN 0 +#define QUADFP_INFINITE 1 +#define QUADFP_ZERO 2 +#define QUADFP_SUBNORMAL 3 +#define QUADFP_NORMAL 4 +#define fpclassifyq(x) \ + __builtin_fpclassify(QUADFP_NAN, QUADFP_INFINITE, QUADFP_NORMAL, \ + QUADFP_SUBNORMAL, QUADFP_ZERO, x) + +#endif /* __FLOAT_STRUCT_H_ */ diff --git a/docker/resources/libmath/fast/src/wrapping_script.c b/docker/resources/libmath/fast/src/wrapping_script.c new file mode 100755 index 0000000..556ae39 --- /dev/null +++ b/docker/resources/libmath/fast/src/wrapping_script.c @@ -0,0 +1,565 @@ +#define _GNU_SOURCE +#include +#include +#include +//#include +#include +#include + +#include "float_struct.h" + +#define xstr(s) str(s) +#define str(s) #s + +// Algebraic functions +typedef double (*real_sqrt_t)(double dbl); +typedef float (*real_sqrtf_t)(float dbl); +typedef double (*real_cbrt_t)(double dbl); +typedef float (*real_cbrtf_t)(float dbl); +typedef double (*real_hypot_t)(double dbl1, double dbl2); +typedef float (*real_hypotf_t)(float dbl1, float dbl2); + +// Elementary transcendental functions +typedef double (*real_log_t)(double dbl); +typedef float (*real_logf_t)(float dbl); +typedef double (*real_log10_t)(double dbl); +typedef float (*real_log10f_t)(float dbl); +typedef double (*real_log1p_t)(double dbl); +typedef float (*real_log1pf_t)(float dbl); +typedef double (*real_log2_t)(double dbl); +typedef float (*real_log2f_t)(float dbl); + +typedef double (*real_sin_t)(double dbl); +typedef float (*real_sinf_t)(float dbl); +typedef double (*real_asin_t)(double dbl); +typedef float (*real_asinf_t)(float dbl); +typedef double (*real_asinh_t)(double dbl); +typedef float (*real_asinhf_t)(float dbl); + +// Higher transcendental functions +typedef double (*real_cos_t)(double dbl); +typedef float (*real_cosf_t)(float dbl); +typedef double (*real_acos_t)(double dbl); +typedef float (*real_acosf_t)(float dbl); +typedef double (*real_acosh_t)(double dbl); +typedef float (*real_acoshf_t)(float dbl); +typedef double (*real_atan_t)(double dbl); +typedef float (*real_atanf_t)(float dbl); +typedef double (*real_atan2_t)(double dbl1, double dbl2); +typedef float (*real_atan2f_t)(float dbl1, float dbl2); +typedef double (*real_atanh_t)(double dbl); +typedef float (*real_atanhf_t)(float dbl); +typedef double (*real_exp_t)(double dbl); +typedef float (*real_expf_t)(float dbl); +typedef double (*real_exp10_t)(double dbl); +typedef float (*real_exp10f_t)(float dbl); +typedef double (*real_exp2_t)(double dbl); +typedef float (*real_exp2f_t)(float dbl); +typedef double (*real_expm1_t)(double dbl); +typedef float (*real_expm1f_t)(float dbl); +typedef double (*real_pow_t)(double dbl1, double dbl2); +typedef float (*real_powf_t)(float dbl1, float dbl2); + +// Higher transcendental functions +typedef double (*real_j0_t)(double dbl); +typedef float (*real_j0f_t)(float dbl); +typedef double (*real_j1_t)(double dbl); +typedef float (*real_j1f_t)(float dbl); +typedef double (*real_jn_t)(int n, double dbl); +typedef float (*real_jnf_t)(int n, float dbl); +typedef double (*real_y0_t)(double dbl); +typedef float (*real_y0f_t)(float dbl); +typedef double (*real_y1_t)(double dbl); +typedef float (*real_y1f_t)(float dbl); +typedef double (*real_yn_t)(int n, double dbl); +typedef float (*real_ynf_t)(int n, float dbl); +typedef double (*real_erf_t)(double dbl); +typedef float (*real_erff_t)(float dbl); +typedef double (*real_erfc_t)(double dbl); +typedef float (*real_erfcf_t)(float dbl); +typedef double (*real_lgamma_t)(double dbl); +typedef float (*real_lgammaf_t)(float dbl); +typedef double (*real_tgamma_t)(double dbl); +typedef float (*real_tgammaf_t)(float dbl); + +typedef double (*real_lgamma_r_t)(double dbl, int *signgamp); +typedef float (*real_lgammaf_r_t)(float dbl, int *signgamp); + +typedef void (*real_sincos_t)(double dbl, double *sin, double *cos); +typedef void (*real_sincosf_t)(float dbl, float *sin, float *cos); + +static real_sqrt_t real_sqrt = NULL; +static real_sqrtf_t real_sqrtf = NULL; +static real_cbrt_t real_cbrt = NULL; +static real_cbrtf_t real_cbrtf = NULL; +static real_hypot_t real_hypot = NULL; +static real_hypotf_t real_hypotf = NULL; + +// Elementary transcendental functions +static real_log_t real_log = NULL; +static real_logf_t real_logf = NULL; +static real_log10_t real_log10 = NULL; +static real_log10f_t real_log10f = NULL; +static real_log1p_t real_log1p = NULL; +static real_log1pf_t real_log1pf = NULL; +static real_log2_t real_log2 = NULL; +static real_log2f_t real_log2f = NULL; + +static real_sin_t real_sin = NULL; +static real_sinf_t real_sinf = NULL; +static real_asin_t real_asin = NULL; +static real_asinf_t real_asinf = NULL; +static real_asinh_t real_asinh = NULL; +static real_asinhf_t real_asinhf = NULL; + +// Higher transcendental functions +static real_cos_t real_cos = NULL; +static real_cosf_t real_cosf = NULL; +static real_acos_t real_acos = NULL; +static real_acosf_t real_acosf = NULL; +static real_acosh_t real_acosh = NULL; +static real_acoshf_t real_acoshf = NULL; +static real_atan_t real_atan = NULL; +static real_atanf_t real_atanf = NULL; +static real_atan2_t real_atan2 = NULL; +static real_atan2f_t real_atan2f = NULL; +static real_atanh_t real_atanh = NULL; +static real_atanhf_t real_atanhf = NULL; +static real_exp_t real_exp = NULL; +static real_expf_t real_expf = NULL; +static real_exp10_t real_exp10 = NULL; +static real_exp10f_t real_exp10f = NULL; +static real_exp2_t real_exp2 = NULL; +static real_exp2f_t real_exp2f = NULL; +static real_expm1_t real_expm1 = NULL; +static real_expm1f_t real_expm1f = NULL; +static real_pow_t real_pow = NULL; +static real_powf_t real_powf = NULL; + +// Higher transcendental functions +static real_j0_t real_j0 = NULL; +static real_j0f_t real_j0f = NULL; +static real_j1_t real_j1 = NULL; +static real_j1f_t real_j1f = NULL; +static real_jn_t real_jn = NULL; +static real_jnf_t real_jnf = NULL; +static real_y0_t real_y0 = NULL; +static real_y0f_t real_y0f = NULL; +static real_y1_t real_y1 = NULL; +static real_y1f_t real_y1f = NULL; +static real_yn_t real_yn = NULL; +static real_ynf_t real_ynf = NULL; +static real_erf_t real_erf = NULL; +static real_erff_t real_erff = NULL; +static real_erfc_t real_erfc = NULL; +static real_erfcf_t real_erfcf = NULL; +static real_lgamma_t real_lgamma = NULL; +static real_lgammaf_t real_lgammaf = NULL; +static real_tgamma_t real_tgamma = NULL; +static real_tgammaf_t real_tgammaf = NULL; + +static real_lgamma_r_t real_lgamma_r = NULL; +static real_lgammaf_r_t real_lgammaf_r = NULL; + +static real_sincos_t real_sincos = NULL; +static real_sincosf_t real_sincosf = NULL; + +typedef enum real_functions { + SQRT = 0, + SQRTF, + CBRT, + CBRTF, + HYPOT, + HYPOTF, + LOG, + LOGF, + LOG10, + LOG10F, + LOG1P, + LOG1PF, + LOG2, + LOG2F, + SIN, + SINF, + ASIN, + ASINF, + ASINH, + ASINHF, + COS, + COSF, + ACOS, + ACOSF, + ACOSH, + ACOSHF, + ATAN, + ATANF, + ATAN2, + ATAN2F, + ATANH, + ATANHF, + EXP, + EXPF, + EXP10, + EXP10F, + EXP2, + EXP2F, + EXPM1, + EXPM1F, + POW, + POWF, + J0, + J0F, + J1, + J1F, + JN, + JNF, + Y0, + Y0F, + Y1, + Y1F, + YN, + YNF, + ERF, + ERFF, + ERFC, + ERFCF, + LGAMMA, + LGAMMAF, + TGAMMA, + TGAMMAF, + LGAMMA_R, + LGAMMAF_R, + SINCOS, + SINCOSF, + __REAL_FUNCTION_END__ +} real_functions_t; + +void *real_functions[] = {[SQRT] = &real_sqrt, + [SQRTF] = &real_sqrtf, + [CBRT] = &real_cbrt, + [CBRTF] = &real_cbrtf, + [HYPOT] = &real_hypot, + [HYPOTF] = &real_hypotf, + [LOG] = &real_log, + [LOGF] = &real_logf, + [LOG10] = &real_log10, + [LOG10F] = &real_log10f, + [LOG1P] = &real_log1p, + [LOG1PF] = &real_log1pf, + [LOG2] = &real_log2, + [LOG2F] = &real_log2f, + [SIN] = &real_sin, + [SINF] = &real_sinf, + [ASIN] = &real_asin, + [ASINF] = &real_asinf, + [ASINH] = &real_asinh, + [ASINHF] = &real_asinhf, + [COS] = &real_cos, + [COSF] = &real_cosf, + [ACOS] = &real_acos, + [ACOSF] = &real_acosf, + [ACOSH] = &real_acosh, + [ACOSHF] = &real_acoshf, + [ATAN] = &real_atan, + [ATANF] = &real_atanf, + [ATAN2] = &real_atan2, + [ATAN2F] = &real_atan2f, + [ATANH] = &real_atanh, + [ATANHF] = &real_atanhf, + [EXP] = &real_exp, + [EXPF] = &real_expf, + [EXP10] = &real_exp10, + [EXP10F] = &real_exp10f, + [EXP2] = &real_exp2, + [EXP2F] = &real_exp2f, + [EXPM1] = &real_expm1, + [EXPM1F] = &real_expm1f, + [POW] = &real_pow, + [POWF] = &real_powf, + [J0] = &real_j0, + [J0F] = &real_j0f, + [J1] = &real_j1, + [J1F] = &real_j1f, + [JN] = &real_jn, + [JNF] = &real_jnf, + [Y0] = &real_y0, + [Y0F] = &real_y0f, + [Y1] = &real_y1, + [Y1F] = &real_y1f, + [YN] = &real_yn, + [YNF] = &real_ynf, + [ERF] = &real_erf, + [ERFF] = &real_erff, + [ERFC] = &real_erfc, + [ERFCF] = &real_erfcf, + [LGAMMA] = &real_lgamma, + [LGAMMAF] = &real_lgammaf, + [TGAMMA] = &real_tgamma, + [TGAMMAF] = &real_tgammaf, + [LGAMMA_R] = &real_lgamma_r, + [LGAMMAF_R] = &real_lgammaf_r, + [SINCOS] = &real_sincos, + [SINCOSF] = &real_sincosf, + [__REAL_FUNCTION_END__] = NULL}; + +typedef uint64_t xoroshiro_state[2]; +static xoroshiro_state rng_state; + +uint64_t next_seed(uint64_t seed_state) { + uint64_t z = (seed_state += UINT64_C(0x9E3779B97F4A7C15)); + z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); + z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB); + return z ^ (z >> 31); +} + +static inline uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + +uint64_t next(xoroshiro_state s) { + const uint64_t s0 = s[0]; + uint64_t s1 = s[1]; + const uint64_t result = rotl(s0 + s1, 17) + s0; + + s1 ^= s0; + s[0] = rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b + s[1] = rotl(s1, 28); // c + + return result; +} + +__attribute__((constructor(0))) static void fuzzy_init(void) { + + struct timeval t1; + gettimeofday(&t1, NULL); + uint64_t seed = t1.tv_sec ^ t1.tv_usec; + rng_state[0] = next_seed(seed); + rng_state[1] = next_seed(seed); + + real_functions[SQRT] = (real_sqrt_t)dlsym(RTLD_NEXT, "sqrt"); + real_functions[SQRTF] = (real_sqrtf_t)dlsym(RTLD_NEXT, "sqrtf"); + real_functions[CBRT] = (real_cbrt_t)dlsym(RTLD_NEXT, "cbrt"); + real_functions[CBRTF] = (real_cbrtf_t)dlsym(RTLD_NEXT, "cbrtf"); + real_functions[HYPOT] = (real_hypot_t)dlsym(RTLD_NEXT, "hypot"); + real_functions[HYPOTF] = (real_hypotf_t)dlsym(RTLD_NEXT, "hypotf"); + real_functions[LOG] = (real_log_t)dlsym(RTLD_NEXT, "log"); + real_functions[LOGF] = (real_logf_t)dlsym(RTLD_NEXT, "logf"); + real_functions[LOG10] = (real_log10_t)dlsym(RTLD_NEXT, "log10"); + real_functions[LOG10F] = (real_log10f_t)dlsym(RTLD_NEXT, "log10f"); + real_functions[LOG1P] = (real_log1p_t)dlsym(RTLD_NEXT, "log1p"); + real_functions[LOG1PF] = (real_log1pf_t)dlsym(RTLD_NEXT, "log1pf"); + real_functions[LOG2] = (real_log2_t)dlsym(RTLD_NEXT, "log2"); + real_functions[LOG2F] = (real_log2f_t)dlsym(RTLD_NEXT, "log2f"); + real_functions[SIN] = (real_sin_t)dlsym(RTLD_NEXT, "sin"); + real_functions[SINF] = (real_sinf_t)dlsym(RTLD_NEXT, "sinf"); + real_functions[ASIN] = (real_asin_t)dlsym(RTLD_NEXT, "asin"); + real_functions[ASINF] = (real_asinf_t)dlsym(RTLD_NEXT, "asinf"); + real_functions[ASINH] = (real_asinh_t)dlsym(RTLD_NEXT, "asinh"); + real_functions[ASINHF] = (real_asinhf_t)dlsym(RTLD_NEXT, "asinhf"); + real_functions[COS] = (real_cos_t)dlsym(RTLD_NEXT, "cos"); + real_functions[COSF] = (real_cosf_t)dlsym(RTLD_NEXT, "cosf"); + real_functions[ACOS] = (real_acos_t)dlsym(RTLD_NEXT, "acos"); + real_functions[ACOSF] = (real_acosf_t)dlsym(RTLD_NEXT, "acosf"); + real_functions[ACOSH] = (real_acosh_t)dlsym(RTLD_NEXT, "acosh"); + real_functions[ACOSHF] = (real_acoshf_t)dlsym(RTLD_NEXT, "acoshf"); + real_functions[ATAN] = (real_atan_t)dlsym(RTLD_NEXT, "atan"); + real_functions[ATANF] = (real_atanf_t)dlsym(RTLD_NEXT, "atanf"); + real_functions[ATAN2] = (real_atan2_t)dlsym(RTLD_NEXT, "atan2"); + real_functions[ATAN2F] = (real_atan2f_t)dlsym(RTLD_NEXT, "atan2f"); + real_functions[ATANH] = (real_atanh_t)dlsym(RTLD_NEXT, "atanh"); + real_functions[ATANHF] = (real_atanhf_t)dlsym(RTLD_NEXT, "atanhf"); + real_functions[EXP] = (real_exp_t)dlsym(RTLD_NEXT, "exp"); + real_functions[EXPF] = (real_expf_t)dlsym(RTLD_NEXT, "expf"); + real_functions[EXP10] = (real_exp10_t)dlsym(RTLD_NEXT, "exp10"); + real_functions[EXP10F] = (real_exp10f_t)dlsym(RTLD_NEXT, "exp10f"); + real_functions[EXP2] = (real_exp2_t)dlsym(RTLD_NEXT, "exp2"); + real_functions[EXP2F] = (real_exp2f_t)dlsym(RTLD_NEXT, "exp2f"); + real_functions[EXPM1] = (real_expm1_t)dlsym(RTLD_NEXT, "expm1"); + real_functions[EXPM1F] = (real_expm1f_t)dlsym(RTLD_NEXT, "expm1f"); + real_functions[POW] = (real_pow_t)dlsym(RTLD_NEXT, "pow"); + real_functions[POWF] = (real_powf_t)dlsym(RTLD_NEXT, "powf"); + real_functions[J0] = (real_j0_t)dlsym(RTLD_NEXT, "j0"); + real_functions[J0F] = (real_j0f_t)dlsym(RTLD_NEXT, "j0f"); + real_functions[J1] = (real_j1_t)dlsym(RTLD_NEXT, "j1"); + real_functions[J1F] = (real_j1f_t)dlsym(RTLD_NEXT, "j1f"); + real_functions[JN] = (real_jn_t)dlsym(RTLD_NEXT, "jn"); + real_functions[JNF] = (real_jnf_t)dlsym(RTLD_NEXT, "jnf"); + real_functions[Y0] = (real_y0_t)dlsym(RTLD_NEXT, "y0"); + real_functions[Y0F] = (real_y0f_t)dlsym(RTLD_NEXT, "y0f"); + real_functions[Y1] = (real_y1_t)dlsym(RTLD_NEXT, "y1"); + real_functions[Y1F] = (real_y1f_t)dlsym(RTLD_NEXT, "y1f"); + real_functions[YN] = (real_yn_t)dlsym(RTLD_NEXT, "yn"); + real_functions[YNF] = (real_ynf_t)dlsym(RTLD_NEXT, "ynf"); + real_functions[ERF] = (real_erf_t)dlsym(RTLD_NEXT, "erf"); + real_functions[ERFF] = (real_erff_t)dlsym(RTLD_NEXT, "erff"); + real_functions[ERFC] = (real_erfc_t)dlsym(RTLD_NEXT, "erfc"); + real_functions[ERFCF] = (real_erfcf_t)dlsym(RTLD_NEXT, "erfcf"); + real_functions[LGAMMA] = (real_lgamma_t)dlsym(RTLD_NEXT, "lgamma"); + real_functions[LGAMMAF] = (real_lgammaf_t)dlsym(RTLD_NEXT, "lgammaf"); + real_functions[TGAMMA] = (real_tgamma_t)dlsym(RTLD_NEXT, "tgamma"); + real_functions[TGAMMAF] = (real_tgammaf_t)dlsym(RTLD_NEXT, "tgammaf"); + real_functions[LGAMMA_R] = (real_lgamma_r_t)dlsym(RTLD_NEXT, "lgamma_r"); + real_functions[LGAMMAF_R] = (real_lgammaf_r_t)dlsym(RTLD_NEXT, "lgammaf_r"); + real_functions[SINCOS] = (real_sincos_t)dlsym(RTLD_NEXT, "sincos"); + real_functions[SINCOSF] = (real_sincosf_t)dlsym(RTLD_NEXT, "sincosf"); +} + +// Override + +#define ZERO(TYPE) _Generic(TYPE, float : 0.0f, double : 0.0) +#define GET_FTYPE(TYPE) _Generic(TYPE, float : FFLOAT, double : FDOUBLE) + +static inline void float_rr(float *a) { + if (*a == 0.0) + return; + binary32 *b32 = (binary32 *)a; + b32->u32 += (next(rng_state) & 1) ? 1 : -1; +} + +static inline void double_rr(double *a) { + if (*a == 0.0) + return; + binary64 *b64 = (binary64 *)a; + b64->u64 += (next(rng_state) & 1) ? 1 : -1; +} + +#define FP_RR(X) _Generic(X, float * : float_rr, double * : double_rr)(X) + +#define DEFINE_1_WRAPPER(NAME, SYM, TYPE) \ + TYPE NAME(TYPE x) { \ + real_##NAME##_t fun = real_functions[SYM]; \ + TYPE res = fun(x); \ + FP_RR(&res); \ + return res; \ + } + +#define DEFINE_1i_1_WRAPPER(NAME, SYM, TYPE) \ + TYPE NAME(int n, TYPE x) { \ + real_##NAME##_t fun = real_functions[SYM]; \ + TYPE res = fun(n, x); \ + FP_RR(&res); \ + return res; \ + } + +#define DEFINE_1_1p_WRAPPER(NAME, SYM, TYPE) \ + TYPE NAME(TYPE x, int *s) { \ + real_##NAME##_t fun = real_functions[SYM]; \ + TYPE res = fun(x, s); \ + FP_RR(&res); \ + return res; \ + } + +#define DEFINE_1_2p_WRAPPER(NAME, SYM, TYPE) \ + void NAME(TYPE x, TYPE *o1, TYPE *o2) { \ + real_##NAME##_t fun = real_functions[SYM]; \ + fun(x, o1, o2); \ + FP_RR(o1); \ + FP_RR(o2); \ + } + +#define DEFINE_2_WRAPPER(NAME, SYM, TYPE) \ + TYPE NAME(TYPE x, TYPE y) { \ + real_##NAME##_t fun = real_functions[SYM]; \ + TYPE res = fun(x, y); \ + FP_RR(&res); \ + return res; \ + } + +DEFINE_1_WRAPPER(sqrt, SQRT, double); +DEFINE_1_WRAPPER(sqrtf, SQRTF, float); + +DEFINE_1_WRAPPER(cbrt, CBRT, double); +DEFINE_1_WRAPPER(cbrtf, CBRTF, float); + +DEFINE_2_WRAPPER(hypot, HYPOT, double); +DEFINE_2_WRAPPER(hypotf, HYPOTF, float); + +DEFINE_1_WRAPPER(log, LOG, double); +DEFINE_1_WRAPPER(logf, LOGF, float); + +DEFINE_1_WRAPPER(log10, LOG10, double); +DEFINE_1_WRAPPER(log10f, LOG10F, float); + +DEFINE_1_WRAPPER(log1p, LOG1P, double); +DEFINE_1_WRAPPER(log1pf, LOG1PF, float); + +DEFINE_1_WRAPPER(log2, LOG2, double); +DEFINE_1_WRAPPER(log2f, LOG2F, float); + +DEFINE_1_WRAPPER(sin, SIN, double); +DEFINE_1_WRAPPER(sinf, SINF, float); + +DEFINE_1_WRAPPER(asin, ASIN, double); +DEFINE_1_WRAPPER(asinf, ASINF, float); + +DEFINE_1_WRAPPER(asinh, ASINH, double); +DEFINE_1_WRAPPER(asinhf, ASINHF, float); + +DEFINE_1_WRAPPER(cos, COS, double); +DEFINE_1_WRAPPER(cosf, COSF, float); + +DEFINE_1_WRAPPER(acos, ACOS, double); +DEFINE_1_WRAPPER(acosf, ACOSF, float); + +DEFINE_1_WRAPPER(acosh, ACOSH, double); +DEFINE_1_WRAPPER(acoshf, ACOSHF, float); + +DEFINE_1_WRAPPER(atan, ATAN, double); +DEFINE_1_WRAPPER(atanf, ATANF, float); + +DEFINE_1_WRAPPER(atanh, ATANH, double); +DEFINE_1_WRAPPER(atanhf, ATANHF, float); + +DEFINE_2_WRAPPER(atan2, ATAN2, double); +DEFINE_2_WRAPPER(atan2f, ATAN2F, float); + +DEFINE_1_WRAPPER(exp, EXP, double); +DEFINE_1_WRAPPER(expf, EXPF, float); + +DEFINE_2_WRAPPER(pow, POW, double); +DEFINE_2_WRAPPER(powf, POWF, float); + +DEFINE_1_WRAPPER(exp10, EXP10, double); +DEFINE_1_WRAPPER(exp10f, EXP10F, float); + +DEFINE_1_WRAPPER(exp2, EXP2, double); +DEFINE_1_WRAPPER(exp2f, EXP2F, float); + +DEFINE_1_WRAPPER(expm1, EXPM1, double); +DEFINE_1_WRAPPER(expm1f, EXPM1F, float); + +DEFINE_1_WRAPPER(j0, J0, double); +DEFINE_1_WRAPPER(j0f, J0F, float); + +DEFINE_1_WRAPPER(j1, J1, double); +DEFINE_1_WRAPPER(j1f, J1F, float); + +DEFINE_1i_1_WRAPPER(jn, JN, double); +DEFINE_1i_1_WRAPPER(jnf, JNF, float); + +DEFINE_1_WRAPPER(y0, Y0, double); +DEFINE_1_WRAPPER(y0f, Y0F, float); + +DEFINE_1_WRAPPER(y1, Y1, double); +DEFINE_1_WRAPPER(y1f, Y1F, float); + +DEFINE_1i_1_WRAPPER(yn, YN, double); +DEFINE_1i_1_WRAPPER(ynf, YNF, float); + +DEFINE_1_WRAPPER(erf, ERF, double); +DEFINE_1_WRAPPER(erff, ERFF, float); + +DEFINE_1_WRAPPER(erfc, ERFC, double); +DEFINE_1_WRAPPER(erfcf, ERFCF, float); + +DEFINE_1_WRAPPER(lgamma, LGAMMA, double); +DEFINE_1_WRAPPER(lgammaf, LGAMMAF, float); + +DEFINE_1_WRAPPER(tgamma, TGAMMA, double); +DEFINE_1_WRAPPER(tgammaf, TGAMMAF, float); + +DEFINE_1_1p_WRAPPER(lgamma_r, LGAMMA_R, double); +DEFINE_1_1p_WRAPPER(lgammaf_r, LGAMMAF_R, float); + +DEFINE_1_2p_WRAPPER(sincos, SINCOS, double); +DEFINE_1_2p_WRAPPER(sincosf, SINCOSF, float); diff --git a/docker/resources/libmath/set-fuzzy-libmath.py b/docker/resources/libmath/set-fuzzy-libmath.py index 2802fb8..9fc2d8e 100755 --- a/docker/resources/libmath/set-fuzzy-libmath.py +++ b/docker/resources/libmath/set-fuzzy-libmath.py @@ -9,6 +9,7 @@ versions = [ 'no-fuzzy', + 'fast', 'standard', 'quad', 'mpfr' @@ -19,7 +20,7 @@ def switch_version(version): try: - with open(ld_preload_file) as fi: + with open(ld_preload_file, encoding='utf-8') as fi: current_so = fi.readline().strip().split() except FileNotFoundError: current_so = [] @@ -32,16 +33,19 @@ def switch_version(version): to_write = " ".join(new_so) - with open(ld_preload_file, "w") as fo: + with open(ld_preload_file, "w", encoding='utf-8') as fo: fo.write(to_write) def parse_args(): - help_msg = f'''\ + help_msg = '''\ Fuzzy libmath version to use: - no-fuzzy: Disable fuzzy libmath - - standard: Use the standard libmath available on the system. + - fast: Use the standard libmath available on the system. + Not possible to modify the virtual precision! Fastest instrumentation but possibly not accurate + - standard: Use the standard libmath available on the system. + Fast instrumentation but possibly not accurate - quad: Use the libquadmath for intermediate results. Slower than the standard version but more accurate. - mpfr: Use the mpfr library for intermediate results. @@ -57,6 +61,10 @@ def parse_args(): return args -if '__main__' == __name__: +def main(): args = parse_args() switch_version(args.version) + + +if '__main__' == __name__: + main() diff --git a/docker/resources/libmath/tests/Makefile b/docker/resources/libmath/tests/Makefile index eae6fba..ea812c7 100644 --- a/docker/resources/libmath/tests/Makefile +++ b/docker/resources/libmath/tests/Makefile @@ -2,12 +2,14 @@ .PHONY: test perf test: + python3 test.py --library=fast python3 test.py --library=standard python3 test.py --library=quad python3 test.py --library=mpfr perf: clean python3 test.py --library=ref --profiling 2> perf.ref.log + python3 test.py --library=fast --profiling 2> perf.fast.log python3 test.py --library=standard --profiling 2> perf.standard.log python3 test.py --library=quad --profiling 2> perf.quad.log python3 test.py --library=mpfr --profiling 2> perf.mpfr.log diff --git a/docker/resources/libmath/tests/test.py b/docker/resources/libmath/tests/test.py index d3c37c0..24adb23 100644 --- a/docker/resources/libmath/tests/test.py +++ b/docker/resources/libmath/tests/test.py @@ -24,7 +24,7 @@ class Types(Enum): gcc = 'gcc' -libraries = ['ref', 'standard', 'quad', 'mpfr'] +libraries = ['ref', 'fast', 'standard', 'quad', 'mpfr'] outputs_filename = 'outputs' perf_filename = '' check_noise_cmd = f"python3 check_result.py {outputs_filename}" @@ -34,6 +34,7 @@ class Types(Enum): excluded_functions = { 'ref': [], + 'fast': [], 'standard': [], 'quad': ['exp10', 'exp10f', 'lgammaf_r', 'lgamma_r', 'exp2', 'exp2f'], 'mpfr': []