├── .gitignore ├── Makefile ├── README.md ├── docker └── Dockerfile ├── gsl-2.5.tar.gz ├── lib └── libPassModule.so ├── misc └── compile-gsl-sf.sh ├── script ├── oracleMpmath.py └── reproduce.py └── src ├── communicator.h ├── fpInterface.h ├── fpUtil.cpp ├── fpUtil.h ├── gslSolver.cpp ├── handlers.cpp ├── opcode.h ├── target.h └── targetExample.c /.gitignore: -------------------------------------------------------------------------------- 1 | data/ 2 | build/ 3 | bin/ 4 | gsl-2.5/ 5 | gslbuild/ 6 | *.out 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX=clang++-3.9 2 | LD=clang++-3.9 3 | CXXFLAGS=-std=c++11 -O2 -fPIC -fno-rtti 4 | 5 | CLANG=clang-3.9 6 | OPT=opt-3.9 7 | CLANGFLAGS=-fPIC -fno-rtti 8 | 9 | LLVMCFG=llvm-config-3.9 10 | LLVMCXXFLAGS=$(shell $(LLVMCFG) --cxxflags) 11 | LLVMCXXFLAGS+=-fPIC -fno-rtti 12 | LLVMLDFLAGS=$(shell $(LLVMCFG) --ldflags) 13 | 14 | GSLCFG=/atom/gslbuild/bin/gsl-config 15 | GSLCXXFLAGS=$(CXXFLAGS) $(shell $(GSLCFG) --cflags) 16 | GSLLDFLAGS=-static $(shell $(GSLCFG) --libs) 17 | 18 | OS_NAME=$(shell uname -s) 19 | ifeq ($(OS_NAME), Darwin) 20 | # For MacOS: https://stackoverflow.com/questions/37210682/building-and-using-a-pass-for-llvm-3-8-on-osx 21 | LLVMLDFLAGS+=-Wl,-flat_namespace -Wl,-undefined -Wl,suppress 22 | endif 23 | 24 | DEPS = src/fpUtil.h src/communicator.h src/opcode.h 25 | 26 | .PHONY: clean handler util target solver 27 | 28 | all: solver 29 | prep: handler util target 30 | 31 | # The handler start 32 | handler: build/handlers.o 33 | build/handlers.o: src/handlers.cpp $(DEPS) 34 | @mkdir -p build 35 | $(CXX) -c $(CXXFLAGS) -o $@ $< 36 | # The handler finish 37 | 38 | util: build/fpUtil.o 39 | build/fpUtil.o: src/fpUtil.cpp src/fpUtil.h 40 | @mkdir -p build 41 | $(CXX) $(CXXFLAGS) -c -o $@ $< 42 | 43 | # Compile the target under analysis start. 44 | targetObjs = build/targetExample.o 45 | target: build/all_target.a 46 | build/all_target.a: $(targetObjs) 47 | ar crv $@ $(targetObjs) 48 | build/targetExample.o: src/targetExample.c lib/libPassModule.so 49 | @mkdir -p build 50 | $(CLANG) -S -emit-llvm -g -o build/targetExample.ll $< 51 | $(OPT) -S -load lib/libPassModule.so -funcpass -o build/targetExample_i.ll build/targetExample.ll 52 | $(CLANG) $(CLANGFLAGS) -c -o $@ build/targetExample_i.ll 53 | # Compile the target under analysis finish. 54 | 55 | # Generate GSL Solver 56 | solver: bin/gslSolver.out 57 | bin/gslSolver.out: build/gslSolver.o build/fpUtil.o build/handlers.o build/all_target.a 58 | @mkdir -p bin 59 | $(LD) -o $@ $^ $(GSLLDFLAGS) 60 | build/gslSolver.o: src/gslSolver.cpp $(DEPS) 61 | @mkdir -p build 62 | $(CXX) $(GSLCXXFLAGS) -c -o $@ $< 63 | 64 | clean: 65 | rm -f *.o *.so *.out 66 | rm -f *.ll *.bc *.s 67 | rm -f *.dwo 68 | rm -rf *.dSYM 69 | rm -rf build/ 70 | rm -rf bin/ 71 | rm -rf data/ 72 | rm -rf pdfs/ 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Detecting Floating-Point Errors via Atomic Conditions 2 | 3 | ## Setup 4 | Install the [docker](https://www.docker.com/). Here are some guides for install [docker for Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/) and [docker for MacOS](https://docs.docker.com/docker-for-mac/install/) 5 | 6 | Clone this repo to your local workspace: 7 | ``` 8 | $ git clone https://github.com/FP-Analysis/atomic-condition.git 9 | ``` 10 | 11 | The `docker` folder contains a Dockerfile that can be used to build our implementation. If an error about permission denied occurs, try to run docker in root `sudo docker ...`. 12 | ``` 13 | $ cd atomic-condition/docker 14 | $ docker build -t atomic . 15 | ``` 16 | It may takes a few minutes (5 minutes approx) for installing necessary packages and compiling the whole GSL Library. 17 | 18 | ## Usage 19 | Run this docker's container with interactive mode, the working directory is at `/atom`. 20 | ``` 21 | $ docker run -it atomic /bin/bash 22 | ``` 23 | 24 | ### Play with the Motivation Example 25 | The small example `foo` in `src/targetExample.c` computes the motivation example in our paper: `y = (1 - cos(x)) / (x * x)` 26 | 27 | Run on the small example `foo`, defined in `src/targetExample.c`: 28 | ``` 29 | ( In docker's container: /atom ) 30 | $ make 31 | $ bin/gslSolver.out example 32 | ``` 33 | The result shows: 34 | ``` 35 | ... 36 | Most suspicious input first: 37 | -1.6006806510433069e-08 Output: 4.3331212264181757e-01 38 | 1.5707963267949008e+00 Output: 4.0528473456935066e-01 39 | End of suspicious input list. 40 | ... 41 | ``` 42 | 43 | Then we use `mpmath` to calculate the accurate result of this two inputs: 44 | ``` 45 | (In python3) 46 | >>> import mpmath 47 | >>> mpmath.mp.prec=256 48 | >>> def foo_h(x): 49 | ... x = mpmath.mpf(x) 50 | ... return (1-mpmath.cos(x))/(x*x) 51 | ... 52 | >>> y1 = foo_h(-1.6006806510433069e-08) 53 | >>> print(y1) 54 | 0.49999999999999998932425... 55 | >>> y2 = foo_h(1.5707963267949008e+00) 56 | >>> print(y2) 57 | 0.40528473456935062536197... 58 | ``` 59 | We can see that there is a significant error when `x=-1.6006806510433069e-08`, the first of our reported inputs. 60 | 61 | If you want to play with your own function, just modify the `foo` function in `src/targetExample.c`, then 62 | ``` 63 | $ make 64 | $ bin/gslSolver.out example 65 | ``` 66 | 67 | ### Run on GSL Functions 68 | ``` 69 | $ make 70 | $ bin/gslSolver.out gsl 71 | ``` 72 | 73 | #### Compute Relative Error (Only support GSL functions for now) 74 | Using the oracle from `mpmath` to compute the relative error: 75 | ``` 76 | $ make 77 | $ bin/gslSolver.out gsl && python3 script/oracleMpmath.py 78 | ``` 79 | 80 | Example: GSL function `gsl_sf_lngamma` has the index 73, 81 | ``` 82 | $ bin/gslSolver.out gsl 73 && python3 script/oracleMpmath.py 83 | ... 84 | Function Index: 73 85 | Max Relative Error: 86 | Input: -2.457024738220797e+00 87 | Output: 3.552713678800501e-15 88 | Oracle: 4.767633887335327e-15 89 | Relative Error: 2.54827e-01 90 | ``` 91 | 92 | ### Reproduce the Results in Paper 93 | #### Getting the relative errors of GSL functions (Table 4 and Table 5) 94 | You can check GSL functions one by one as mentioned in above section. 95 | You can also check all of the results in single run with: 96 | ``` 97 | $ make 98 | $ bin/gslSolver.out gsl all 99 | $ python3 script/oracleMpmath.py 100 | ``` 101 | 102 | #### Getting the statistics of the relative errors (Figure 3) and the ranking results (Figure 4) 103 | ``` 104 | (If you have already run these 3 commands, you don't need to run them again) 105 | $ make 106 | $ bin/gslSolver.out gsl all 107 | $ python3 script/oracleMpmath.py 108 | 109 | (Please do not insert other commands between this one and the above 3 ones, otherwise you need to run them once again to get the necessary intermediate results.) 110 | $ python3 script/reproduce.py 111 | ``` 112 | 113 | #### Data sources for LSGA and DEMC 114 | The data of LSGA's running time are collected from the [LSGA paper][1], which claims (the running time) 115 | 116 | > ... are approximately equal to 60 seconds. 117 | 118 | The data of DEMC's running time are collected from the [DEMC's data repository][2]. 119 | 120 | [1]: https://dl.acm.org/citation.cfm?id=2818820 121 | [2]: https://github.com/yixin-09/AutoRNP/tree/master/paper_data/testing_results/DEMC 122 | 123 | ## GSL Function List and mpmath Support 124 | | GSL Function Name | Index | mpmath support? | 125 | |-----------------------------|-------|------------------| 126 | | gsl_sf_airy_Ai | 0 |:heavy_check_mark:| 127 | | gsl_sf_airy_Bi | 1 |:heavy_check_mark:| 128 | | gsl_sf_airy_Ai_scaled | 2 |:heavy_check_mark:| 129 | | gsl_sf_airy_Bi_scaled | 3 |:heavy_check_mark:| 130 | | gsl_sf_airy_Ai_deriv | 4 |:heavy_check_mark:| 131 | | gsl_sf_airy_Bi_deriv | 5 |:heavy_check_mark:| 132 | | gsl_sf_airy_Ai_deriv_scaled | 6 |:heavy_check_mark:| 133 | | gsl_sf_airy_Bi_deriv_scaled | 7 |:heavy_check_mark:| 134 | | gsl_sf_bessel_J0 | 8 |:heavy_check_mark:| 135 | | gsl_sf_bessel_J1 | 9 |:heavy_check_mark:| 136 | | gsl_sf_bessel_Y0 | 10 |:heavy_check_mark:| 137 | | gsl_sf_bessel_Y1 | 11 |:heavy_check_mark:| 138 | | gsl_sf_bessel_I0 | 12 |:heavy_check_mark:| 139 | | gsl_sf_bessel_I1 | 13 |:heavy_check_mark:| 140 | | gsl_sf_bessel_I0_scaled | 14 |:heavy_check_mark:| 141 | | gsl_sf_bessel_I1_scaled | 15 |:heavy_check_mark:| 142 | | gsl_sf_bessel_K0 | 16 |:heavy_check_mark:| 143 | | gsl_sf_bessel_K1 | 17 |:heavy_check_mark:| 144 | | gsl_sf_bessel_K0_scaled | 18 |:heavy_check_mark:| 145 | | gsl_sf_bessel_K1_scaled | 19 |:heavy_check_mark:| 146 | | gsl_sf_bessel_j0 | 20 |:heavy_check_mark:| 147 | | gsl_sf_bessel_j1 | 21 |:heavy_check_mark:| 148 | | gsl_sf_bessel_j2 | 22 |:heavy_check_mark:| 149 | | gsl_sf_bessel_y0 | 23 |:heavy_check_mark:| 150 | | gsl_sf_bessel_y1 | 24 |:heavy_check_mark:| 151 | | gsl_sf_bessel_y2 | 25 |:heavy_check_mark:| 152 | | gsl_sf_bessel_i0_scaled | 26 |:heavy_check_mark:| 153 | | gsl_sf_bessel_i1_scaled | 27 |:heavy_check_mark:| 154 | | gsl_sf_bessel_i2_scaled | 28 |:heavy_check_mark:| 155 | | gsl_sf_bessel_k0_scaled | 29 |:heavy_check_mark:| 156 | | gsl_sf_bessel_k1_scaled | 30 |:heavy_check_mark:| 157 | | gsl_sf_bessel_k2_scaled | 31 |:heavy_check_mark:| 158 | | gsl_sf_clausen | 32 |:heavy_check_mark:| 159 | | gsl_sf_dawson | 33 | | 160 | | gsl_sf_debye_1 | 34 | | 161 | | gsl_sf_debye_2 | 35 | | 162 | | gsl_sf_debye_3 | 36 | | 163 | | gsl_sf_debye_4 | 37 | | 164 | | gsl_sf_debye_5 | 38 | | 165 | | gsl_sf_debye_6 | 39 | | 166 | | gsl_sf_dilog | 40 |:heavy_check_mark:| 167 | | gsl_sf_ellint_Kcomp | 41 |:heavy_check_mark:| 168 | | gsl_sf_ellint_Ecomp | 42 |:heavy_check_mark:| 169 | | gsl_sf_ellint_Dcomp | 43 | | 170 | | gsl_sf_erfc | 44 |:heavy_check_mark:| 171 | | gsl_sf_log_erfc | 45 |:heavy_check_mark:| 172 | | gsl_sf_erf | 46 |:heavy_check_mark:| 173 | | gsl_sf_erf_Z | 47 |:heavy_check_mark:| 174 | | gsl_sf_erf_Q | 48 |:heavy_check_mark:| 175 | | gsl_sf_hazard | 49 |:heavy_check_mark:| 176 | | gsl_sf_exp | 50 |:heavy_check_mark:| 177 | | gsl_sf_expm1 | 51 |:heavy_check_mark:| 178 | | gsl_sf_exprel | 52 |:heavy_check_mark:| 179 | | gsl_sf_exprel_2 | 53 |:heavy_check_mark:| 180 | | gsl_sf_expint_E1 | 54 |:heavy_check_mark:| 181 | | gsl_sf_expint_E2 | 55 |:heavy_check_mark:| 182 | | gsl_sf_expint_E1_scaled | 56 |:heavy_check_mark:| 183 | | gsl_sf_expint_E2_scaled | 57 |:heavy_check_mark:| 184 | | gsl_sf_expint_Ei | 58 |:heavy_check_mark:| 185 | | gsl_sf_expint_Ei_scaled | 59 |:heavy_check_mark:| 186 | | gsl_sf_Shi | 60 |:heavy_check_mark:| 187 | | gsl_sf_Chi | 61 |:heavy_check_mark:| 188 | | gsl_sf_expint_3 | 62 | | 189 | | gsl_sf_Si | 63 |:heavy_check_mark:| 190 | | gsl_sf_Ci | 64 |:heavy_check_mark:| 191 | | gsl_sf_atanint | 65 | | 192 | | gsl_sf_fermi_dirac_m1 | 66 |:heavy_check_mark:| 193 | | gsl_sf_fermi_dirac_0 | 67 |:heavy_check_mark:| 194 | | gsl_sf_fermi_dirac_1 | 68 |:heavy_check_mark:| 195 | | gsl_sf_fermi_dirac_2 | 69 |:heavy_check_mark:| 196 | | gsl_sf_fermi_dirac_mhalf | 70 |:heavy_check_mark:| 197 | | gsl_sf_fermi_dirac_half | 71 |:heavy_check_mark:| 198 | | gsl_sf_fermi_dirac_3half | 72 |:heavy_check_mark:| 199 | | gsl_sf_lngamma | 73 |:heavy_check_mark:| 200 | | gsl_sf_gamma | 74 |:heavy_check_mark:| 201 | | gsl_sf_gammastar | 75 | | 202 | | gsl_sf_gammainv | 76 |:heavy_check_mark:| 203 | | gsl_sf_lambert_W0 | 77 |:heavy_check_mark:| 204 | | gsl_sf_lambert_Wm1 | 78 |:heavy_check_mark:| 205 | | gsl_sf_legendre_P1 | 79 |:heavy_check_mark:| 206 | | gsl_sf_legendre_P2 | 80 |:heavy_check_mark:| 207 | | gsl_sf_legendre_P3 | 81 |:heavy_check_mark:| 208 | | gsl_sf_legendre_Q0 | 82 |:heavy_check_mark:| 209 | | gsl_sf_legendre_Q1 | 83 |:heavy_check_mark:| 210 | | gsl_sf_log | 84 |:heavy_check_mark:| 211 | | gsl_sf_log_abs | 85 |:heavy_check_mark:| 212 | | gsl_sf_log_1plusx | 86 |:heavy_check_mark:| 213 | | gsl_sf_log_1plusx_mx | 87 |:heavy_check_mark:| 214 | | gsl_sf_psi | 88 |:heavy_check_mark:| 215 | | gsl_sf_psi_1piy | 89 | | 216 | | gsl_sf_psi_1 | 90 |:heavy_check_mark:| 217 | | gsl_sf_sin_pi | 91 | | 218 | | gsl_sf_cos_pi | 92 | | 219 | | gsl_sf_synchrotron_1 | 93 | | 220 | | gsl_sf_synchrotron_2 | 94 |:heavy_check_mark:| 221 | | gsl_sf_transport_2 | 95 | | 222 | | gsl_sf_transport_3 | 96 | | 223 | | gsl_sf_transport_4 | 97 | | 224 | | gsl_sf_transport_5 | 98 | | 225 | | gsl_sf_sin | 99 |:heavy_check_mark:| 226 | | gsl_sf_cos | 100 |:heavy_check_mark:| 227 | | gsl_sf_sinc | 101 |:heavy_check_mark:| 228 | | gsl_sf_lnsinh | 102 |:heavy_check_mark:| 229 | | gsl_sf_lncosh | 103 |:heavy_check_mark:| 230 | | gsl_sf_zeta | 104 |:heavy_check_mark:| 231 | | gsl_sf_zetam1 | 105 |:heavy_check_mark:| 232 | | gsl_sf_eta | 106 |:heavy_check_mark:| 233 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | ARG DEBIAN_FRONTEND=noninteractive 3 | 4 | RUN apt-get update && apt-get install -y --no-install-recommends apt-utils 5 | 6 | RUN apt-get install -y --no-install-recommends \ 7 | ca-certificates \ 8 | git \ 9 | build-essential \ 10 | clang-3.9 \ 11 | llvm-3.9 \ 12 | python3 \ 13 | python3-setuptools \ 14 | python3-pip 15 | 16 | RUN pip3 install wheel 17 | RUN pip3 install mpmath 18 | 19 | RUN git clone https://github.com/FP-Analysis/atomic-condition.git atom && \ 20 | cd atom 21 | 22 | # Build necessary objects. 23 | WORKDIR /atom 24 | RUN make prep 25 | RUN tar xf gsl-2.5.tar.gz 26 | 27 | # Build GSL 28 | WORKDIR /atom/gsl-2.5 29 | RUN ./configure --prefix=/atom/gslbuild CC=clang-3.9 30 | RUN make -j4 31 | RUN ln -s /atom/misc/compile-gsl-sf.sh /atom/gsl-2.5/specfunc 32 | WORKDIR /atom/gsl-2.5/specfunc 33 | RUN ./compile-gsl-sf.sh 34 | 35 | # Ready for building solver. 36 | WORKDIR /atom 37 | 38 | -------------------------------------------------------------------------------- /gsl-2.5.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FP-Analysis/atomic-condition/2bb550ed842ac92f5eb3666eaf889f8012d0237d/gsl-2.5.tar.gz -------------------------------------------------------------------------------- /lib/libPassModule.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FP-Analysis/atomic-condition/2bb550ed842ac92f5eb3666eaf889f8012d0237d/lib/libPassModule.so -------------------------------------------------------------------------------- /misc/compile-gsl-sf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LLVM_PROJECT_PATH=/atom 4 | GSL_PREFIX=/atom/gslbuild 5 | 6 | MODULE_PATH=${LLVM_PROJECT_PATH}/lib/libPassModule.so 7 | HANDLER_PATH=${LLVM_PROJECT_PATH}/build/handlers.o 8 | FPUTIL_PATH=${LLVM_PROJECT_PATH}/build/fpUtil.o 9 | 10 | 11 | libgslspecfunc_SOURCE="airy.c airy_der.c airy_zero.c atanint.c bessel.c bessel_I0.c bessel_I1.c bessel_In.c bessel_Inu.c bessel_J0.c bessel_J1.c bessel_Jn.c bessel_Jnu.c bessel_K0.c bessel_K1.c bessel_Kn.c bessel_Knu.c bessel_Y0.c bessel_Y1.c bessel_Yn.c bessel_Ynu.c bessel_amp_phase.c bessel_i.c bessel_j.c bessel_k.c bessel_olver.c bessel_temme.c bessel_y.c bessel_zero.c bessel_sequence.c beta.c beta_inc.c clausen.c coulomb.c coupling.c coulomb_bound.c dawson.c debye.c dilog.c elementary.c ellint.c elljac.c erfc.c exp.c expint.c expint3.c fermi_dirac.c gegenbauer.c gamma.c gamma_inc.c hermite.c hyperg_0F1.c hyperg_2F0.c hyperg_1F1.c hyperg_2F1.c hyperg_U.c hyperg.c laguerre.c lambert.c legendre_H3d.c legendre_P.c legendre_Qn.c legendre_con.c legendre_poly.c log.c mathieu_angfunc.c mathieu_charv.c mathieu_coeff.c mathieu_radfunc.c mathieu_workspace.c poch.c pow_int.c psi.c result.c shint.c sincos_pi.c sinint.c synchrotron.c transport.c trig.c zeta.c" 12 | 13 | clean_the_data_dir() { 14 | rm -rf ./data/ 15 | } 16 | 17 | compile_one_with_llvm_module() { 18 | echo "Compileing $1 ..." 19 | 20 | ir_file=${1%.c}.ll 21 | ir_instructed_file=${1%.c}_i.ll 22 | pic_file=.libs/${1%.c}.o 23 | nonpic_file=${1%.c}.o 24 | 25 | # echo $ir_file 26 | # echo $ir_instructed_file 27 | # echo $pic_file 28 | # echo $nonpic_file 29 | 30 | set -x 31 | clang-3.9 -DHAVE_CONFIG_H -I. -I.. -S -emit-llvm -g -o $ir_file $1 32 | opt-3.9 -S -load $MODULE_PATH -funcpass -o $ir_instructed_file $ir_file 33 | clang-3.9 -O2 -DHAVE_CONFIG_H -fPIC -DPIC -c -o $pic_file $ir_instructed_file 34 | clang-3.9 -O2 -DHAVE_CONFIG_H -c -o $nonpic_file $ir_instructed_file 35 | set +x 36 | } 37 | 38 | compile_all_with_llvm_module() { 39 | # compile_with_llvm_module sincos_pi.c 40 | for src in $libgslspecfunc_SOURCE; do 41 | compile_one_with_llvm_module $src 42 | done 43 | } 44 | 45 | compile_all_directly() { 46 | make -j4 47 | } 48 | 49 | create_libtool_file() { 50 | cat << EOF > handlers.lo 51 | # handlers.lo - a libtool object file 52 | # Generated by libtool (GNU libtool) 2.4.2 53 | # 54 | # Please DO NOT delete this file! 55 | # It is necessary for linking the library 56 | 57 | # Name of the PIC object. 58 | pic_object='${HANDLER_PATH}' 59 | 60 | # Name of the non-PIC object. 61 | non_pic_object='${HANDLER_PATH}' 62 | EOF 63 | 64 | cat << EOF > fputil.lo 65 | # fputil.lo - a libtool object file 66 | # Generated by libtool (GNU libtool) 2.4.2 67 | # 68 | # Please DO NOT delete this file! 69 | # It is necessary for linking the library 70 | 71 | # Name of the PIC object. 72 | pic_object='${FPUTIL_PATH}' 73 | 74 | # Name of the non-PIC object. 75 | non_pic_object='${FPUTIL_PATH}' 76 | EOF 77 | } 78 | 79 | linking_libgslspecfunc() { 80 | /bin/bash ../libtool --tag=CC --mode=link clang-3.9 -g -O2 -o libgslspecfunc.la airy.lo airy_der.lo airy_zero.lo atanint.lo bessel.lo bessel_I0.lo bessel_I1.lo bessel_In.lo bessel_Inu.lo bessel_J0.lo bessel_J1.lo bessel_Jn.lo bessel_Jnu.lo bessel_K0.lo bessel_K1.lo bessel_Kn.lo bessel_Knu.lo bessel_Y0.lo bessel_Y1.lo bessel_Yn.lo bessel_Ynu.lo bessel_amp_phase.lo bessel_i.lo bessel_j.lo bessel_k.lo bessel_olver.lo bessel_temme.lo bessel_y.lo bessel_zero.lo bessel_sequence.lo beta.lo beta_inc.lo clausen.lo coulomb.lo coupling.lo coulomb_bound.lo dawson.lo debye.lo dilog.lo elementary.lo ellint.lo elljac.lo erfc.lo exp.lo expint.lo expint3.lo fermi_dirac.lo gegenbauer.lo gamma.lo gamma_inc.lo hermite.lo hyperg_0F1.lo hyperg_2F0.lo hyperg_1F1.lo hyperg_2F1.lo hyperg_U.lo hyperg.lo laguerre.lo lambert.lo legendre_H3d.lo legendre_P.lo legendre_Qn.lo legendre_con.lo legendre_poly.lo log.lo mathieu_angfunc.lo mathieu_charv.lo mathieu_coeff.lo mathieu_radfunc.lo mathieu_workspace.lo poch.lo pow_int.lo psi.lo result.lo shint.lo sincos_pi.lo sinint.lo synchrotron.lo transport.lo trig.lo zeta.lo handlers.lo fputil.lo -lm 81 | } 82 | 83 | linking_libgsl_and_install() { 84 | cd .. 85 | /bin/bash ./libtool --tag=CC --mode=link clang-3.9 -g -O2 -version-info 24:0:1 -o libgsl.la -rpath ${GSL_PREFIX}/lib version.lo block/libgslblock.la blas/libgslblas.la bspline/libgslbspline.la complex/libgslcomplex.la cheb/libgslcheb.la dht/libgsldht.la diff/libgsldiff.la deriv/libgslderiv.la eigen/libgsleigen.la err/libgslerr.la fft/libgslfft.la filter/libgslfilter.la fit/libgslfit.la histogram/libgslhistogram.la ieee-utils/libgslieeeutils.la integration/libgslintegration.la interpolation/libgslinterpolation.la linalg/libgsllinalg.la matrix/libgslmatrix.la min/libgslmin.la monte/libgslmonte.la multifit/libgslmultifit.la multifit_nlinear/libgslmultifit_nlinear.la multilarge/libgslmultilarge.la multilarge_nlinear/libgslmultilarge_nlinear.la multimin/libgslmultimin.la multiroots/libgslmultiroots.la ntuple/libgslntuple.la ode-initval/libgslodeiv.la ode-initval2/libgslodeiv2.la permutation/libgslpermutation.la combination/libgslcombination.la multiset/libgslmultiset.la poly/libgslpoly.la qrng/libgslqrng.la randist/libgslrandist.la rng/libgslrng.la roots/libgslroots.la siman/libgslsiman.la sort/libgslsort.la specfunc/libgslspecfunc.la movstat/libgslmovstat.la rstat/libgslrstat.la statistics/libgslstatistics.la sum/libgslsum.la sys/libgslsys.la test/libgsltest.la utils/libutils.la vector/libgslvector.la cdf/libgslcdf.la wavelet/libgslwavelet.la spmatrix/libgslspmatrix.la spblas/libgslspblas.la splinalg/libgslsplinalg.la -lm 86 | /bin/bash ./libtool --tag=CC --mode=link clang-3.9 -g -O2 -o gsl-randist gsl-randist.o libgsl.la cblas/libgslcblas.la -lm -lstdc++ 87 | /bin/bash ./libtool --tag=CC --mode=link clang-3.9 -g -O2 -o gsl-histogram gsl-histogram.o libgsl.la cblas/libgslcblas.la -lm -lstdc++ 88 | make install 89 | } 90 | 91 | main() { 92 | set -e 93 | if [ "$1" == "link" ]; then 94 | create_libtool_file 95 | set -x 96 | linking_libgslspecfunc 97 | linking_libgsl_and_install 98 | else 99 | clean_the_data_dir 100 | compile_all_directly 101 | compile_all_with_llvm_module 102 | create_libtool_file 103 | set -x 104 | linking_libgslspecfunc 105 | linking_libgsl_and_install 106 | fi 107 | } 108 | 109 | main $1 110 | -------------------------------------------------------------------------------- /script/oracleMpmath.py: -------------------------------------------------------------------------------- 1 | import io 2 | import mpmath 3 | import signal 4 | import json 5 | import struct 6 | import math 7 | 8 | def f0(x): 9 | # airy_Ai 10 | return mpmath.airyai(x) 11 | def f1(x): 12 | # airy_Bi 13 | return mpmath.airybi(x) 14 | def f2(x): 15 | # airy_Ai_scaled 16 | scale = mpmath.exp(mpmath.mpf(2)/mpmath.mpf(3)*mpmath.sqrt(x)*x) 17 | y = mpmath.airyai(x) 18 | if x > 0.0: 19 | y = y * scale 20 | return y 21 | def f3(x): 22 | # airy_Bi_scaled 23 | scale = mpmath.exp(-mpmath.mpf(2)/mpmath.mpf(3)*mpmath.sqrt(x)*x) 24 | y = mpmath.airybi(x) 25 | if x > 0.0: 26 | y = y * scale 27 | return y 28 | def f4(x): 29 | # airy_Ai_deriv 30 | return mpmath.airyai(x, derivative=1) 31 | def f5(x): 32 | # airy_Bi_deriv 33 | return mpmath.airybi(x, derivative=1) 34 | def f6(x): 35 | # airy_Ai_deriv_scaled 36 | scale = mpmath.exp(mpmath.mpf(2)/mpmath.mpf(3)*mpmath.sqrt(x)*x) 37 | y = mpmath.airyai(x, derivative=1) 38 | if x > 0.0: 39 | y = y * scale 40 | return y 41 | def f7(x): 42 | # airy_Bi_deriv_scaled 43 | scale = mpmath.exp(-mpmath.mpf(2)/mpmath.mpf(3)*mpmath.sqrt(x)*x) 44 | y = mpmath.airybi(x, derivative=1) 45 | if x > 0.0: 46 | y = y * scale 47 | return y 48 | def f8(x): 49 | # bessel_J0 50 | return mpmath.besselj(0,x) 51 | def f9(x): 52 | # bessel_J1 53 | return mpmath.besselj(1,x) 54 | def f10(x): 55 | # bessel_Y0 56 | return mpmath.bessely(0,x) 57 | def f11(x): 58 | # bessel_Y1 59 | return mpmath.bessely(1,x) 60 | def f12(x): 61 | # bessel_I0 62 | return mpmath.besseli(0,x) 63 | def f13(x): 64 | # bessel_I1 65 | return mpmath.besseli(1,x) 66 | def f14(x): 67 | # bessel_I0_scaled 68 | scale = mpmath.exp(-abs(x)) 69 | y = mpmath.besseli(0,x) * scale 70 | return y 71 | def f15(x): 72 | # bessel_I1_scaled 73 | scale = mpmath.exp(-abs(x)) 74 | y = mpmath.besseli(1,x) * scale 75 | return y 76 | def f16(x): 77 | # bessel_K0 78 | return mpmath.besselk(0,x) 79 | def f17(x): 80 | # bessel_K1 81 | return mpmath.besselk(1,x) 82 | def f18(x): 83 | # bessel_K0_scaled 84 | scale = mpmath.exp(x) 85 | return mpmath.besselk(0,x)*scale 86 | def f19(x): 87 | # bessel_K1_scaled 88 | scale = mpmath.exp(x) 89 | return mpmath.besselk(1,x)*scale 90 | def f20(x): 91 | # bessel_j0 92 | x = mpmath.mpf(x) 93 | return mpmath.sin(x) / x 94 | def f21(x): 95 | # bessel_j1 96 | x = mpmath.mpf(x) 97 | y = (mpmath.sin(x)/x - mpmath.cos(x)) / x 98 | return y 99 | def f22(x): 100 | # bessel_j2 101 | x = mpmath.mpf(x) 102 | y = ((3/(x*x)-1) * mpmath.sin(x) - 3*mpmath.cos(x)/x) / x 103 | return y 104 | def f23(x): 105 | # bessel_y0 106 | x = mpmath.mpf(x) 107 | return -mpmath.cos(x)/x 108 | def f24(x): 109 | # bessel_y1 110 | x = mpmath.mpf(x) 111 | return -(mpmath.cos(x)/x + mpmath.sin(x)) / x 112 | def f25(x): 113 | # bessel_y2 114 | x = mpmath.mpf(x) 115 | y = (-3/(x*x*x)+1/x)*mpmath.cos(x)-(3/(x*x))*mpmath.sin(x) 116 | return y 117 | def f26(x): 118 | # bessel_i0_scaled 119 | x = mpmath.mpf(x) 120 | y = mpmath.sqrt(mpmath.pi/(2*x)) * mpmath.besseli(0.5,x) * mpmath.exp(-abs(x)) 121 | return y 122 | def f27(x): 123 | # bessel_i1_scaled 124 | x = mpmath.mpf(x) 125 | y = mpmath.sqrt(mpmath.pi/(2*x)) * mpmath.besseli(1.5,x) * mpmath.exp(-abs(x)) 126 | return y 127 | def f28(x): 128 | # bessel_i2_scaled 129 | x = mpmath.mpf(x) 130 | y = mpmath.sqrt(mpmath.pi/(2*x)) * mpmath.besseli(2.5,x) * mpmath.exp(-abs(x)) 131 | def f29(x): 132 | # bessel_k0_scaled 133 | x = mpmath.mpf(x) 134 | y = mpmath.sqrt(mpmath.pi/(2*x)) * mpmath.besselk(0.5,x) * mpmath.exp(x) 135 | return y 136 | def f30(x): 137 | # bessel_k1_scaled 138 | x = mpmath.mpf(x) 139 | y = mpmath.sqrt(mpmath.pi/(2*x)) * mpmath.besselk(1.5,x) * mpmath.exp(x) 140 | return y 141 | def f31(x): 142 | # bessel_k2_scaled 143 | x = mpmath.mpf(x) 144 | y = mpmath.sqrt(mpmath.pi/(2*x)) * mpmath.besselk(2.5,x) * mpmath.exp(x) 145 | return y 146 | def f32(x): 147 | # clausen 148 | return mpmath.clsin(2,x) 149 | def f40(x): 150 | # dilog 151 | return mpmath.polylog(2,x) 152 | def f41(x): 153 | # ellint_Kcomp 154 | x = mpmath.mpf(x) 155 | return mpmath.ellipk(x*x) 156 | def f42(x): 157 | # ellint_Ecomp 158 | x = mpmath.mpf(x) 159 | return mpmath.ellipe(x*x) 160 | def f44(x): 161 | # erfc 162 | return mpmath.erfc(x) 163 | def f45(x): 164 | # log_erfc 165 | return mpmath.log(mpmath.erfc(x)) 166 | def f46(x): 167 | # erf 168 | return mpmath.erf(x) 169 | def f47(x): 170 | # erf_Z 171 | return mpmath.npdf(x) 172 | def f48(x): 173 | # erf_Q 174 | return 1-mpmath.ncdf(x) 175 | def f49(x): 176 | # hazard 177 | return mpmath.npdf(x) / (1-mpmath.ncdf(x)) 178 | def f50(x): 179 | # exp 180 | return mpmath.exp(x) 181 | def f51(x): 182 | # expm1 183 | return mpmath.expm1(x) 184 | def f52(x): 185 | # exprel 186 | x = mpmath.mpf(x) 187 | return mpmath.expm1(x)/x 188 | def f53(x): 189 | # exprel_2 190 | x = mpmath.mpf(x) 191 | y = 2*(mpmath.expm1(x)-x)/(x*x) 192 | return y 193 | def f54(x): 194 | # expint_E1 195 | return mpmath.expint(1, x) 196 | def f55(x): 197 | # expint_E2 198 | return mpmath.expint(2, x) 199 | def f56(x): 200 | # expint_E1_scaled 201 | return mpmath.expint(1, x) * mpmath.exp(x) 202 | def f57(x): 203 | # expint_E2_scaled 204 | return mpmath.expint(2, x) * mpmath.exp(x) 205 | def f58(x): 206 | # expint_Ei 207 | return mpmath.ei(x) 208 | def f59(x): 209 | # expint_Ei_scaled 210 | return mpmath.ei(x) * mpmath.exp(-x) 211 | def f60(x): 212 | # Shi 213 | return mpmath.shi(x) 214 | def f61(x): 215 | # Chi 216 | return mpmath.chi(x) 217 | def f63(x): 218 | # Si 219 | return mpmath.si(x) 220 | def f64(x): 221 | # Ci 222 | return mpmath.ci(x) 223 | def f66(x): 224 | # fermi_dirac_m1 225 | return -mpmath.polylog(0, -mpmath.exp(x)) 226 | def f67(x): 227 | # fermi_dirac_0 228 | return -mpmath.polylog(1, -mpmath.exp(x)) 229 | def f68(x): 230 | # fermi_dirac_1 231 | return -mpmath.polylog(2, -mpmath.exp(x)) 232 | def f69(x): 233 | # fermi_dirac_2 234 | return -mpmath.polylog(3, -mpmath.exp(x)) 235 | def f70(x): 236 | # fermi_dirac_mhalf 237 | return -mpmath.polylog(0.5, -mpmath.exp(x)) 238 | def f71(x): 239 | # fermi_dirac_half 240 | try: 241 | return -mpmath.polylog(1.5, -mpmath.exp(x)) 242 | except: 243 | return None 244 | def f72(x): 245 | # fermi_dirac_3half 246 | try: 247 | return -mpmath.polylog(2.5, -mpmath.exp(x)) 248 | except: 249 | return None 250 | def f73(x): 251 | # lngamma 252 | try: 253 | return mpmath.loggamma(x) 254 | except: 255 | return None 256 | def f74(x): 257 | # gamma 258 | try: 259 | return mpmath.gamma(x) 260 | except: 261 | return None 262 | def f76(x): 263 | # gammainv 264 | try: 265 | return mpmath.rgamma(x) 266 | except: 267 | return None 268 | def f77(x): 269 | # lambert_W0 270 | return mpmath.lambertw(x) 271 | def f78(x): 272 | # lambert_Wm1 273 | if x >= 0: 274 | return mpmath.lambertw(x) 275 | else: 276 | return mpmath.lambertw(x, -1) 277 | def f79(x): 278 | # legendre_P1 279 | return mpmath.legendre(1,x) 280 | def f80(x): 281 | # legendre_P2 282 | return mpmath.legendre(2,x) 283 | def f81(x): 284 | # legendre_P3 285 | return mpmath.legendre(3,x) 286 | def f82(x): 287 | # legendre_Q0 288 | return mpmath.legenq(0,0,x) 289 | def f83(x): 290 | # legendre_Q1 291 | return mpmath.legenq(1,0,x) 292 | def f84(x): 293 | # log 294 | return mpmath.log(x) 295 | def f85(x): 296 | # log_abs 297 | return mpmath.log(abs(x)) 298 | def f86(x): 299 | # log_1plusx 300 | return mpmath.log1p(x) 301 | def f87(x): 302 | # log_1plusx_mx 303 | x = mpmath.mpf(x) 304 | return mpmath.log1p(x)-x 305 | def f88(x): 306 | # psi 307 | if abs(x) > 1e100: 308 | return None 309 | try: 310 | return mpmath.psi(0,x) 311 | except: 312 | return None 313 | def f90(x): 314 | # psi_1 315 | if abs(x) > 1e100: 316 | return None 317 | try: 318 | return mpmath.psi(1,x) 319 | except: 320 | return None 321 | def f94(x): 322 | # synchrotron_2 323 | x = mpmath.mpf(x) 324 | coff=mpmath.mpf(2)/mpmath.mpf(3) 325 | return x * mpmath.besselk(coff, x) 326 | def f99(x): 327 | # sin 328 | return mpmath.sin(x) 329 | def f100(x): 330 | # cos 331 | return mpmath.cos(x) 332 | def f101(x): 333 | # sinc 334 | return mpmath.sincpi(x) 335 | def f102(x): 336 | # lnsinh 337 | return mpmath.log(mpmath.sinh(x)) 338 | def f103(x): 339 | # lncosh 340 | return mpmath.log(mpmath.cosh(x)) 341 | def f104(x): 342 | # zeta 343 | return mpmath.zeta(x) 344 | def f105(x): 345 | # zetam1 346 | return mpmath.zeta(x)-1 347 | def f106(x): 348 | # eta 349 | return mpmath.altzeta(x) 350 | 351 | funcDict = { 352 | 0: {"direct_support": True , "support": True , "func": f0}, 353 | 1: {"direct_support": True , "support": True , "func": f1}, 354 | 2: {"direct_support": False, "support": True , "func": f2}, 355 | 3: {"direct_support": False, "support": True , "func": f3}, 356 | 4: {"direct_support": True , "support": True , "func": f4}, 357 | 5: {"direct_support": True , "support": True , "func": f5}, 358 | 6: {"direct_support": False, "support": True , "func": f6}, 359 | 7: {"direct_support": False, "support": True , "func": f7}, 360 | 8: {"direct_support": True , "support": True , "func": f8}, 361 | 9: {"direct_support": True , "support": True , "func": f9}, 362 | 10: {"direct_support": True , "support": True , "func": f10}, 363 | 11: {"direct_support": True , "support": True , "func": f11}, 364 | 12: {"direct_support": True , "support": True , "func": f12}, 365 | 13: {"direct_support": True , "support": True , "func": f13}, 366 | 14: {"direct_support": False, "support": True , "func": f14}, 367 | 15: {"direct_support": False, "support": True , "func": f15}, 368 | 16: {"direct_support": True , "support": True , "func": f16}, 369 | 17: {"direct_support": True , "support": True , "func": f17}, 370 | 18: {"direct_support": False, "support": True , "func": f18}, 371 | 19: {"direct_support": False, "support": True , "func": f19}, 372 | 20: {"direct_support": False, "support": True , "func": f20}, 373 | 21: {"direct_support": False, "support": True , "func": f21}, 374 | 22: {"direct_support": False, "support": True , "func": f22}, 375 | 23: {"direct_support": False, "support": True , "func": f23}, 376 | 24: {"direct_support": False, "support": True , "func": f24}, 377 | 25: {"direct_support": False, "support": True , "func": f25}, 378 | 26: {"direct_support": False, "support": True , "func": f26}, 379 | 27: {"direct_support": False, "support": True , "func": f27}, 380 | 28: {"direct_support": False, "support": True , "func": f28}, 381 | 29: {"direct_support": False, "support": True , "func": f29}, 382 | 30: {"direct_support": False, "support": True , "func": f30}, 383 | 31: {"direct_support": False, "support": True , "func": f31}, 384 | 32: {"direct_support": True , "support": True , "func": f32}, 385 | 33: {"direct_support": False, "support": False}, 386 | 34: {"direct_support": False, "support": False}, 387 | 35: {"direct_support": False, "support": False}, 388 | 36: {"direct_support": False, "support": False}, 389 | 37: {"direct_support": False, "support": False}, 390 | 38: {"direct_support": False, "support": False}, 391 | 39: {"direct_support": False, "support": False}, 392 | 40: {"direct_support": True , "support": True , "func": f40}, 393 | 41: {"direct_support": True , "support": True , "func": f41}, 394 | 42: {"direct_support": True , "support": True , "func": f42}, 395 | 43: {"direct_support": False, "support": False}, 396 | 44: {"direct_support": True , "support": True , "func": f44}, 397 | 45: {"direct_support": False, "support": True , "func": f45}, 398 | 46: {"direct_support": True , "support": True , "func": f46}, 399 | 47: {"direct_support": True , "support": True , "func": f47}, 400 | 48: {"direct_support": True , "support": True , "func": f48}, 401 | 49: {"direct_support": False, "support": True , "func": f49}, 402 | 50: {"direct_support": True , "support": True , "func": f50}, 403 | 51: {"direct_support": True , "support": True , "func": f51}, 404 | 52: {"direct_support": False, "support": True , "func": f52}, 405 | 53: {"direct_support": False, "support": True , "func": f53}, 406 | 54: {"direct_support": True , "support": True , "func": f54}, 407 | 55: {"direct_support": True , "support": True , "func": f55}, 408 | 56: {"direct_support": False, "support": True , "func": f56}, 409 | 57: {"direct_support": False, "support": True , "func": f57}, 410 | 58: {"direct_support": True , "support": True , "func": f58}, 411 | 59: {"direct_support": False, "support": True , "func": f59}, 412 | 60: {"direct_support": True , "support": True , "func": f60}, 413 | 61: {"direct_support": True , "support": True , "func": f61}, 414 | 62: {"direct_support": False, "support": False}, 415 | 63: {"direct_support": True , "support": True , "func": f63}, 416 | 64: {"direct_support": True , "support": True , "func": f64}, 417 | 65: {"direct_support": False, "support": False}, 418 | 66: {"direct_support": False, "support": True , "func": f66}, 419 | 67: {"direct_support": False, "support": True , "func": f67}, 420 | 68: {"direct_support": False, "support": True , "func": f68}, 421 | 69: {"direct_support": False, "support": True , "func": f69}, 422 | 70: {"direct_support": False, "support": True , "func": f70}, 423 | 71: {"direct_support": False, "support": True , "func": f71}, 424 | 72: {"direct_support": False, "support": True , "func": f72}, 425 | 73: {"direct_support": True , "support": True , "func": f73}, 426 | 74: {"direct_support": True , "support": True , "func": f74}, 427 | 75: {"direct_support": False, "support": False}, 428 | 76: {"direct_support": True , "support": True , "func": f76}, 429 | 77: {"direct_support": True , "support": True , "func": f77}, 430 | 78: {"direct_support": True , "support": True , "func": f78}, 431 | 79: {"direct_support": True , "support": True , "func": f79}, 432 | 80: {"direct_support": True , "support": True , "func": f80}, 433 | 81: {"direct_support": True , "support": True , "func": f81}, 434 | 82: {"direct_support": True , "support": True , "func": f82}, 435 | 83: {"direct_support": True , "support": True , "func": f83}, 436 | 84: {"direct_support": True , "support": True , "func": f84}, 437 | 85: {"direct_support": False, "support": True , "func": f85}, 438 | 86: {"direct_support": True , "support": True , "func": f86}, 439 | 87: {"direct_support": False, "support": True , "func": f87}, 440 | 88: {"direct_support": True , "support": True , "func": f88}, 441 | 89: {"direct_support": False, "support": False}, 442 | 90: {"direct_support": True , "support": True , "func": f90}, 443 | 91: {"direct_support": False, "support": False}, 444 | 92: {"direct_support": False, "support": False}, 445 | 93: {"direct_support": False, "support": False}, 446 | 94: {"direct_support": False, "support": True , "func": f94}, 447 | 95: {"direct_support": False, "support": False}, 448 | 96: {"direct_support": False, "support": False}, 449 | 97: {"direct_support": False, "support": False}, 450 | 98: {"direct_support": False, "support": False}, 451 | 99: {"direct_support": True , "support": True , "func": f99}, 452 | 100: {"direct_support": True , "support": True , "func": f100}, 453 | 101: {"direct_support": True , "support": True , "func": f101}, 454 | 102: {"direct_support": False, "support": True , "func": f102}, 455 | 103: {"direct_support": False, "support": True , "func": f103}, 456 | 104: {"direct_support": True , "support": True , "func": f104}, 457 | 105: {"direct_support": False, "support": True , "func": f105}, 458 | 106: {"direct_support": True , "support": True , "func": f106}, 459 | } 460 | 461 | class GetOracle: 462 | def __init__(self): 463 | # Set mpmath precision 464 | mpmath.mp.prec=128 465 | def getOracleValue(self, funcIndex, inputX): 466 | funcIndex = int(funcIndex) 467 | # print("Func: ", funcIndex, "Input: ", inputX) 468 | if funcIndex not in funcDict: 469 | print("Function Index Error") 470 | return None 471 | if funcDict[funcIndex]['support'] == False: 472 | print("Function not supported by mpmath") 473 | return None 474 | inputX = mpmath.mpf(inputX) 475 | func = funcDict[funcIndex]['func'] 476 | outY = func(inputX) 477 | if outY == None: 478 | return None 479 | outY = outY.real 480 | return outY 481 | def calcRelativeError(self, oracle, output): 482 | oracle = mpmath.mpf(oracle) 483 | output = mpmath.mpf(output) 484 | delta = abs(output-oracle) 485 | if delta == 0: 486 | return 0 487 | try: 488 | return abs(delta / oracle) 489 | except: 490 | return float("inf") 491 | 492 | class OutputParser: 493 | def __init__(self): 494 | self.outputFile="tempOutput.out" 495 | self.writeToFile="Output.out" 496 | with io.open(self.outputFile) as f: 497 | self.rawData = f.readlines() 498 | self.data = {} 499 | self.oracleMod = GetOracle() 500 | def readAndCalculate(self): 501 | valid = True 502 | for line in self.rawData: 503 | # Determine whether valid 504 | if line.startswith('------------------'): 505 | valid = True 506 | continue 507 | if valid == False: 508 | continue 509 | 510 | # Read only for valid index. 511 | if line.startswith("Function Index"): 512 | curIndex = int(line.split(":")[1]) 513 | if funcDict[curIndex]['support'] == False: 514 | # Read Until next 515 | valid = False 516 | continue 517 | self.data[curIndex] = {} 518 | continue 519 | if line.startswith("Execution Time"): 520 | curTime = float(line.split(":")[1].split()[0]) 521 | self.data[curIndex]['time'] = curTime 522 | continue 523 | if line.startswith("**************"): 524 | self.printInfo(curIndex) 525 | # Wait for input, system('pause') 526 | # input() 527 | continue 528 | if line.startswith("Format:"): 529 | self.data[curIndex]['input_list'] = [] 530 | # Format: InstID, OpCode, MaxAtomCond, Input, Output, CountToEnd, ConditionToEnd 531 | if line.startswith("Data:"): 532 | inputInfo = {} 533 | terms = line.split(":")[1] 534 | terms = terms.split(',') 535 | inputInfo['inst_id'] = int(terms[0]) 536 | inputInfo['op_code'] = int(terms[1]) 537 | inputInfo['atom_cond'] = float(terms[2]) 538 | # Input / Output 539 | inputX = float(terms[3]) 540 | outputY = float(terms[4]) 541 | if math.isfinite(inputX) == False or math.isfinite(outputY) == False: 542 | continue 543 | inputInfo['input'] = inputX 544 | inputInfo['output'] = outputY 545 | # print(inputX, outputY) 546 | # Data for priorization 547 | countToEnd = int(terms[5]) 548 | conditionToEnd = float(terms[6]) 549 | inputInfo['count_to_end'] = countToEnd 550 | inputInfo['condition_to_end'] = conditionToEnd 551 | 552 | # Calculate Oracle 553 | oracleVal = self.oracleMod.getOracleValue(curIndex, inputX) 554 | if oracleVal == None: 555 | print("On function:", curIndex) 556 | print("Mpmath not support input: ", inputX) 557 | continue 558 | 559 | relativeErr = self.oracleMod.calcRelativeError(oracleVal, outputY) 560 | inputInfo['oracle'] = oracleVal 561 | inputInfo['relative_err'] = relativeErr 562 | self.data[curIndex]['input_list'].append(inputInfo) 563 | continue 564 | def printInfo(self, index): 565 | print("------------------------") 566 | info = self.data[index] 567 | print("Function Index:", index) 568 | inputinfo = info['input_list'] 569 | relList = sorted(inputinfo, key=lambda x: x['relative_err'], reverse=True) 570 | print("Max Relative Error:") 571 | for item in relList[:1]: 572 | print(" Input: ", format(float(item['input']), '.15e')) 573 | print(" Output:", format(float(item['output']), '.15e')) 574 | print(" Oracle:", format(float(item['oracle']), '.15e')) 575 | print(" Relative Error:", format(float(item['relative_err']), '.5e')) 576 | print("------------------------") 577 | 578 | def writeToJson(self): 579 | tempData = self.data 580 | needConvert = set(['input', 'output', 'oracle', 'relative_err', 'ulp_err', 'condition_to_end']) 581 | for func_index in tempData: 582 | for i in range(len(tempData[func_index]['input_list'])): 583 | for key in tempData[func_index]['input_list'][i]: 584 | if key in needConvert: 585 | tempData[func_index]['input_list'][i][key] = float(tempData[func_index]['input_list'][i][key]) 586 | # This encoder setting not works with Python3.6 587 | # https://stackoverflow.com/questions/32521823/json-encoder-float-repr-changed-but-no-effect 588 | json.encoder.FLOAT_REPR=lambda x: format(x, '.15e') 589 | with io.open(self.writeToFile, 'w') as f: 590 | f.write(json.dumps(tempData, sort_keys=True, indent=2)) 591 | 592 | def main(): 593 | op = OutputParser() 594 | op.readAndCalculate() 595 | op.writeToJson() 596 | 597 | 598 | if __name__ == '__main__': 599 | main() 600 | 601 | -------------------------------------------------------------------------------- /script/reproduce.py: -------------------------------------------------------------------------------- 1 | import json 2 | import io 3 | import random 4 | 5 | random.seed(20191025) 6 | 7 | with io.open('Output.out') as f: 8 | data = json.load(f) 9 | 10 | def getErrorList(i): 11 | funcIndex = str(i) 12 | if funcIndex in data: 13 | inputs = data[funcIndex]['input_list'] 14 | errList = [item['relative_err'] for item in inputs] 15 | return errList 16 | else: 17 | return [] 18 | 19 | def rankingInfo(): 20 | rand = [0,0,0,0,0,0] 21 | rank = [0,0,0,0,0,0] 22 | for i in range(107): 23 | funcIndex = str(i) 24 | if funcIndex not in data: 25 | continue 26 | inputs = data[funcIndex]['input_list'] 27 | # Ranked 28 | inputs.sort(key=lambda x: x['count_to_end']) 29 | for k in range(1,6): 30 | errListTopK = [item['relative_err'] for item in inputs[:k]] 31 | maxTopK = max(errListTopK, default=0) 32 | if maxTopK >= 1e-3: 33 | rank[k] += 1 34 | # Random 35 | random.shuffle(inputs) 36 | for k in range(1,6): 37 | errListTopK = [item['relative_err'] for item in inputs[:k]] 38 | maxTopK = max(errListTopK, default=0) 39 | if maxTopK >= 1e-3: 40 | rand[k] += 1 41 | print('----------------------') 42 | print('Line Chart Info in Fig.4') 43 | print('Prioritized:', rank) 44 | print('Random: ', rand) 45 | print('----------------------') 46 | 47 | def histogramInfo(): 48 | hist = [0,0,0,0,0,0,0,0] 49 | for i in range(107): 50 | funcIndex = str(i) 51 | if funcIndex not in data: 52 | continue 53 | errList = getErrorList(i) 54 | maxErr = max(errList, default=0) 55 | if maxErr < 1e-15: 56 | hist[0] += 1 57 | elif maxErr < 1e-12: 58 | hist[1] += 1 59 | elif maxErr < 1e-9: 60 | hist[2] += 1 61 | elif maxErr < 1e-6: 62 | hist[3] += 1 63 | elif maxErr < 1e-3: 64 | hist[4] += 1 65 | elif maxErr< 1: 66 | hist[5] += 1 67 | elif maxErr < 1e3: 68 | hist[6] += 1 69 | else: 70 | hist[7] += 1 71 | print('----------------------') 72 | print('Histogram Info in Fig.3') 73 | print('[0,1e-15) ', hist[0]) 74 | print('[1e-15,1e-12)', hist[1]) 75 | print('[1e-12,1e-9) ', hist[2]) 76 | print('[1e-9,1e-6) ', hist[3]) 77 | print('[1e-6,1e-3) ', hist[4]) 78 | print(' Insignificant Error:', sum(hist[:5])) 79 | print('----------------------') 80 | print('[1e-3,1) ', hist[5]) 81 | print('[1, 1e3) ', hist[6]) 82 | print('[1e3, +inf) ', hist[7]) 83 | print(' Significant Error: ', sum(hist[5:])) 84 | print('----------------------') 85 | print(' Total: ', sum(hist)) 86 | print('----------------------') 87 | 88 | histogramInfo() 89 | rankingInfo() 90 | -------------------------------------------------------------------------------- /src/communicator.h: -------------------------------------------------------------------------------- 1 | #ifndef COMM_H 2 | #define COMM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "opcode.h" 8 | 9 | struct InstInfo 10 | { 11 | uint64_t opcode = -1; 12 | double op1 = 0; 13 | double op2 = 0; 14 | uint64_t instID = 0; 15 | }; 16 | class Communicator { 17 | public: 18 | static Communicator& getInstance() { 19 | static Communicator instance; 20 | return instance; 21 | } 22 | private: 23 | Communicator() { } 24 | public: 25 | Communicator(Communicator const &) = delete; 26 | void operator=(Communicator const&) = delete; 27 | 28 | private: 29 | std::vector infoList; 30 | std::set instIDSet; 31 | bool record = false; 32 | int unStable[OPSIZE] = {}; 33 | 34 | public: 35 | void initComm() { 36 | clearInfoList(); 37 | record = true; 38 | // setup all unstable operations. 39 | unStable[OP_ADD] = 1; 40 | unStable[OP_SUB] = 1; 41 | unStable[OP_MUL] = 0; 42 | unStable[OP_DIV] = 0; 43 | 44 | unStable[OP_SIN] = 1; 45 | unStable[OP_COS] = 1; 46 | unStable[OP_TAN] = 1; 47 | unStable[OP_ASIN] = 1; 48 | unStable[OP_ACOS] = 1; 49 | unStable[OP_ATAN] = 0; 50 | unStable[OP_ATAN2] = 0; 51 | 52 | unStable[OP_SINH] = 1; 53 | unStable[OP_COSH] = 1; 54 | unStable[OP_TANH] = 0; 55 | 56 | unStable[OP_EXP] = 0; 57 | unStable[OP_LOG] = 1; 58 | unStable[OP_LOG10] = 1; 59 | 60 | unStable[OP_SQRT] = 0; 61 | unStable[OP_POW] = 1; 62 | } 63 | 64 | void clearInstIDSet() { 65 | std::set emptySet; 66 | std::swap(instIDSet, emptySet); 67 | } 68 | 69 | void clear() { 70 | clearInfoList(); 71 | } 72 | 73 | void clearInfoList() { 74 | std::vector emptyList; 75 | std::swap(infoList, emptyList); 76 | } 77 | 78 | void writeInstInfo(uint64_t opcode, double op1, double op2, uint64_t instID) { 79 | if (record == false) { 80 | return; 81 | } 82 | if (unStable[opcode] == 0) { 83 | return; 84 | } 85 | // The below code works if record sets to true. 86 | InstInfo info; 87 | info.opcode = opcode; 88 | info.op1 = op1; 89 | info.op2 = op2; 90 | info.instID = instID; 91 | infoList.push_back(info); 92 | } 93 | 94 | std::vector getInstInfoList() { 95 | return infoList; 96 | } 97 | 98 | bool isEmpty() { 99 | return infoList.empty(); 100 | } 101 | 102 | }; 103 | 104 | #endif -------------------------------------------------------------------------------- /src/fpInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef FPINTERFACE_H 2 | #define FPINTERFACE_H 3 | 4 | #include "communicator.h" 5 | #include 6 | #include 7 | #include "target.h" 8 | 9 | const std::vector> simpleFuncList = { 10 | foo, 11 | }; 12 | 13 | const std::vector> GSLFuncList = { 14 | // gsl_sf_airy.h 15 | std::bind(gsl_sf_airy_Ai_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 16 | std::bind(gsl_sf_airy_Bi_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 17 | std::bind(gsl_sf_airy_Ai_scaled_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 18 | std::bind(gsl_sf_airy_Bi_scaled_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 19 | std::bind(gsl_sf_airy_Ai_deriv_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 20 | std::bind(gsl_sf_airy_Bi_deriv_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 21 | std::bind(gsl_sf_airy_Ai_deriv_scaled_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 22 | std::bind(gsl_sf_airy_Bi_deriv_scaled_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 23 | // gsl_sf_bessel.h 24 | gsl_sf_bessel_J0_e, 25 | gsl_sf_bessel_J1_e, 26 | gsl_sf_bessel_Y0_e, 27 | gsl_sf_bessel_Y1_e, 28 | gsl_sf_bessel_I0_e, 29 | gsl_sf_bessel_I1_e, 30 | gsl_sf_bessel_I0_scaled_e, 31 | gsl_sf_bessel_I1_scaled_e, 32 | gsl_sf_bessel_K0_e, 33 | gsl_sf_bessel_K1_e, 34 | gsl_sf_bessel_K0_scaled_e, 35 | gsl_sf_bessel_K1_scaled_e, 36 | gsl_sf_bessel_j0_e, 37 | gsl_sf_bessel_j1_e, 38 | gsl_sf_bessel_j2_e, 39 | gsl_sf_bessel_y0_e, 40 | gsl_sf_bessel_y1_e, 41 | gsl_sf_bessel_y2_e, 42 | gsl_sf_bessel_i0_scaled_e, 43 | gsl_sf_bessel_i1_scaled_e, 44 | gsl_sf_bessel_i2_scaled_e, 45 | gsl_sf_bessel_k0_scaled_e, 46 | gsl_sf_bessel_k1_scaled_e, 47 | gsl_sf_bessel_k2_scaled_e, 48 | // gsl_sf_clausen.h 49 | gsl_sf_clausen_e, 50 | // gsl_sf_coulomb.h 51 | // gsl_sf_coupling.h 52 | // gsl_sf_dawson.h 53 | gsl_sf_dawson_e, 54 | // gsl_sf_debye.h 55 | gsl_sf_debye_1_e, 56 | gsl_sf_debye_2_e, 57 | gsl_sf_debye_3_e, 58 | gsl_sf_debye_4_e, 59 | gsl_sf_debye_5_e, 60 | gsl_sf_debye_6_e, 61 | // gsl_sf_dilog.h 62 | gsl_sf_dilog_e, 63 | // gsl_sf_elementary.h 64 | // gsl_sf_ellint.h 65 | std::bind(gsl_sf_ellint_Kcomp_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 66 | std::bind(gsl_sf_ellint_Ecomp_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 67 | std::bind(gsl_sf_ellint_Dcomp_e, std::placeholders::_1, GSL_PREC_DOUBLE, std::placeholders::_2), 68 | // gsl_sf_elljac.h 69 | // gsl_sf_erf.h 70 | gsl_sf_erfc_e, 71 | gsl_sf_log_erfc_e, 72 | gsl_sf_erf_e, 73 | gsl_sf_erf_Z_e, 74 | gsl_sf_erf_Q_e, 75 | gsl_sf_hazard_e, 76 | // gsl_sf_exp.h 77 | gsl_sf_exp_e, 78 | gsl_sf_expm1_e, 79 | gsl_sf_exprel_e, 80 | gsl_sf_exprel_2_e, 81 | // gsl_sf_expint.h 82 | gsl_sf_expint_E1_e, 83 | gsl_sf_expint_E2_e, 84 | gsl_sf_expint_E1_scaled_e, 85 | gsl_sf_expint_E2_scaled_e, 86 | gsl_sf_expint_Ei_e, 87 | gsl_sf_expint_Ei_scaled_e, 88 | gsl_sf_Shi_e, 89 | gsl_sf_Chi_e, 90 | gsl_sf_expint_3_e, 91 | gsl_sf_Si_e, 92 | gsl_sf_Ci_e, 93 | gsl_sf_atanint_e, 94 | // gsl_sf_fermi_dirac.h 95 | gsl_sf_fermi_dirac_m1_e, 96 | gsl_sf_fermi_dirac_0_e, 97 | gsl_sf_fermi_dirac_1_e, 98 | gsl_sf_fermi_dirac_2_e, 99 | gsl_sf_fermi_dirac_mhalf_e, 100 | gsl_sf_fermi_dirac_half_e, 101 | gsl_sf_fermi_dirac_3half_e, 102 | // gsl_sf_gamma.h 103 | gsl_sf_lngamma_e, 104 | gsl_sf_gamma_e, 105 | gsl_sf_gammastar_e, 106 | gsl_sf_gammainv_e, 107 | // gsl_sf_gegenbauer.h 108 | // gsl_sf_hermite.h 109 | // gsl_sf_hyperg.h 110 | // gsl_sf_laguerre.h 111 | // gsl_sf_lambert.h 112 | gsl_sf_lambert_W0_e, 113 | gsl_sf_lambert_Wm1_e, 114 | // gsl_sf_legendre.h 115 | gsl_sf_legendre_P1_e, 116 | gsl_sf_legendre_P2_e, 117 | gsl_sf_legendre_P3_e, 118 | gsl_sf_legendre_Q0_e, 119 | gsl_sf_legendre_Q1_e, 120 | // gsl_sf_log.h 121 | gsl_sf_log_e, 122 | gsl_sf_log_abs_e, 123 | gsl_sf_log_1plusx_e, 124 | gsl_sf_log_1plusx_mx_e, 125 | // gsl_sf_mathieu.h 126 | // gsl_sf_pow_int.h 127 | // gsl_sf_psi.h 128 | gsl_sf_psi_e, 129 | gsl_sf_psi_1piy_e, 130 | gsl_sf_psi_1_e, 131 | // gsl_sf_sincos_pi.h 132 | gsl_sf_sin_pi_e, 133 | gsl_sf_cos_pi_e, 134 | // gsl_sf_synchrotron.h 135 | gsl_sf_synchrotron_1_e, 136 | gsl_sf_synchrotron_2_e, 137 | // gsl_sf_transport.h 138 | gsl_sf_transport_2_e, 139 | gsl_sf_transport_3_e, 140 | gsl_sf_transport_4_e, 141 | gsl_sf_transport_5_e, 142 | // gsl_sf_trig.h 143 | gsl_sf_sin_e, 144 | gsl_sf_cos_e, 145 | gsl_sf_sinc_e, 146 | gsl_sf_lnsinh_e, 147 | gsl_sf_lncosh_e, 148 | // gsl_sf_zeta.h 149 | gsl_sf_zeta_e, 150 | gsl_sf_zetam1_e, 151 | gsl_sf_eta_e 152 | }; 153 | 154 | class FloatingPointFunction { 155 | public: 156 | virtual void call(double x) = 0; 157 | virtual double getResult() = 0; 158 | virtual double callAndGetResult(double x) = 0; 159 | virtual bool isSuccess() = 0; 160 | std::vector getInstInfoList() { 161 | return comm.getInstInfoList(); 162 | } 163 | FloatingPointFunction() : comm( Communicator::getInstance() ) { 164 | comm.initComm(); 165 | } 166 | protected: 167 | double in, out; 168 | int status; 169 | Communicator &comm; 170 | }; 171 | 172 | 173 | class GSLFunction : public FloatingPointFunction { 174 | public: 175 | GSLFunction(int index) { 176 | gsl_set_error_handler_off(); 177 | 178 | if (index < 0 || index >= GSLFuncList.size()) { 179 | std::cout << "Invalid index in [GSLFunction]: " << index << '\n'; 180 | GSLFuncRef = GSLFuncList[0]; 181 | return; 182 | } 183 | GSLFuncRef = GSLFuncList[index]; 184 | return; 185 | } 186 | 187 | void call(double x) { 188 | comm.clear(); 189 | in = x; 190 | status = GSLFuncRef(in, &gslres); 191 | out = gslres.val; 192 | } 193 | 194 | double callAndGetResult(double x) { 195 | call(x); 196 | return out; 197 | } 198 | 199 | double getResult() { return out; } 200 | bool isSuccess() { return (status == GSL_SUCCESS); } 201 | 202 | private: 203 | std::function GSLFuncRef; 204 | gsl_sf_result gslres; 205 | }; 206 | 207 | class SimpleFunction : public FloatingPointFunction { 208 | public: 209 | SimpleFunction(int index) { 210 | if (index < 0 || index >= simpleFuncList.size()) { 211 | std::cout << "Invalid index in [SimpleFunction]: " << index << '\n'; 212 | funcRef = simpleFuncList[0]; 213 | return; 214 | } 215 | funcRef = simpleFuncList[index]; 216 | } 217 | void call(double x) { 218 | comm.clear(); 219 | in = x; 220 | out = funcRef(x); 221 | if (std::isnan(out)) { 222 | status = -1; 223 | } 224 | else { 225 | status = 0; 226 | } 227 | } 228 | 229 | double callAndGetResult(double x) { 230 | call(x); 231 | return out; 232 | } 233 | 234 | double getResult() { return out; } 235 | bool isSuccess() { return (status == 0); } 236 | 237 | private: 238 | std::function funcRef; 239 | }; 240 | 241 | #endif -------------------------------------------------------------------------------- /src/fpUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "fpUtil.h" 2 | 3 | double fpUtil::i64ToDouble(uint64_t i) { 4 | return *(double*)(&i); 5 | } 6 | 7 | uint64_t fpUtil::doubleToI64(double d) { 8 | return *(uint64_t*)(&d); 9 | } 10 | 11 | float fpUtil::i32ToFloat(uint32_t i) { 12 | return *(float*)(&i); 13 | } 14 | 15 | uint32_t fpUtil::floatToI32(float f) { 16 | return *(uint32_t*)(&f); 17 | } 18 | 19 | uint64_t fpUtil::getDoubleSign(double d) { 20 | uint64_t i = doubleToI64(d); 21 | return (i & DBL_SIGNMASK) >> 63; 22 | } 23 | 24 | uint64_t fpUtil::getDoubleExpo(double d) { 25 | uint64_t i = doubleToI64(d); 26 | return (i & DBL_EXPOMASK) >> 52; 27 | } 28 | 29 | uint64_t fpUtil::getDoubleFrac(double d) { 30 | uint64_t i = doubleToI64(d); 31 | return (i & DBL_FRACMASK); 32 | } 33 | 34 | uint32_t fpUtil::getFloatSign(float f) { 35 | uint32_t i = floatToI32(f); 36 | return (i & FLT_SIGNMASK) >> 31; 37 | } 38 | 39 | uint32_t fpUtil::getFloatExpo(float f) { 40 | uint32_t i = floatToI32(f); 41 | return (i & FLT_EXPOMASK) >> 23; 42 | } 43 | 44 | uint32_t fpUtil::getFloatFrac(float f) { 45 | uint32_t i = floatToI32(f); 46 | return (i & FLT_FRACMASK); 47 | } 48 | 49 | double fpUtil::buildDouble(uint64_t sign, uint64_t expo, uint64_t frac) { 50 | uint64_t bits; 51 | bits = (sign << 63) & DBL_SIGNMASK; 52 | bits |= (expo << 52) & DBL_EXPOMASK; 53 | bits |= (frac & DBL_FRACMASK); 54 | return i64ToDouble(bits); 55 | } 56 | 57 | float fpUtil::buildFloat(uint32_t sign, uint32_t expo, uint32_t frac) { 58 | uint32_t bits; 59 | bits = (sign << 31) & FLT_SIGNMASK; 60 | bits |= (expo << 23) & FLT_EXPOMASK; 61 | bits |= (frac & FLT_FRACMASK); 62 | return i32ToFloat(bits); 63 | } 64 | 65 | double fpUtil::doubleULP(double d) { 66 | uint64_t bits = doubleToI64(d); 67 | // make it positive. 68 | bits = bits & (DBL_EXPOMASK | DBL_FRACMASK); 69 | d = i64ToDouble(bits); 70 | double d_plus = i64ToDouble(bits+1); 71 | return d_plus - d; 72 | } 73 | 74 | float fpUtil::floatULP(float f) { 75 | uint32_t bits = floatToI32(f); 76 | // make it positive. 77 | bits = bits & (FLT_EXPOMASK | FLT_FRACMASK); 78 | f = i32ToFloat(bits); 79 | float f_plus = i32ToFloat(bits+1); 80 | return f_plus - f; 81 | } 82 | 83 | uint64_t fpUtil::doubleDist(double d1, double d2) { 84 | uint64_t dist, bits1, bits2; 85 | bits1 = doubleToI64(d1) & (DBL_EXPOMASK | DBL_FRACMASK); 86 | bits2 = doubleToI64(d2) & (DBL_EXPOMASK | DBL_FRACMASK); 87 | if ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) { 88 | dist = bits1 + bits2; 89 | } 90 | else { 91 | if (bits1 > bits2) 92 | dist = bits1 - bits2; 93 | else 94 | dist = bits2 - bits1; 95 | } 96 | return dist; 97 | } 98 | 99 | uint32_t fpUtil::floatDist(float f1, float f2) { 100 | uint32_t dist, bits1, bits2; 101 | bits1 = doubleToI64(f1) & (FLT_EXPOMASK | FLT_FRACMASK); 102 | bits2 = doubleToI64(f2) & (FLT_EXPOMASK | FLT_FRACMASK); 103 | if ((f1 > 0 && f2 < 0) || (f1 < 0 && f2 > 0)) { 104 | dist = bits1 + bits2; 105 | } 106 | else { 107 | if (bits1 > bits2) 108 | dist = bits1 - bits2; 109 | else 110 | dist = bits2 - bits1; 111 | } 112 | return dist; 113 | } 114 | 115 | uint64_t fpUtil::rand64() { 116 | // important to make the generator 'static' here. 117 | static std::mt19937_64 mt_generator_64(0xdeadbeef); 118 | return mt_generator_64(); 119 | } 120 | 121 | //mindis not included,maxdis included. 122 | double fpUtil::randNeighbor(double x,uint64_t mindis,uint64_t maxdis){ 123 | uint64_t tmp; 124 | uint64_t bits = 0; 125 | uint64_t sign = fpUtil::getDoubleSign(x); 126 | uint64_t expo = fpUtil::getDoubleExpo(x); 127 | uint64_t frac = fpUtil::getDoubleFrac(x); 128 | uint64_t newfrac; 129 | 130 | //buggy 131 | //uint64_t nlower = fmax(0,frac - maxdis); 132 | //uint64_t nupper = fmax(0,frac - mindis); 133 | 134 | uint64_t nlower = frac < maxdis ? 0 : frac-maxdis; 135 | uint64_t nupper = frac < mindis ? 0 : frac-mindis; 136 | 137 | uint64_t nrange = nupper-nlower; 138 | uint64_t plower = fmin(DBL_FRACMASK,frac + mindis); 139 | uint64_t pupper = fmin(DBL_FRACMASK,frac + maxdis); 140 | uint64_t prange = pupper - plower; 141 | assert(nrange+prange > 1); 142 | //use rand64(?) 143 | uint64_t r = rand64()%(nrange+prange); 144 | if(r frac)assert(newfrac-frac >= mindis && newfrac-frac <= maxdis); 149 | else assert(frac-newfrac >= mindis && frac-newfrac <= maxdis); 150 | return fpUtil::buildDouble(sign,expo,newfrac); 151 | } 152 | 153 | uint32_t fpUtil::rand32() { 154 | // important to make the generator 'static' here. 155 | static std::mt19937 mt_generator_32(0xdeadbeef); 156 | return mt_generator_32(); 157 | } 158 | 159 | double fpUtil::randDouble() { 160 | return i64ToDouble(rand64()); 161 | } 162 | 163 | float fpUtil::randFloat() { 164 | return i32ToFloat(rand32()); 165 | } 166 | 167 | double fpUtil::rand01() 168 | { 169 | return fabs(fpUtil::randDouble()/fpUtil::DBL_POSINF); 170 | } 171 | 172 | double fpUtil::revisedCondition(uint64_t opcode, double lhs, double rhs) { 173 | double cond1, cond2; 174 | double dzdist; 175 | switch(opcode) { 176 | case OP_ADD: 177 | dzdist = fabs(lhs+rhs); 178 | cond1 = fabs(lhs) / dzdist; 179 | cond2 = fabs(rhs) / dzdist; 180 | return cond1 + cond2 - dzdist; 181 | case OP_SUB: 182 | dzdist = fabs(lhs-rhs); 183 | cond1 = fabs(lhs) / dzdist; 184 | cond2 = fabs(rhs) / dzdist; 185 | return cond1 + cond2 - dzdist; 186 | case OP_SIN: 187 | // cond1 = fabs(lhs / tan(lhs)); 188 | // x \to n*pi, n \in Z. 189 | cond1 = 1 / fabs(remainder(lhs, fpUtil::PI)); 190 | return cond1; 191 | case OP_COS: 192 | // cond1 = fabs(lhs * tan(lhs)); 193 | // x \to n*pi + pi/2, n \in Z. 194 | cond1 = 1 / fabs(remainder((remainder(lhs, fpUtil::PI)-fpUtil::PI_2),fpUtil::PI)); 195 | return cond1; 196 | case OP_TAN: 197 | // cond1 = fabs(lhs / (sin(lhs) * cos(lhs))); 198 | // x \to n*pi/2, n \in Z. 199 | cond1 = 1 / fabs(remainder(lhs, fpUtil::PI_2)); 200 | return cond1; 201 | case OP_ASIN: 202 | cond1 = fabs(lhs / (sqrt(1-lhs*lhs) * asin(lhs))); 203 | return cond1; 204 | case OP_ACOS: 205 | cond1 = fabs(lhs / (sqrt(1-lhs*lhs) * acos(lhs))); 206 | return cond1; 207 | case OP_SINH: 208 | cond1 = fabs(lhs / tanh(lhs)); 209 | return cond1; 210 | case OP_COSH: 211 | cond1 = fabs(lhs * tanh(lhs)); 212 | return cond1; 213 | case OP_LOG: 214 | dzdist = fabs(lhs - 1); 215 | cond1 = fabs(1 / log(lhs)); 216 | return cond1 - dzdist; 217 | case OP_LOG10: 218 | dzdist = fabs(lhs - 1); 219 | cond1 = fabs(1 / log(lhs)); 220 | return cond1 - dzdist; 221 | case OP_POW: 222 | cond1 = fabs(rhs); 223 | cond2 = fabs(rhs * log(lhs)); 224 | return cond1 + cond2; 225 | default: 226 | return -DBL_MAX; 227 | } 228 | return -DBL_MAX; 229 | } 230 | 231 | double fpUtil::rawCondition(uint64_t opcode, double lhs, double rhs) { 232 | double cond1, cond2, dzdist; 233 | switch(opcode) { 234 | case OP_ADD: 235 | dzdist = fabs(lhs+rhs); 236 | cond1 = fabs(lhs) / dzdist; 237 | cond2 = fabs(rhs) / dzdist; 238 | return cond1 + cond2; 239 | case OP_SUB: 240 | dzdist = fabs(lhs-rhs); 241 | cond1 = fabs(lhs) / dzdist; 242 | cond2 = fabs(rhs) / dzdist; 243 | return cond1 + cond2; 244 | case OP_SIN: 245 | cond1 = fabs(lhs / tan(lhs)); 246 | return cond1; 247 | case OP_COS: 248 | cond1 = fabs(lhs * tan(lhs)); 249 | return cond1; 250 | case OP_TAN: 251 | cond1 = fabs(lhs / (sin(lhs) * cos(lhs))); 252 | return cond1; 253 | case OP_ASIN: 254 | cond1 = fabs(lhs / (sqrt(1-lhs*lhs) * asin(lhs))); 255 | return cond1; 256 | case OP_ACOS: 257 | cond1 = fabs(lhs / (sqrt(1-lhs*lhs) * acos(lhs))); 258 | return cond1; 259 | case OP_SINH: 260 | cond1 = fabs(lhs / tanh(lhs)); 261 | return cond1; 262 | case OP_COSH: 263 | cond1 = fabs(lhs * tanh(lhs)); 264 | return cond1; 265 | case OP_LOG: 266 | dzdist = fabs(lhs - 1); 267 | cond1 = fabs(1 / log(lhs)); 268 | return cond1; 269 | case OP_LOG10: 270 | dzdist = fabs(lhs - 1); 271 | cond1 = fabs(1 / log(lhs)); 272 | return cond1; 273 | case OP_POW: 274 | cond1 = fabs(rhs); 275 | cond2 = fabs(rhs * log(lhs)); 276 | return cond1 + cond2; 277 | default: 278 | return 1; 279 | } 280 | return 1; 281 | } 282 | 283 | double fpUtil::negInvRevisedCondition(uint64_t opcode, double lhs, double rhs){ 284 | return -1.0/(revisedCondition(opcode,lhs,rhs)); 285 | } -------------------------------------------------------------------------------- /src/fpUtil.h: -------------------------------------------------------------------------------- 1 | #ifndef FPUTIL_H 2 | #define FPUTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "opcode.h" 12 | 13 | namespace fpUtil { 14 | const uint64_t DBL_SIGNMASK = 0x8000000000000000uLL; 15 | const uint64_t DBL_EXPOMASK = 0x7FF0000000000000uLL; 16 | const uint64_t DBL_FRACMASK = 0x000FFFFFFFFFFFFFuLL; 17 | 18 | const uint64_t DBL_POSINF = 0x7FF0000000000000uLL; 19 | const uint64_t DBL_NEGINF = 0xFFF0000000000000uLL; 20 | const uint64_t DBL_NAN = 0x7FFFFFFFFFFFFFFFuLL; 21 | 22 | const uint32_t FLT_SIGNMASK = 0x80000000; 23 | const uint32_t FLT_EXPOMASK = 0x7F800000; 24 | const uint32_t FLT_FRACMASK = 0x007FFFFF; 25 | 26 | const uint32_t FLT_POSINF = 0x7F800000; 27 | const uint32_t FLT_NEGINF = 0xFF800000; 28 | const uint32_t FLT_NAN = 0x7FFFFFFF; 29 | 30 | const double PI = 3.14159265358979; 31 | const double PI_2 = 1.57079632679490; 32 | 33 | // Convert between floating point and bits. 34 | double i64ToDouble(uint64_t i); 35 | uint64_t doubleToI64(double d); 36 | 37 | float i32ToFloat(uint32_t i); 38 | uint32_t floatToI32(float f); 39 | 40 | // Get parts from floating point. 41 | uint64_t getDoubleSign(double d); 42 | uint64_t getDoubleExpo(double d); 43 | uint64_t getDoubleFrac(double d); 44 | 45 | uint32_t getFloatSign(float f); 46 | uint32_t getFloatExpo(float f); 47 | uint32_t getFloatFrac(float f); 48 | 49 | // Build floating point from parts. 50 | double buildDouble(uint64_t sign, uint64_t expo, uint64_t frac); 51 | 52 | float buildFloat(uint32_t sign, uint32_t expo, uint32_t frac); 53 | 54 | // ULP value. 55 | double doubleULP(double d); 56 | float floatULP(float f); 57 | 58 | // POPL19 Dist value. 59 | uint64_t doubleDist(double d1, double d2); 60 | uint32_t floatDist(float f1, float f2); 61 | 62 | // Random functions. 63 | uint64_t rand64(); 64 | double randNeighbor(double x, uint64_t mindis,uint64_t maxdis); 65 | double randDouble(); 66 | 67 | uint32_t rand32(); 68 | float randFloat(); 69 | 70 | double rand01(); 71 | 72 | // ConditionNumber 73 | double revisedCondition(uint64_t opcode, double lhs, double rhs); 74 | double negInvRevisedCondition(uint64_t opcode, double lhs, double rhs); 75 | double rawCondition(uint64_t opcode, double lhs, double rhs); 76 | }; 77 | #endif 78 | -------------------------------------------------------------------------------- /src/gslSolver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "fpUtil.h" 21 | #include "fpInterface.h" 22 | 23 | class InputFitnessPair { 24 | public: 25 | double input; 26 | double fitness; 27 | 28 | InputFitnessPair() { 29 | input = 0; 30 | fitness = -std::numeric_limits::max(); 31 | } 32 | InputFitnessPair(double in, double fit) { 33 | input = in; 34 | fitness = fit; 35 | } 36 | bool operator < (const InputFitnessPair &rhs) const { 37 | return fitness < rhs.fitness; 38 | } 39 | bool operator > (const InputFitnessPair &rhs) const { 40 | return fitness > rhs.fitness; 41 | } 42 | }; 43 | class InputFitnessPairGreater { 44 | public: 45 | bool operator () (const InputFitnessPair& lhs, const InputFitnessPair& rhs) const { 46 | return lhs.fitness > rhs.fitness; 47 | } 48 | }pairGreater; 49 | class InputFitnessPairLess { 50 | public: 51 | bool operator () (const InputFitnessPair& lhs, const InputFitnessPair& rhs) const { 52 | return lhs.fitness < rhs.fitness; 53 | } 54 | }pairLess; 55 | 56 | class InstructionInfo { 57 | private: 58 | uint64_t instID; 59 | uint64_t opcode; 60 | uint32_t recordSize = 100; 61 | std::vector topInputsRandom; 62 | std::vector topInputsEvolution; 63 | // For recording prioritization results. 64 | uint32_t topInputCountToEnd; 65 | double topInputConditionToEnd; 66 | 67 | private: 68 | void pushHeap(double input, double fitness) { 69 | topInputsRandom.push_back(InputFitnessPair(input, fitness)); 70 | std::push_heap(topInputsRandom.begin(), topInputsRandom.end(), pairGreater); 71 | } 72 | void popHeap() { 73 | std::pop_heap(topInputsRandom.begin(), topInputsRandom.end(), pairGreater); 74 | topInputsRandom.pop_back(); 75 | } 76 | InputFitnessPair topHeap() { 77 | return topInputsRandom[0]; 78 | } 79 | public: 80 | InstructionInfo() { 81 | instID = 0; 82 | opcode = 0; 83 | } 84 | InstructionInfo(uint64_t id, uint64_t op) { 85 | instID = id; 86 | opcode = op; 87 | } 88 | uint64_t getInstID() const { return instID; } 89 | uint64_t getOpCode() const { return opcode; } 90 | uint32_t getRecordSize() const { return recordSize; } 91 | void setRecordSize(uint32_t k) { recordSize = k; } 92 | 93 | std::vector getInputsRandom() const { return topInputsRandom; } 94 | std::vector getInputsEvolution() const { return topInputsEvolution; } 95 | int getInputsRandomSize() const { return topInputsRandom.size(); } 96 | int getInputsEvolutionSize() const { return topInputsEvolution.size(); } 97 | void setInputsEvolution(std::vector l) { topInputsEvolution = l; } 98 | InputFitnessPair getInputsEvolutionTop() const { return topInputsEvolution[0]; } 99 | 100 | void setTopInputCountToEnd(uint32_t c) { topInputCountToEnd = c; } 101 | void setTopInputConditionToEnd(double d) { topInputConditionToEnd = d; } 102 | uint32_t getTopInputCountToEnd() const { return topInputCountToEnd; } 103 | double getTopInputConditionToEnd() const { return topInputConditionToEnd; } 104 | 105 | void pushInputFitness(double input, double fitness) { 106 | if (!std::isfinite(fitness)) 107 | return; 108 | if (topInputsRandom.size() < recordSize) 109 | { 110 | pushHeap(input, fitness); 111 | return; 112 | } 113 | if (fitness > topHeap().fitness) 114 | { 115 | popHeap(); 116 | pushHeap(input, fitness); 117 | } 118 | } 119 | 120 | void printRandomInfo(std::unique_ptr & funcPtr) { 121 | std::sort(topInputsRandom.begin(), topInputsRandom.end(), pairGreater); 122 | 123 | std::cout << "************************************************\n"; 124 | std::cout << "Instruction ID: " << instID << '\n'; 125 | std::cout << "Instruction OP: " << opcode << '\n'; 126 | std::cout.precision(5); 127 | uint32_t inputSize = topInputsRandom.size(); 128 | std::cout << "Valid inputs in our records: " << topInputsRandom.size() << '\n'; 129 | std::cout << "Largest fitness after random: " << std::scientific << topInputsRandom[0].fitness << '\n'; 130 | std::cout << "50th fitness after random: " << std::scientific << topInputsRandom[inputSize/2].fitness << '\n'; 131 | std::cout.precision(16); 132 | std::cout << " Largest's input: " << std::setw(25) << std::scientific << topInputsRandom[0].input << '\n'; 133 | std::cout << " Largest's output: " << std::setw(25) << std::scientific << funcPtr->callAndGetResult(topInputsRandom[0].input) << '\n'; 134 | 135 | std::make_heap(topInputsRandom.begin(), topInputsRandom.end(), pairGreater); 136 | } 137 | void printEvolutionInfo(std::unique_ptr & funcPtr) { 138 | std::cout << "------------------\n"; 139 | std::cout << "Instruction ID: " << instID << '\n'; 140 | std::cout << "Instruction OP: " << opcode << '\n'; 141 | std::cout.precision(5); 142 | uint32_t inputSize = topInputsEvolution.size(); 143 | std::cout << "Valid inputs in our records: " << topInputsEvolution.size() << '\n'; 144 | std::cout << "Largest fitness after evo: " << std::scientific << topInputsEvolution[0].fitness << '\n'; 145 | std::cout << "50th fitness after evo: " << std::scientific << topInputsEvolution[inputSize/2].fitness << '\n'; 146 | std::cout.precision(16); 147 | std::cout << " Largest's input: " << std::setw(25) << std::scientific << topInputsEvolution[0].input << '\n'; 148 | std::cout << " Largest's output: " << std::setw(25) << std::scientific << funcPtr->callAndGetResult(topInputsEvolution[0].input) << '\n'; 149 | } 150 | 151 | void printBriefInfo(int funcIndex) { 152 | std::cout << "2. Searching on Operations.\nFunction Index: " << funcIndex << ", "; 153 | std::cout << "Analyzing Operation: " << instID << ", OPCode: " << opcode << '\n'; 154 | std::cout << " Largest's input: " << std::setw(15) << std::scientific << topInputsEvolution[0].input << ", "; 155 | std::cout << " Fitness: " << std::scientific << topInputsEvolution[0].fitness << '\n'; 156 | } 157 | }; 158 | 159 | class EvoSolver { 160 | private: 161 | std::unique_ptr funcUnderTest; 162 | std::map instMap; 163 | uint32_t unstableInstCount = 0; 164 | int32_t GSLFuncIndex; 165 | // For record execution time. 166 | std::chrono::high_resolution_clock::time_point startTime; 167 | std::chrono::high_resolution_clock::time_point finishTime; 168 | std::chrono::duration elapsedTime; 169 | 170 | // Params: 171 | // For _1RandomSearch 172 | double initExpRange = 20; 173 | double initCenterRate = 0.15; 174 | uint32_t randomIteration = 100000; 175 | // For _2EvolutionSearch 176 | double evoGeometricP = 0.25; 177 | double evoNormalFactorStart = 1e-2; 178 | double evoNormalFactorEnd = 1e-13; 179 | uint32_t evoIterations = 100; 180 | uint32_t evoPerIterationSize = 100; 181 | 182 | std::mt19937 mtGenerator; 183 | std::uniform_real_distribution uni01; 184 | 185 | std::string outPath = "tempOutput.out"; 186 | 187 | public: 188 | EvoSolver() : 189 | mtGenerator(0xdeadbeef), 190 | uni01(0.0, 1.0) 191 | { 192 | // Clean File. 193 | std::ofstream myfile; 194 | myfile.open(outPath, std::ofstream::out); 195 | myfile.close(); 196 | } 197 | 198 | void run(std::unique_ptr & funcPtr, int index) { 199 | startTime = std::chrono::high_resolution_clock::now(); 200 | _init(funcPtr, index); 201 | _1RandomSearch(); 202 | _2EvolutionSearch(); 203 | _3Prioritize(); 204 | finishTime = std::chrono::high_resolution_clock::now(); 205 | elapsedTime = finishTime - startTime; 206 | 207 | _writeToFile(); 208 | _printInfo(); 209 | } 210 | 211 | void setRandomIteration(uint32_t iter) { randomIteration = iter; } 212 | void setEvoIteration(uint32_t iter) {evoIterations = iter; } 213 | 214 | private: 215 | void _init(std::unique_ptr & funcPtr, int index) { 216 | GSLFuncIndex = index; 217 | funcUnderTest = std::move(funcPtr); 218 | 219 | // Clear member values 220 | unstableInstCount = 0; 221 | // Fast clear instMap. 222 | std::map emptyMap; 223 | std::swap(emptyMap, instMap); 224 | std::cout << "Current Analyzing Function Index: " << index << std::endl; 225 | } 226 | 227 | double _initDist() { 228 | double x = fpUtil::randDouble(); 229 | double p01 = uni01(mtGenerator); 230 | if (p01 < initCenterRate) { 231 | p01 = uni01(mtGenerator); 232 | uint64_t xsign = fpUtil::getDoubleSign(x); 233 | uint64_t xexpo = 1023 + (uint64_t)(initExpRange*2*p01-initExpRange); 234 | uint64_t xfrac = fpUtil::getDoubleFrac(x); 235 | x = fpUtil::buildDouble(xsign, xexpo, xfrac); 236 | } 237 | return x; 238 | } 239 | 240 | // The results stored in instMap. 241 | void _1RandomSearch() { 242 | double x, y; 243 | 244 | for (int i = 1; i <= randomIteration; i++) { 245 | x = _initDist(); 246 | funcUnderTest->call(x); 247 | 248 | // print the progress. 249 | if (i % (randomIteration/100) == 0) 250 | std::cout << "1. Random Search Processing: " << i / (randomIteration/100) << "%, " << i << "..." << "\r" << std::flush; 251 | 252 | // Only log when the execution is success. 253 | if (!funcUnderTest->isSuccess()) 254 | continue; 255 | y = funcUnderTest->getResult(); 256 | 257 | std::vector infoList = funcUnderTest->getInstInfoList(); 258 | for (const auto &info : infoList) { 259 | if (instMap.count(info.instID) == 0) { 260 | instMap[info.instID] = InstructionInfo(info.instID, info.opcode); 261 | } 262 | 263 | double fit = fpUtil::revisedCondition(info.opcode, info.op1, info.op2); 264 | 265 | InstructionInfo &curInst = instMap[info.instID]; 266 | curInst.pushInputFitness(x, fit); 267 | } 268 | } 269 | std::cout << "\n1. Random Search Done.\n"; 270 | } 271 | 272 | // The results stored in instMap. 273 | void _2EvolutionSearch() { 274 | std::geometric_distribution geometricDist(evoGeometricP); 275 | std::normal_distribution normalDist(0, 1); 276 | 277 | double x, y; 278 | 279 | for (auto &kv : instMap) { 280 | uint64_t instid = kv.first; 281 | InstructionInfo & curInst = kv.second; 282 | 283 | if (curInst.getInputsRandomSize() == 0) 284 | continue; 285 | 286 | std::vector inputList = curInst.getInputsRandom(); 287 | // Sort the inputList, with the largest fitness first. 288 | std::sort(inputList.begin(), inputList.end(), pairGreater); 289 | 290 | // Filter the actual stable "suspicious" inst. 291 | double largestFitness = inputList[0].fitness; 292 | if (largestFitness < 1e1) 293 | continue; 294 | 295 | unstableInstCount++; 296 | 297 | // Print the info before evolution search. 298 | // curInst.printRandomInfo(funcUnderTest); 299 | 300 | // Generates new inputs based on current input list. 301 | for (int i = 0; i < evoIterations; i++) { 302 | double evoNormalFactor = exp(log(evoNormalFactorStart) + 303 | ((double)i / evoIterations) * log(evoNormalFactorEnd / evoNormalFactorStart)); 304 | for (int j = 0; j < evoPerIterationSize; j++) { 305 | // 2.1 select. 306 | int seletedIndex; 307 | // make sure the index is smaller than input list size. 308 | while ((seletedIndex = geometricDist(mtGenerator)) >= inputList.size()); 309 | double curInput = inputList[seletedIndex].input; 310 | 311 | // 2.2 mutation. 312 | double mutation = evoNormalFactor * fabs(curInput) * normalDist(mtGenerator); 313 | double newInput = curInput + mutation; 314 | if (!std::isfinite(newInput)) 315 | continue; 316 | 317 | // 2.3 run with the new input. 318 | funcUnderTest->call(newInput); 319 | if (!funcUnderTest->isSuccess()) 320 | continue; 321 | y = funcUnderTest->getResult(); 322 | 323 | std::vector infoList = funcUnderTest->getInstInfoList(); 324 | for (const auto &info : infoList) { 325 | // We only care about the current instruction. 326 | if (info.instID != curInst.getInstID()) 327 | continue; 328 | double newFit = fpUtil::revisedCondition(info.opcode, info.op1, info.op2); 329 | if (!std::isfinite(newFit)) 330 | continue; 331 | inputList.push_back(InputFitnessPair(newInput, newFit)); 332 | } 333 | } 334 | // After each iteration, only reserve the top 100 inputs. 335 | std::sort(inputList.begin(), inputList.end(), pairGreater); 336 | inputList.resize(curInst.getRecordSize()); 337 | } 338 | // After all iterations, store the inputList into curInst. 339 | curInst.setInputsEvolution(inputList); 340 | 341 | // curInst.printEvolutionInfo(funcUnderTest); 342 | curInst.printBriefInfo(GSLFuncIndex); 343 | } 344 | } 345 | 346 | // The results stored in prioritizedInput. 347 | void _3Prioritize() { 348 | 349 | double x, y; 350 | int status; 351 | gsl_sf_result res; 352 | 353 | std::vector inputsWithCountToEnd; 354 | std::map io; 355 | // The prior score of an input is calculated from 356 | // the correspounding instruction to end. 357 | for (auto &kv : instMap) { 358 | uint64_t instid = kv.first; 359 | InstructionInfo & curInst = kv.second; 360 | 361 | if (curInst.getInputsEvolutionSize() == 0) 362 | continue; 363 | 364 | double curInput = curInst.getInputsEvolutionTop().input; 365 | double curFit = curInst.getInputsEvolutionTop().fitness; 366 | 367 | funcUnderTest->call(curInput); 368 | y = funcUnderTest->getResult(); 369 | 370 | bool started = false; 371 | double logConditionToEnd = 0; 372 | uint32_t countToEnd = 0; 373 | std::vector infoList = funcUnderTest->getInstInfoList(); 374 | for (const auto &info : infoList) { 375 | // we need to find the curInput running to the curInst with the curFit. 376 | // Considering a inst maybe executed multiple times. 377 | if (started == false && info.instID == instid) { 378 | double tmpFit = fpUtil::revisedCondition(info.opcode, info.op1, info.op2); 379 | if (tmpFit == curFit) { 380 | started = true; 381 | } 382 | } 383 | if (started == true) { 384 | double rawCond = fpUtil::rawCondition(info.opcode, info.op1, info.op2); 385 | // std::cout << "Raw Cond: " << rawCond; 386 | // std::cout << ' ' << info.op1 << ' ' << info.op2 << ' ' << info.opcode << "\n"; 387 | // Condition 388 | if ( instMap.count(info.instID) != 0 && std::isfinite(rawCond) ) { 389 | logConditionToEnd += log(rawCond); 390 | } 391 | // Count 392 | if ( instMap.count(info.instID) != 0) { 393 | countToEnd += 1; 394 | } 395 | } 396 | } 397 | curInst.setTopInputCountToEnd(countToEnd); 398 | curInst.setTopInputConditionToEnd(logConditionToEnd); 399 | 400 | inputsWithCountToEnd.push_back(InputFitnessPair(curInput, countToEnd)); 401 | io[curInput] = y; 402 | // std::cout << curInst.getInputsRandomSize() << ' ' << curInst.getInputsEvolutionSize() << '\n'; 403 | } 404 | // Prioritize based on condition to end. 405 | sort(inputsWithCountToEnd.begin(), inputsWithCountToEnd.end()); 406 | 407 | std::cout << "***********Results after Prioritize***********\n"; 408 | std::cout << "Most suspicious input first: \n"; 409 | for (auto & i : inputsWithCountToEnd) { 410 | std::cout << std::setprecision(16) << std::scientific << i.input << "\t\t"; 411 | std::cout << "Output: " << io[i.input] << '\n'; 412 | } 413 | std::cout << "End of suspicious input list.\n"; 414 | } 415 | 416 | // The evolution search info. 417 | void _printInfo() { 418 | std::cout << "************************************************\n"; 419 | std::cout << "Actual Unstable Instructions Size: " << unstableInstCount << '\n'; 420 | std::cout << "Potential Unstable Instructions Size: " << instMap.size() << '\n'; 421 | std::cout.unsetf(std::ios_base::floatfield); 422 | std::cout << "Execution Time: " << elapsedTime.count() << " sec.\n"; 423 | std::cout << "************************************************\n"; 424 | } 425 | 426 | void _writeToFile() { 427 | std::ofstream myfile; 428 | myfile.open(outPath, std::ofstream::out | std::ofstream::app); 429 | // Write Timestamp. 430 | std::time_t stamp = time(NULL); 431 | myfile << "---------------------------------------\n"; 432 | myfile << "Time: " << std::ctime(&stamp) << '\n'; 433 | // Write Function Index. 434 | myfile << "Function Index: " << GSLFuncIndex << '\n'; 435 | myfile << "Actual Unstable Instructions Size: " << unstableInstCount << '\n'; 436 | myfile << "Potential Unstable Instructions Size: " << instMap.size() << '\n'; 437 | myfile << "Execution Time: " << elapsedTime.count() << " sec.\n"; 438 | myfile << "Format: InstID, OpCode, MaxAtomCond, Input, Output, CountToEnd, ConditionToEnd\n"; 439 | // Write Computation Results. 440 | for (const auto &kv : instMap) { 441 | uint64_t instid = kv.first; 442 | const InstructionInfo & curInst = kv.second; 443 | 444 | if (curInst.getInputsEvolutionSize() == 0) 445 | continue; 446 | InputFitnessPair pair = curInst.getInputsEvolutionTop(); 447 | myfile << "Data: "; 448 | myfile << curInst.getInstID() << ", "; 449 | myfile << curInst.getOpCode() << ", "; 450 | myfile << std::setprecision(5) << std::scientific << pair.fitness << ", "; 451 | myfile << std::setprecision(16) << std::scientific << pair.input << ", "; 452 | myfile << std::setprecision(16) << std::scientific << funcUnderTest->callAndGetResult(pair.input) << ", "; 453 | myfile << curInst.getTopInputCountToEnd() << ", "; 454 | myfile << curInst.getTopInputConditionToEnd() << "\n"; 455 | } 456 | myfile << "***************************************\n"; 457 | myfile.close(); 458 | } 459 | }; 460 | 461 | int main(int argc, char *argv[]) { 462 | // // Init communicator. 463 | // Communicator &comm = Communicator::getInstance(); 464 | 465 | EvoSolver es; 466 | std::unique_ptr funcPtr; 467 | 468 | if (argc == 1 || (argc > 1 && strcmp(argv[1], "example") == 0)) { 469 | int index = 0; 470 | if (argc > 2) 471 | index = atoi(argv[2]); 472 | if (index >= simpleFuncList.size()) { 473 | std::cout << "Invalid index in simpleFuncList\n"; 474 | return 0; 475 | } 476 | funcPtr.reset(new SimpleFunction(index)); 477 | es.run(funcPtr, index); 478 | } 479 | else if (argc > 2 && strcmp(argv[1], "gsl") == 0) { 480 | if (!strcmp(argv[2],"all")) { 481 | for (int i = 0; i < GSLFuncList.size(); i++) { 482 | funcPtr.reset(new GSLFunction(i)); 483 | es.run(funcPtr, i); 484 | } 485 | } 486 | else { 487 | int index = atoi(argv[2]); 488 | if (index >= GSLFuncList.size()) { 489 | std::cout << "Invalid index in GSLFuncList.\n"; 490 | return 0; 491 | } 492 | funcPtr.reset(new GSLFunction(index)); 493 | es.run(funcPtr, index); 494 | } 495 | } 496 | else { 497 | std::cout << "Invalid argument." << std::endl; 498 | std::cout << "Valid Example: \n\tbin/gslSolver.out gsl 73\n\tor\n\tbin/gslSolver.out example\n"; 499 | } 500 | 501 | return 0; 502 | } 503 | -------------------------------------------------------------------------------- /src/handlers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "communicator.h" 5 | 6 | extern "C" bool fCmpInstHandler(double, double, bool, int32_t, 7 | char*, char*, uint64_t, int32_t, int32_t); 8 | extern "C" bool iCmpInstHandler(uint64_t, uint64_t, bool, int32_t, 9 | char*, char*, uint64_t, int32_t, int32_t); 10 | extern "C" void fAddHandler(double, double, char*, char*, uint64_t, int32_t, int32_t); 11 | extern "C" void fSubHandler(double, double, char*, char*, uint64_t, int32_t, int32_t); 12 | extern "C" void fMulHandler(double, double, char*, char*, uint64_t, int32_t, int32_t); 13 | extern "C" void fDivHandler(double, double, char*, char*, uint64_t, int32_t, int32_t); 14 | extern "C" void callOneArgHandler(int32_t, double, char*, char*, uint64_t, int32_t, int32_t); 15 | extern "C" void callTwoArgsHandler(int32_t, double, double, char*, char*, uint64_t, int32_t, int32_t); 16 | 17 | bool fCmpInstHandler( 18 | double a, 19 | double b, 20 | bool origin_res, 21 | int32_t predicate, 22 | char* funcName, 23 | char* modName, 24 | uint64_t instID, 25 | int32_t debugLine, 26 | int32_t debugCol) 27 | { 28 | return origin_res; 29 | } 30 | 31 | bool iCmpInstHandler( 32 | uint64_t a, 33 | uint64_t b, 34 | bool origin_res, 35 | int32_t predicate, 36 | char* funcName, 37 | char* modName, 38 | uint64_t instID, 39 | int32_t debugLine, 40 | int32_t debugCol) 41 | { 42 | return origin_res; 43 | } 44 | 45 | void fAddHandler( 46 | double a, 47 | double b, 48 | char* funcName, 49 | char* modName, 50 | uint64_t instID, 51 | int32_t debugLine, 52 | int32_t debugCol) 53 | { 54 | Communicator &comm = Communicator::getInstance(); 55 | comm.writeInstInfo(OP_ADD, a, b, instID); 56 | } 57 | 58 | void fSubHandler( 59 | double a, 60 | double b, 61 | char* funcName, 62 | char* modName, 63 | uint64_t instID, 64 | int32_t debugLine, 65 | int32_t debugCol) 66 | { 67 | Communicator &comm = Communicator::getInstance(); 68 | comm.writeInstInfo(OP_SUB, a, b, instID); 69 | } 70 | 71 | void fMulHandler( 72 | double a, 73 | double b, 74 | char* funcName, 75 | char* modName, 76 | uint64_t instID, 77 | int32_t debugLine, 78 | int32_t debugCol) 79 | { 80 | Communicator &comm = Communicator::getInstance(); 81 | comm.writeInstInfo(OP_MUL, a, b, instID); 82 | } 83 | 84 | void fDivHandler( 85 | double a, 86 | double b, 87 | char* funcName, 88 | char* modName, 89 | uint64_t instID, 90 | int32_t debugLine, 91 | int32_t debugCol) 92 | { 93 | Communicator &comm = Communicator::getInstance(); 94 | comm.writeInstInfo(OP_DIV, a, b, instID); 95 | } 96 | 97 | void callOneArgHandler( 98 | int32_t functionID, 99 | double a, 100 | char* funcName, 101 | char* modName, 102 | uint64_t instID, 103 | int32_t debugLine, 104 | int32_t debugCol) 105 | { 106 | Communicator &comm = Communicator::getInstance(); 107 | comm.writeInstInfo(functionID, a, a, instID); 108 | } 109 | 110 | void callTwoArgsHandler( 111 | int32_t functionID, 112 | double a, 113 | double b, 114 | char* funcName, 115 | char* modName, 116 | uint64_t instID, 117 | int32_t debugLine, 118 | int32_t debugCol) 119 | { 120 | Communicator &comm = Communicator::getInstance(); 121 | comm.writeInstInfo(functionID, a, b, instID); 122 | } 123 | -------------------------------------------------------------------------------- /src/opcode.h: -------------------------------------------------------------------------------- 1 | #ifndef OPCODE_H 2 | #define OPCODE_H 3 | 4 | // Definition of OPCODE 5 | #define OPSIZE 25 6 | 7 | #define OP_ADD 20 8 | #define OP_SUB 21 9 | #define OP_MUL 22 10 | #define OP_DIV 23 11 | 12 | #define OP_SIN 1 13 | #define OP_COS 2 14 | #define OP_TAN 3 15 | #define OP_ASIN 4 16 | #define OP_ACOS 5 17 | #define OP_ATAN 6 18 | #define OP_ATAN2 7 19 | #define OP_SINH 8 20 | #define OP_COSH 9 21 | #define OP_TANH 10 22 | #define OP_EXP 11 23 | #define OP_LOG 12 24 | #define OP_LOG10 13 25 | #define OP_SQRT 14 26 | #define OP_POW 15 27 | 28 | #endif -------------------------------------------------------------------------------- /src/target.h: -------------------------------------------------------------------------------- 1 | // targetExample.c 2 | 3 | extern "C" double foo(double); 4 | -------------------------------------------------------------------------------- /src/targetExample.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double foo(double x) { 4 | // This function calculate the motivation example: 5 | // y = (1-cos(x))/(x^2) 6 | // See details at: https://www.wolframalpha.com/input/?i=(1-cos(x))%2F(x%5E2) 7 | 8 | // It triggers significant error when x->0, where y should be ->0.5. 9 | double val = (1-cos(x))/(x*x); 10 | return val; 11 | } 12 | 13 | --------------------------------------------------------------------------------