├── LICENSE ├── README.md ├── case_studies ├── cordic │ └── cordic_sin │ │ ├── Makefile │ │ └── cordic_sin.c └── simpson │ ├── Makefile │ ├── SimpsonsRule.c │ └── mathFunc.txt ├── fpsan_pass ├── CMakeLists.txt └── FPSan │ ├── CMakeLists.txt │ ├── FPSanitizer.cpp │ └── FPSanitizer.h ├── fpsan_runtime ├── Makefile ├── handleReal.cpp └── handleReal.h └── fpsanitizer_test ├── correctness_test.py ├── correctness_test_expected ├── ContinuedFraction1 │ └── error.log ├── MindlessG │ └── error.log ├── ParallelResistance │ └── error.log ├── SimpsonsRule │ └── error.log ├── SinTaylorExpansion │ └── error.log ├── cc │ └── error.log ├── compare-zero-self │ └── error.log ├── cordic_cos │ └── error.log ├── cordic_sin │ └── error.log ├── diff-roots-simple │ └── error.log ├── diff-roots │ └── error.log ├── diff-simple │ └── error.log ├── dotproduct1 │ └── error.log ├── dotproduct2 │ └── error.log ├── exact-ranges │ └── error.log ├── gromacs-bondfree-580 │ └── error.log ├── gsl-modpi │ └── error.log ├── indirect │ └── error.log ├── mini │ └── error.log ├── multi-args │ └── error.log ├── naturalnumber │ └── error.log ├── newtonraphson │ └── error.log ├── newtonraphsonsqrt │ └── error.log ├── onthefly │ └── error.log ├── redir │ └── error.log ├── rootfinding1 │ └── error.log ├── rootfinding2 │ └── error.log ├── same-small │ └── error.log ├── simpl-swallow-testa │ └── error.log ├── simpl-swallow-testb │ └── error.log ├── simpl-swallow-testc │ └── error.log ├── simpl-swallow-testd │ └── error.log ├── simple-negate │ └── error.log ├── small │ └── error.log ├── some-trig │ └── error.log ├── sqrtf │ └── error.log ├── sum-50 │ └── error.log ├── sum-500 │ └── error.log ├── tiny │ └── error.log ├── var-test-2 │ └── error.log └── var-test │ └── error.log ├── makefiles ├── Makefile └── mathFunc.txt └── src ├── ContinuedFraction1.c ├── MindlessG.c ├── ParallelResistance.c ├── SimpsonsRule.c ├── SinTaylorExpansion.c ├── cc.c ├── compare-zero-self.c ├── cordic_cos.c ├── cordic_sin.c ├── diff-roots-simple.c ├── diff-roots.c ├── diff-simple.c ├── dotproduct1.c ├── dotproduct2.c ├── exact-ranges.c ├── functions.txt ├── gromacs-bondfree-580.c ├── gsl-modpi.c ├── indirect.c ├── indirect1.c ├── mini.c ├── multi-args.c ├── naturalnumber.c ├── newtonraphson.c ├── newtonraphsonsqrt.c ├── onthefly.c ├── redir.c ├── rootfinding1.c ├── rootfinding2.c ├── same-small.c ├── simpl-swallow-testa.c ├── simpl-swallow-testb.c ├── simpl-swallow-testc.c ├── simpl-swallow-testd.c ├── simple-negate.c ├── small.c ├── some-trig.c ├── sqrtf.c ├── sum-50.c ├── sum-500.c ├── tiny.c ├── var-test-2.c └── var-test.c /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Sangeeta Chowdhary, Jay Lim, and Santosh Nagarakatte 2 | Rutgers, The State University of New Jersey 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FPSanitizer - A debugger to detect and diagnose numerical errors in floating point programs 2 | ====== 3 | 4 | Building LLVM 5 | ------ 6 | 7 | 1. Get llvm and clang version 9 8 | 9 | ``` 10 | wget http://releases.llvm.org/9.0.0/llvm-9.0.0.src.tar.xz 11 | wget http://releases.llvm.org/9.0.0/cfe-9.0.0.src.tar.xz 12 | ``` 13 | 14 | 2. Build llvm and clang 15 | 16 | ``` 17 | tar -xvf llvm-9.0.0.src.tar.xz 18 | mv llvm-9.0.0.src/ llvm 19 | tar -xvf cfe-9.0.0.src.tar.xz 20 | mv cfe-9.0.0.src clang 21 | mkdir build 22 | cd build 23 | cmake -DLLVM_ENABLE_PROJECTS=clang -G "Unix Makefiles" ../llvm 24 | make -j8 25 | 26 | ``` 27 | 28 | 3. Set env variable LLVM_HOME to the LLVM build directory 29 | ``` 30 | export LLVM_HOME= 31 | ``` 32 | 33 | Building FPSanitizer 34 | ------ 35 | 36 | 1. Clone fpsan git repo. 37 | ``` 38 | git clone https://github.com/rutgers-apl/fpsanitizer.git 39 | 40 | ``` 41 | 42 | 2. Set the environment variable FPSAN_HOME 43 | 44 | ``` 45 | export FPSAN_HOME= 46 | 47 | ``` 48 | 49 | 50 | 3. If your compiler does not support C++11 by default, add the following line to $FPSAN_HOME/fpsan-pass/FPSan/CMakefile 51 | 52 | ``` 53 | target_compile_feature(FPSanitizer PRIVATE cxx_range_for cxx_auto_type) 54 | 55 | ``` 56 | 57 | otherwise, use the followng line 58 | 59 | ``` 60 | target_compile_features(FPSanitizer PRIVATE ) 61 | 62 | ``` 63 | 64 | 3. Build the FPSan pass 65 | 66 | ``` 67 | cd $FPSAN_HOME/fpsan_pass 68 | mkdir build 69 | cd build 70 | cmake -DCMAKE_BUILD_TYPE="Debug" ../ 71 | make 72 | 73 | ``` 74 | 75 | 76 | 4. Build the FPSan runtime 77 | 78 | ``` 79 | cd $FPSAN_HOME/fpsan_runtime 80 | export SET_TRACING=TRACING 81 | make 82 | 83 | ``` 84 | 85 | 86 | Testing microbenchmarks using fpsanitizer: 87 | ------ 88 | 89 | One can test the microbenchmarks using 90 | fpsanitizer with the following commands: 91 | 92 | ``` 93 | export LD_LIBRARY_PATH=$FPSAN_HOME/fpsan_runtime/obj:$LD_LIBRARY_PATH 94 | cd fpsanitizer_test/ 95 | python3 correctness_test.py 96 | ``` 97 | 98 | 99 | This process should take less than 4 minutes. During the execution, 100 | the script runs each microbenchmark and reports whether the 101 | microbenchmark has (a) NaN computation, (b)catastrophic cancellation, 102 | (c) infinity computation, or (d) branch flip. The script also outputs 103 | whether this error is correctly found (expected with green letters) or 104 | incorrectly found (unexpected with red letters). The script should 105 | only report "expected" and not "unexpected." 106 | 107 | Finally, when the script terminates, it reports the total number of 108 | microbenchmarks, the total number of microbenchmarks that reports each 109 | type of error, and whether the numbers are correct or not. 110 | 111 | ------ 112 | Running case studies using fpsanitizer: 113 | ------ 114 | ``` 115 | $ cd case_studies/cordic/cordic_sin 116 | $ gdb cordic_sin.fp.o 117 | ``` 118 | Now our goal is to find a computation of the variable "y" 119 | which has more than or equal to 45 bits of error. Place a 120 | conditional breakpoint which looks for any floating point operation 121 | resulting in the error of 45 bits or more. Since 122 | handleReal.cpp is a part of the shared library, type "y" 123 | when prompted, and run the program: 124 | 125 | ``` 126 | (gdb) break handleReal.cpp:180 if realRes->error >= 45 127 | (gdb) y 128 | (gdb) run 129 | ``` 130 | Skip the first eight break. This instance computes the value for 131 | the variable "z." 132 | ``` 133 | (gdb) continue 134 | ``` 135 | Now, call the function "fpsan_trace" which prints the trace of 136 | expressions leading up to the computed value: 137 | ``` 138 | (gdb) call fpsan_trace(realRes) 139 | ``` 140 | You should be able to see a trace of 8 operations. For each 141 | line, the first value tells you the line number of the computation. The 142 | second value tells you which operations are executed, the 143 | third value shows the line number for first operand, 144 | and the fourth value shows the line number for the 145 | second operand. The result of reals (mpfr) computation, the 146 | result of floating point computation, and the number of bits in error 147 | is shown in parenthesis. 148 | 149 | You will notice that the first line of trace for an add operation 150 | incurs 45 bits of error. You should also be able to track 151 | the operands by looking at the line number of the operands and 152 | finding the corresponding trace. 153 | 154 | Now our goal is to detect the first instance of branch 155 | flip. First, remove the exisiting breakpoint and add a 156 | breakpoint that detects where branch flip occurs: 157 | 158 | ``` 159 | (gdb) clear 160 | (gdb) break handleReal.cpp:143 if(realRes != computedRes) 161 | (gdb) continue 162 | ``` 163 | At this point, the floating point result of "op1" causes a branch 164 | flip. You can look at the trace of "op1" by calling 165 | "fpsan_trace": 166 | 167 | ``` 168 | (gdb) call fpsan_trace(op1) 169 | ``` 170 | You should see a trace of 4 instructions. You will notice that 171 | the first line of the trace for a subtraction operation 172 | (FSUB) shows that fp computed a negative value whereas 173 | mpfr computed a positive value. The prorgram at this point 174 | compares op1 < 0. This means that fp computation will 175 | incorrectly evaluate op1 < 0. 176 | 177 | 178 | (4.2) Simpson's Rule (Section 5.2.2) 179 | 180 | The source code for simpson's rule can be found in the case 181 | studies directory. 182 | ``` 183 | $ cd case_studies/simpson 184 | ``` 185 | Compile the program, 186 | ``` 187 | $ make 188 | ``` 189 | Run the program simpsons.fp.o. It will take roughly 1 190 | minute. You should observe that the output is 191 | 1.8633..E+20. However, the correct result is 1.8840...E20. 192 | If you view error.log, there are a number of operations with 193 | more than 45 bits of error. 194 | 195 | Run gdb, set break point to line 28 in SimpsonsRule.c, and start the program: 196 | ``` 197 | $ gdb SimpsonsRule.fp.o 198 | (gdb) break 28 199 | (gdb) r 200 | (gdb) break handleReal.cpp:180 201 | (gdb) y 202 | (gdb) c 203 | ``` 204 | handleReal.cpp:180 is a location in the runtime that 205 | explicitly checks whether an operation has more than or 206 | equal to 45 bits of error. When gdb breaks, look at the 207 | trace of the realRes: 208 | ``` 209 | (gdb) call fpsan_trace(realRes) 210 | ``` 211 | You will notice that at this point, the first operation 212 | FMUL at line 28 has 45 bits of error. It's operands at line 28 and 27 213 | have error of 26 and 45 bits respectively. FADD at line 27 has two operands- 214 | line 25 and 6. Line 6 is a function so we don't have a trace for computations 215 | in this function. To diagnose the errors in this function we have to set a breakpoint 216 | in this function. 217 | ``` 218 | (gdb) delete 219 | (gdb) b SimpsonsRule.c:27 220 | (gdb) b f 221 | (gdb) b fpsan_check_error_f 222 | (gdb) call fpsan_trace(realRes) 223 | ``` 224 | At this point you can see that multiplication at line 6 causes 27 bits of error. 225 | We can investigate how we have got 45 bits of error in FADD at line 25. 226 | We want to skip few iterations of the for loop in floatSimpsonsRuleV1F1. 227 | To do that follow below steps: 228 | ``` 229 | (gdb) b SimpsonsRule.c:23 230 | (gdb) r 231 | (gdb) c 2000 232 | (gdb) b fpsan_check_error_f 233 | (gdb) c 234 | (gdb) call fpsan_trace(realRes) 235 | ``` 236 | This will show error trace for FMUL at line 22 with error of 26 bits. 237 | If you continue skipping some iterations and looking at error trace, you will notice that 238 | error is being accumulated due to computations with very large values. 239 | -------------------------------------------------------------------------------- /case_studies/cordic/cordic_sin/Makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS=-O1 -fno-slp-vectorize -std=c11 -L$(FPROOT)/obj -lfpsanitizer -lmpfr -lm -pthread -ltbb -lstdc++ 2 | CFLAGS=-O1 -fno-slp-vectorize -g -std=c11 -L$(FPSAN_HOME)/fpsan_runtime/obj -lfpsanitizer -lmpfr -lm -lstdc++ 3 | CAMLFLAGs= 4 | CSRC = $(wildcard *.c) 5 | COUT = $(patsubst %.c,%.o,$(CSRC)) 6 | FPCOUT = $(patsubst %.c,%.fp.o,$(CSRC)) 7 | GCC = clang -O1 8 | CC = clang -O1 -pg -Xclang -load -Xclang $(FPSAN_HOME)/fpsan_pass/build/FPSan/libFPSanitizer.so 9 | 10 | all: $(COUT) $(FPCOUT) 11 | 12 | %.fp.o: %.c 13 | $(CC) -o $@ $< $(CFLAGS) 14 | chmod u+x $@ 15 | 16 | %.o: %.c 17 | $(GCC) -o $@ $< $(CFLAGS) 18 | chmod u+x $@ 19 | 20 | clean: 21 | rm -rf *.o *.sout *.dSYM *~ *.log functions.txt *.out 22 | -------------------------------------------------------------------------------- /case_studies/cordic/cordic_sin/cordic_sin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const double angles[60] = { 5 | 7.8539816339744830962E-01, 6 | 4.6364760900080611621E-01, 7 | 2.4497866312686415417E-01, 8 | 1.2435499454676143503E-01, 9 | 6.2418809995957348474E-02, 10 | 3.1239833430268276254E-02, 11 | 1.5623728620476830803E-02, 12 | 7.8123410601011112965E-03, 13 | 3.9062301319669718276E-03, 14 | 1.9531225164788186851E-03, 15 | 9.7656218955931943040E-04, 16 | 4.8828121119489827547E-04, 17 | 2.4414062014936176402E-04, 18 | 1.2207031189367020424E-04, 19 | 6.1035156174208775022E-05, 20 | 3.0517578115526096862E-05, 21 | 1.5258789061315762107E-05, 22 | 7.6293945311019702634E-06, 23 | 3.8146972656064962829E-06, 24 | 1.9073486328101870354E-06, 25 | 9.5367431640596087942E-07, 26 | 4.7683715820308885993E-07, 27 | 2.3841857910155798249E-07, 28 | 1.1920928955078068531E-07, 29 | 5.9604644775390554414E-08, 30 | 2.9802322387695303677E-08, 31 | 1.4901161193847655147E-08, 32 | 7.4505805969238279871E-09, 33 | 3.7252902984619140453E-09, 34 | 1.8626451492309570291E-09, 35 | 9.3132257461547851536E-10, 36 | 4.6566128730773925778E-10, 37 | 2.3283064365386962890E-10, 38 | 1.1641532182693481445E-10, 39 | 5.8207660913467407226E-11, 40 | 2.9103830456733703613E-11, 41 | 1.4551915228366851807E-11, 42 | 7.2759576141834259033E-12, 43 | 3.6379788070917129517E-12, 44 | 1.8189894035458564758E-12, 45 | 9.0949470177292823792E-13, 46 | 4.5474735088646411896E-13, 47 | 2.2737367544323205948E-13, 48 | 1.1368683772161602974E-13, 49 | 5.6843418860808014870E-14, 50 | 2.8421709430404007435E-14, 51 | 1.4210854715202003717E-14, 52 | 7.1054273576010018587E-15, 53 | 3.5527136788005009294E-15, 54 | 1.7763568394002504647E-15, 55 | 8.8817841970012523234E-16, 56 | 4.4408920985006261617E-16, 57 | 2.2204460492503130808E-16, 58 | 1.1102230246251565404E-16, 59 | 5.5511151231257827021E-17, 60 | 2.7755575615628913511E-17, 61 | 1.3877787807814456755E-17, 62 | 6.9388939039072283776E-18, 63 | 3.4694469519536141888E-18, 64 | 1.7347234759768070944E-18 }; 65 | 66 | float cordic_sin (float z) { 67 | float x = 0.60725293500888125617; 68 | float y = 0.0; 69 | float di = 0.0; 70 | float pow2 = 1.0; 71 | float rot_ang; 72 | for (int i = 0; i < 50; i++) { 73 | if (z >= 0) di = 1.0; 74 | else di = -1.0; 75 | 76 | rot_ang = angles[i]; 77 | 78 | float x_prime = x - y * di * pow2; 79 | float y_prime = y + x * di * pow2; 80 | float z_prime = z - di * rot_ang; 81 | 82 | pow2 = pow2 / 2.0; 83 | x = x_prime; 84 | y = y_prime; 85 | z = z_prime; 86 | } 87 | 88 | return y; 89 | } 90 | 91 | int main(int argc, char** argv) { 92 | float sin = cordic_sin(1E-8); 93 | printf("sin:%e\n", sin); 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /case_studies/simpson/Makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS=-O1 -fno-slp-vectorize -std=c11 -L$(FPROOT)/obj -lfpsanitizer -lmpfr -lm -pthread -ltbb -lstdc++ 2 | CFLAGS=-O1 -fno-slp-vectorize -g -std=c11 -L$(FPSAN_HOME)/fpsan_runtime/obj -lfpsanitizer -lmpfr -lm -lstdc++ 3 | CAMLFLAGs= 4 | CSRC = $(wildcard *.c) 5 | COUT = $(patsubst %.c,%.o,$(CSRC)) 6 | FPCOUT = $(patsubst %.c,%.fp.o,$(CSRC)) 7 | GCC = clang -O1 8 | CC = clang -O1 -pg -Xclang -load -Xclang $(FPSAN_HOME)/fpsan_pass/build/FPSan/libFPSanitizer.so 9 | 10 | all: $(COUT) $(FPCOUT) 11 | 12 | %.fp.o: %.c 13 | $(CC) -o $@ $< $(CFLAGS) 14 | chmod u+x $@ 15 | 16 | %.o: %.c 17 | $(GCC) -o $@ $< $(CFLAGS) 18 | chmod u+x $@ 19 | 20 | clean: 21 | rm -rf *.o *.sout *.dSYM *~ *.log functions.txt *.out 22 | -------------------------------------------------------------------------------- /case_studies/simpson/SimpsonsRule.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | float f(float x) { 6 | return x * x; 7 | } 8 | 9 | float f2(float x) { 10 | return sqrtf(x) / (x * x - 1); 11 | } 12 | 13 | void floatSimpsonsRuleV1F1(float lrange, float urange, int n) { 14 | if (n % 2 != 0) { 15 | printf("n has to be an even number\n"); 16 | return; 17 | } 18 | float step = (urange - lrange) / (float)n; 19 | 20 | float sum = f(lrange); 21 | for (int i = 1; i < n; i = i + 2) { 22 | // even-th term: 4 * f(x_{i}) 23 | sum += 4 * f(lrange + (float)i * step); 24 | // odd-th term: 2 * f(x_{i+1}) 25 | sum += 2 * f(lrange + (float)(i + 1) * step); 26 | } 27 | sum += f(urange); 28 | sum *= (step / 3.0); 29 | 30 | printf("V1: %.50e\n", sum); 31 | } 32 | 33 | void floatSimpsonsRuleV1F2(float lrange, float urange, int n) { 34 | if (n % 2 != 0) { 35 | printf("n has to be an even number\n"); 36 | return; 37 | } 38 | float step = (urange - lrange) / (float)n; 39 | 40 | float sum = f2(lrange); 41 | for (int i = 1; i < n; i = i + 2) { 42 | // even-th term: 4 * f(x_{i}) 43 | sum += 4 * f2(lrange + (float)i * step); 44 | // odd-th term: 2 * f(x_{i+1}) 45 | sum += 2 * f2(lrange + (float)(i + 1) * step); 46 | } 47 | sum += f2(urange); 48 | sum *= (step / 3.0); 49 | 50 | printf("V1: %.50e\n", sum); 51 | } 52 | void floatSimpsonsRuleV2F1(float lrange, float urange, int n) { 53 | if (n % 2 != 0) { 54 | printf("n has to be an even number\n"); 55 | return; 56 | } 57 | float step = (urange - lrange) / (float)n; 58 | 59 | float sum = f(lrange) * (step / 3.0); 60 | for (int i = 1; i < n; i = i + 2) { 61 | // even-th term: 4 * f(x_{i}) 62 | sum += 4 * f(lrange + (float)i * step) * (step / 3.0); 63 | // odd-th term: 2 * f(x_{i+1}) 64 | sum += 2 * f(lrange + (float)(i + 1) * step) * (step / 3.0); 65 | } 66 | sum += f(urange) * (step / 3.0); 67 | 68 | printf("V2: %.50e\n", sum); 69 | } 70 | void floatSimpsonsRuleV2F2(float lrange, float urange, int n) { 71 | if (n % 2 != 0) { 72 | printf("n has to be an even number\n"); 73 | return; 74 | } 75 | float step = (urange - lrange) / (float)n; 76 | 77 | float sum = f2(lrange) * (step / 3.0); 78 | for (int i = 1; i < n; i = i + 2) { 79 | // even-th term: 4 * f(x_{i}) 80 | sum += 4 * f2(lrange + (float)i * step) * (step / 3.0); 81 | // odd-th term: 2 * f(x_{i+1}) 82 | sum += 2 * f2(lrange + (float)(i + 1) * step) * (step / 3.0); 83 | } 84 | sum += f2(urange) * (step / 3.0); 85 | 86 | printf("V2: %.50e\n", sum); 87 | } 88 | 89 | int main(int argc, char** argv) { 90 | floatSimpsonsRuleV1F1(13223113, 14223113, 20000000); 91 | } 92 | -------------------------------------------------------------------------------- /case_studies/simpson/mathFunc.txt: -------------------------------------------------------------------------------- 1 | sqrt 2 | sqrtf 3 | cos 4 | sin 5 | tan 6 | cosec 7 | log 8 | exp 9 | pow 10 | hypot 11 | llvm.floor.f64 12 | acos 13 | sinh 14 | cosh 15 | tanh 16 | atan 17 | atan2 18 | llvm.fabs.f64 19 | GSL_MIN_DBL 20 | GSL_MAX_DBL 21 | llvm.ceil.f64 22 | fmod 23 | ldexp 24 | factor 25 | -------------------------------------------------------------------------------- /fpsan_pass/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | 3 | # we need LLVM_HOME in order not automatically set LLVM_DIR 4 | if(NOT DEFINED ENV{LLVM_HOME}) 5 | message(FATAL_ERROR "$LLVM_HOME is not defined") 6 | else () 7 | set(ENV{LLVM_DIR} $ENV{LLVM_HOME}/lib/cmake/llvm) 8 | endif() 9 | 10 | find_package(LLVM REQUIRED CONFIG) 11 | add_definitions(${LLVM_DEFINITIONS}) 12 | include_directories(${LLVM_INCLUDE_DIRS}) 13 | link_directories(${LLVM_LIBRARY_DIRS}) 14 | 15 | add_subdirectory(FPSan) # Use your pass name here. 16 | -------------------------------------------------------------------------------- /fpsan_pass/FPSan/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(FPSanitizer MODULE 2 | # List your source files here. 3 | FPSanitizer.cpp 4 | ) 5 | 6 | # Use C++11 to compile your pass (i.e., supply -std=c++11). 7 | #target_compile_features(FPSanitizer PRIVATE ) 8 | target_compile_features(FPSanitizer PRIVATE cxx_range_for cxx_auto_type) 9 | 10 | # LLVM is (typically) built with no C++ RTTI. We need to match that; 11 | # otherwise, we'll get linker errors about missing RTTI data. 12 | set_target_properties(FPSanitizer PROPERTIES 13 | COMPILE_FLAGS "-fno-rtti" 14 | ) 15 | 16 | # Get proper shared-library behavior (where symbols are not necessarily 17 | # resolved when the shared library is linked) on OS X. 18 | if(APPLE) 19 | set_target_properties(FPSanitizer PROPERTIES 20 | LINK_FLAGS "-undefined dynamic_lookup" 21 | ) 22 | endif(APPLE) 23 | -------------------------------------------------------------------------------- /fpsan_pass/FPSan/FPSanitizer.h: -------------------------------------------------------------------------------- 1 | //===-FPSanitizer.h - Interface ---------------------------------*- C++ -*-===// 2 | // 3 | // 4 | // 5 | //===----------------------------------------------------------------------===// 6 | // 7 | // This pass instruments floating point instructions by inserting 8 | // calls to the runtime to perform shadow execution with arbitrary 9 | // precision. 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "llvm/IR/DebugInfo.h" 14 | #include "llvm/IR/IRBuilder.h" 15 | #include "llvm/IR/LegacyPassManager.h" 16 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 17 | #include "llvm/Analysis/TargetLibraryInfo.h" 18 | #include 19 | #include 20 | #include 21 | 22 | using namespace llvm; 23 | 24 | namespace { 25 | struct FPSanitizer : public ModulePass { 26 | 27 | public: 28 | FPSanitizer() : ModulePass(ID) {} 29 | 30 | virtual bool runOnModule(Module &module); 31 | void createInitMpfr(Value* BOGEP, Function *F, AllocaInst *Alloca, size_t index); 32 | void createInitAndSetMpfr(Value* BOGEP, Function *F, AllocaInst *Alloca, size_t index, Value *OP); 33 | void createInitAndSetP32(Value* BOGEP, Function *F, AllocaInst *Alloca, size_t index, Value *OP); 34 | void instrumentAllFunctions(std::string FN); 35 | void createMpfrAlloca(Function *F); 36 | void callGetArgument(Function *F); 37 | AllocaInst *createAlloca(Function *F, size_t InsCount); 38 | void createGEP(Function *F, AllocaInst *Alloca, long TotalAlloca); 39 | void clearAlloca(Function *F, size_t InsCount); 40 | Instruction* getNextInstruction(Instruction *I, BasicBlock *BB); 41 | Instruction* getNextInstructionNotPhi(Instruction *I, BasicBlock *BB); 42 | void findInterestingFunctions(Function *F); 43 | bool handleOperand(Value* OP, Value **InstIdx); 44 | void handleStore(StoreInst *SI, BasicBlock *BB, Function *F); 45 | void handleNewPhi(Function *F); 46 | void handleFPTrunc(FPTruncInst *FPT, BasicBlock *BB, Function *F); 47 | void copyPhi(Instruction *I, Function *F); 48 | void handlePhi(PHINode *PN, BasicBlock *BB, Function *F); 49 | void handleSelect(SelectInst *SI, BasicBlock *BB, Function *F); 50 | void handleBinOp(BinaryOperator* BO, BasicBlock *BB, Function *F); 51 | void handleFNeg(UnaryOperator *UO, BasicBlock *BB, Function *F); 52 | void handleFcmp(FCmpInst *FCI, BasicBlock *BB, Function *F); 53 | void handleReturn(ReturnInst *RI, BasicBlock *BB, Function *F); 54 | bool checkIfBitcastFromFP(BitCastInst *BI); 55 | void handleLoad(LoadInst *LI, BasicBlock *BB, Function *F); 56 | void handleMathLibFunc(CallInst *CI, BasicBlock *BB, Function *F, std::string Name); 57 | void handleMemCpy(CallInst *CI, BasicBlock *BB, Function *F, std::string Name); 58 | void handleMemset(CallInst *CI, BasicBlock *BB, Function *F, std::string CallName); 59 | void handlePositLibFunc(CallInst *CI, BasicBlock *BB, Function *F, std::string Name); 60 | void handleCallInst (CallInst *CI, BasicBlock *BB, Function *F); 61 | void handleInvokeInst (InvokeInst *CI, BasicBlock *BB, Function *F); 62 | void handleError (CallInst *CI, BasicBlock *BB, Function *F); 63 | bool isListedFunction(StringRef FN, std::string FileName); 64 | void addFunctionsToList(std::string FN); 65 | bool isFloatType(Type *InsType); 66 | bool isFloat(Type *InsType); 67 | bool isDouble(Type *InsType); 68 | void handleMainRet(Instruction *I, Function *F); 69 | void handleFuncInit(Function *F); 70 | void handleFuncMainInit(Function *F); 71 | void handleInit(Module *M); 72 | void handleIns(Instruction *I, BasicBlock *BB, Function *F); 73 | long getTotalFPInst(Function *F); 74 | ConstantInt* GetInstId(Function *F, Instruction* I); 75 | StructType *MPFRTy; 76 | Type *MPtrTy; 77 | Type *RealPtr; 78 | StructType* Real; 79 | std::set LibFuncList; 80 | std::map ConsMap; 81 | std::map GEPMap; 82 | std::map ConstantMap; 83 | //map new instruction with old esp. for select and phi 84 | std::map RegIdMap; 85 | std::map NewPhiMap; 86 | //track unique index for instructions 87 | std::map MInsMap; 88 | std::map MArgMap; 89 | //Arguments can not be instruction, so we need a seperate map to hold indexes for arguments 90 | std::map ArgMap; 91 | std::map FuncTotalArg; 92 | //list of all functions need to be instrumented 93 | SmallVector AllFuncList; 94 | SmallVector AllInstList; 95 | static char ID; // Pass identification 96 | long InsCount = 0; 97 | 98 | std::function GetTLI; 99 | 100 | void getAnalysisUsage(AnalysisUsage &AU) const override { 101 | AU.setPreservesCFG(); 102 | AU.addRequired(); 103 | } 104 | private: 105 | FunctionCallee Func; 106 | FunctionCallee LoadCall; 107 | FunctionCallee ComputeReal; 108 | FunctionCallee FuncExit; 109 | FunctionCallee CheckBranch; 110 | FunctionCallee FuncInit; 111 | FunctionCallee Finish; 112 | FunctionCallee HandleFunc; 113 | FunctionCallee SetRealTemp; 114 | FunctionCallee AddFunArg; 115 | }; 116 | } 117 | 118 | -------------------------------------------------------------------------------- /fpsan_runtime/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = libfpsanitizer 2 | mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) 3 | TD_ROOT := $(notdir $(patsubst %/,%,$(dir $(mkfile_path)))) 4 | CXX=g++ 5 | LINKER=g++ 6 | LDFLAGS+= -shared 7 | OPT=-O0 8 | 9 | PREC := $(if $(PRECISION),$(PRECISION), "PREC_512") 10 | #To enable tracing run - export SET_TRACING=TRACING 11 | TRACING := $(if $(SET_TRACING), $(SET_TRACING), "TRACING") 12 | 13 | #To enable selective execution 14 | SELECTIVE := $(if $(SET_SELECTIVE), $(SET_SELECTIVE), "SELECTIVE") 15 | CXXFLAGS+= -D$(SELECTIVE) -D$(TRACING) -D $(PREC) -fPIC -g -std=c++11 -rdynamic -Wall -lmpfr -pthread 16 | 17 | 18 | INCPATH=-I. 19 | ARFLAGS=-rcs 20 | 21 | # change these to set the proper directories where each files shoould be 22 | SRCDIR = . 23 | INCDIR = . 24 | OBJDIR = obj 25 | BINDIR = bin 26 | 27 | SOURCES := $(wildcard $(SRCDIR)/*.cpp) 28 | INCLUDES := $(wildcard $(INCDIR)/*.h) 29 | OBJECTS := $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o) 30 | rm = rm -rf 31 | 32 | all: 33 | @test -d $(OBJDIR) || mkdir $(OBJDIR) 34 | @make tool 35 | 36 | tool: $(OBJECTS) 37 | @$(LINKER) $(OBJECTS) $(LDFLAGS) -o $(TARGET).so 38 | @mv $(TARGET).so $(OBJDIR) 39 | @echo "Linking complete!" 40 | 41 | $(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.cpp 42 | $(CXX) $(OPT) $(CXXFLAGS) -c $< $(INCPATH) -o $@ 43 | @echo "Compiled "$<" successfully!" 44 | 45 | .PHONY: clean 46 | 47 | clean: 48 | @$(rm) $(OBJDIR) 49 | @$(rm) *~ 50 | @echo "Cleanup complete!" 51 | -------------------------------------------------------------------------------- /fpsan_runtime/handleReal.cpp: -------------------------------------------------------------------------------- 1 | #include "handleReal.h" 2 | 3 | /* 4 | We don't want to call mpfr_init on every add or sub.That's why we keep 5 | it as global variables and do init once and just update on every add or sub 6 | */ 7 | mpfr_t op1_mpfr, op2_mpfr, res_mpfr; 8 | mpfr_t computed, temp_diff; 9 | // fpsan_trace: a function that user can set a breakpoint on to 10 | // generate DAGs 11 | 12 | #ifdef TRACING 13 | extern "C" void fpsan_fpcore(temp_entry *cur){ 14 | if(cur){ 15 | if(m_lock_key_map[cur->op1_lock] != cur->op1_key ){ 16 | if(m_var_map.count(cur) > 0){ 17 | varString += "( x_"+ m_var_map.at(cur) + ")"; 18 | } 19 | else{ 20 | varCount++; 21 | auto var = std::to_string(varCount); 22 | varString += "( x_"+ var + ")"; 23 | m_var_map.insert( std::pair(cur, var) ); 24 | } 25 | return; 26 | } 27 | if(m_lock_key_map[cur->op2_lock] != cur->op2_key){ 28 | if(m_var_map.count(cur) > 0){ 29 | varString += "( x_"+ m_var_map.at(cur) + ")"; 30 | } 31 | else{ 32 | varCount++; 33 | auto var = std::to_string(varCount); 34 | varString += "( x_"+ var + ")"; 35 | m_var_map.insert( std::pair(cur, var) ); 36 | } 37 | return; 38 | } 39 | if(cur->opcode == CONSTANT){ 40 | if(m_var_map.count(cur) > 0){ 41 | varString += "( x_"+ m_var_map.at(cur); 42 | } 43 | else{ 44 | varCount++; 45 | auto var = std::to_string(varCount); 46 | varString += "( x_"+ var ; 47 | m_var_map.insert( std::pair(cur, var) ); 48 | } 49 | } 50 | else{ 51 | varString += "(" + m_get_string_opcode_fpcore(cur->opcode); 52 | } 53 | if(cur->lhs != NULL){ 54 | if(cur->lhs->timestamp < cur->timestamp){ 55 | fpsan_fpcore(cur->lhs); 56 | } 57 | } 58 | if(cur->rhs != NULL){ 59 | if(cur->rhs->timestamp < cur->timestamp){ 60 | fpsan_fpcore(cur->rhs); 61 | } 62 | } 63 | varString += ")"; 64 | } 65 | } 66 | 67 | extern "C" void fpsan_get_fpcore(temp_entry *cur){ 68 | fflush(stdout); 69 | fpsan_fpcore(cur); 70 | std::string out_fpcore; 71 | out_fpcore = "(FPCore ( "; 72 | 73 | while(varCount > 0){ 74 | out_fpcore += "x_"+std::to_string(varCount) + " "; 75 | varCount--; 76 | } 77 | out_fpcore += ")\n"; 78 | out_fpcore += varString; 79 | out_fpcore += ")\n"; 80 | fprintf(m_fpcore, "%s",out_fpcore.c_str()); 81 | varString = ""; 82 | varCount = 0; 83 | } 84 | extern "C" void fpsan_trace(temp_entry *current){ 85 | m_expr.push_back(current); 86 | int level; 87 | while(!m_expr.empty()){ 88 | level = m_expr.size(); 89 | temp_entry *cur = m_expr.front(); 90 | if(cur == NULL){ 91 | return; 92 | } 93 | if(m_lock_key_map[cur->op1_lock] != cur->op1_key ){ 94 | return; 95 | } 96 | if(m_lock_key_map[cur->op2_lock] != cur->op2_key){ 97 | return; 98 | } 99 | std::cout<<"\n"; 100 | std::cout<<" "<lineno<<" "<opcode)<<" "; 101 | fflush(stdout); 102 | if(cur->lhs != NULL){ 103 | std::cout<<" "<lhs->lineno<<" "; 104 | if(cur->lhs->timestamp < cur->timestamp){ 105 | m_expr.push_back(cur->lhs); 106 | fflush(stdout); 107 | } 108 | } 109 | if(cur->rhs != NULL){ 110 | std::cout<<" "<rhs->lineno<<" "; 111 | if(cur->rhs->timestamp < cur->timestamp){ 112 | m_expr.push_back(cur->rhs); 113 | fflush(stdout); 114 | } 115 | } 116 | std::cout<<"(real:"; 117 | m_print_real(cur->val); 118 | printf(" computed: %e", cur->computed); 119 | std::cout<<", error:"<error<<" "<<")"; 120 | fflush(stdout); 121 | m_expr.pop_front(); 122 | level--; 123 | } 124 | int depth = m_get_depth(current); 125 | std::cout<<"depth:"<computed = val; 133 | } 134 | 135 | extern "C" bool fpsan_check_branch_f(float op1d, temp_entry* op1, 136 | float op2d, temp_entry* op2, 137 | size_t fcmpFlag, bool computedRes, 138 | size_t lineNo){ 139 | 140 | bool realRes = m_check_branch(&(op1->val), &(op2->val), fcmpFlag); 141 | if(realRes != computedRes){ 142 | flipsCount++; 143 | } 144 | return realRes; 145 | } 146 | 147 | extern "C" bool fpsan_check_branch_d(double op1d, temp_entry* op1, 148 | double op2d, temp_entry* op2, 149 | size_t fcmpFlag, bool computedRes, 150 | size_t lineNo){ 151 | 152 | bool realRes = m_check_branch(&(op1->val), &(op2->val), fcmpFlag); 153 | if(realRes != computedRes){ 154 | flipsCount++; 155 | } 156 | return realRes; 157 | } 158 | extern "C" unsigned int fpsan_check_conversion(long real, long computed, 159 | temp_entry *realRes){ 160 | if(real != computed){ 161 | return 1; 162 | } 163 | return 0; 164 | } 165 | 166 | unsigned int check_error(temp_entry *realRes, double computedRes){ 167 | #ifdef TRACING 168 | if(debugtrace){ 169 | std::cout<<"m_expr starts\n"; 170 | m_expr.clear(); 171 | fpsan_trace(realRes); 172 | fpsan_get_fpcore(realRes); 173 | std::cout<<"\nm_expr ends\n"; 174 | std::cout<<"\n"; 175 | } 176 | 177 | 178 | if(realRes->error >= ERRORTHRESHOLD) 179 | return 4; 180 | return 0; 181 | #else 182 | int bits_error = m_update_error(realRes, computedRes); 183 | if(bits_error > ERRORTHRESHOLD) 184 | return 4; 185 | 186 | return 0; 187 | #endif 188 | } 189 | 190 | extern "C" unsigned int fpsan_check_error_f(temp_entry *realRes, float computedRes){ 191 | return check_error(realRes, computedRes); 192 | } 193 | 194 | extern "C" unsigned int fpsan_check_error(temp_entry *realRes, double computedRes){ 195 | return check_error(realRes, computedRes); 196 | } 197 | 198 | extern "C" void fpsan_init() { 199 | if (!m_init_flag) { 200 | 201 | m_fpcore = fopen ("fpsan.fpcore","w"); 202 | m_errfile = fopen ("error.log","w"); 203 | m_brfile = fopen ("branch.log","w"); 204 | 205 | //printf("sizeof Real %lu", sizeof(struct smem_entry)); 206 | m_init_flag = true; 207 | size_t length = MAX_STACK_SIZE * sizeof(temp_entry); 208 | 209 | m_shadow_stack = 210 | (temp_entry *)mmap(0, length, PROT_READ | PROT_WRITE, MMAP_FLAGS, -1, 0); 211 | #ifdef TRACING 212 | m_lock_key_map = 213 | (size_t *)mmap(0, length, PROT_READ | PROT_WRITE, MMAP_FLAGS, -1, 0); 214 | assert(m_lock_key_map != (void *)-1); 215 | #endif 216 | 217 | 218 | #ifdef METADATA_AS_TRIE 219 | 220 | size_t memLen = SS_PRIMARY_TABLE_ENTRIES * sizeof(smem_entry *); 221 | m_shadow_memory = 222 | (smem_entry **)mmap(0, memLen, PROT_READ | PROT_WRITE, MMAP_FLAGS, -1, 0); 223 | 224 | #else 225 | size_t hash_size = (HASH_TABLE_ENTRIES) * sizeof(smem_entry); 226 | m_shadow_memory = 227 | (smem_entry *) mmap(0, hash_size, PROT_READ | PROT_WRITE, MMAP_FLAGS, -1, 0); 228 | 229 | #endif 230 | 231 | assert(m_shadow_stack != (void *)-1); 232 | assert(m_shadow_memory != (void *)-1); 233 | 234 | #ifdef TRACING 235 | m_key_stack_top = 1; 236 | m_key_counter = 1; 237 | 238 | m_lock_key_map[m_key_stack_top] = m_key_counter; 239 | #endif 240 | 241 | for(int i =0; ival, m_precision); 264 | 265 | #ifdef TRACING 266 | op->lock = m_key_stack_top; 267 | op->key = m_lock_key_map[m_key_stack_top]; 268 | #endif 269 | 270 | } 271 | 272 | extern "C" void fpsan_init_store_shadow_dconst(smem_entry *op, double d, 273 | unsigned int linenumber) { 274 | 275 | if(!op->is_init){ 276 | op->is_init = true; 277 | mpfr_init2(op->val, m_precision); 278 | } 279 | m_store_shadow_dconst(op, d, linenumber); 280 | } 281 | 282 | extern "C" void fpsan_init_store_shadow_fconst(smem_entry *op, float f, unsigned int linenumber) { 283 | 284 | if(!op->is_init){ 285 | op->is_init = true; 286 | mpfr_init2(op->val, m_precision); 287 | } 288 | m_store_shadow_fconst(op, f, linenumber); 289 | } 290 | 291 | int m_isnan(mpfr_t real){ 292 | return mpfr_nan_p(real); 293 | } 294 | 295 | 296 | void m_store_shadow_dconst(smem_entry *op, double d, unsigned int linenumber) { 297 | 298 | mpfr_set_d(op->val, d, MPFR_RNDN); 299 | 300 | #ifdef TRACING 301 | op->lock = m_key_stack_top; 302 | op->key = m_lock_key_map[m_key_stack_top]; 303 | op->error = 0; 304 | op->tmp_ptr = NULL; 305 | #endif 306 | 307 | op->lineno = linenumber; 308 | op->opcode = CONSTANT; 309 | op->computed = d; 310 | 311 | } 312 | 313 | void m_store_shadow_fconst(smem_entry *op, float f, unsigned int linenumber) { 314 | 315 | mpfr_set_flt(op->val, f, MPFR_RNDN); 316 | #ifdef TRACING 317 | op->lock = m_key_stack_top; 318 | op->key = m_lock_key_map[m_key_stack_top]; 319 | op->error = 0; 320 | op->tmp_ptr = NULL; 321 | #endif 322 | 323 | op->lineno = linenumber; 324 | op->opcode = CONSTANT; 325 | op->computed = f; 326 | } 327 | 328 | extern "C" void fpsan_store_tempmeta_dconst(temp_entry *op, double d, unsigned int linenumber) { 329 | 330 | mpfr_set_d(op->val, d, MPFR_RNDN); 331 | 332 | #ifdef TRACING 333 | op->lock = m_key_stack_top; 334 | op->key = m_lock_key_map[m_key_stack_top]; 335 | op->op1_lock = 0; 336 | op->op1_key = 0; 337 | op->op2_lock = 0; 338 | op->op2_key = 0; 339 | op->lhs = NULL; 340 | op->rhs = NULL; 341 | op->error = 0; 342 | op->timestamp = m_timestamp++; 343 | #endif 344 | 345 | op->lineno = linenumber; 346 | op->opcode = CONSTANT; 347 | op->computed = d; 348 | 349 | } 350 | 351 | extern "C" void fpsan_store_tempmeta_fconst(temp_entry *op, float f, unsigned int linenumber) { 352 | 353 | mpfr_set_flt(op->val, f, MPFR_RNDN); 354 | 355 | #ifdef TRACING 356 | op->lock = m_key_stack_top; 357 | op->key = m_lock_key_map[m_key_stack_top]; 358 | op->op1_lock = 0; 359 | op->op1_key = 0; 360 | op->op2_lock = 0; 361 | op->op2_key = 0; 362 | op->lhs = NULL; 363 | op->rhs = NULL; 364 | op->error = 0; 365 | op->timestamp = m_timestamp++; 366 | #endif 367 | 368 | op->lineno = linenumber; 369 | op->opcode = CONSTANT; 370 | op->computed = f; 371 | 372 | } 373 | 374 | extern "C" void fpsan_clear_mpfr(mpfr_t *val) { 375 | mpfr_clear(*val); 376 | } 377 | 378 | float m_get_float(mpfr_t mpfr_val) { return mpfr_get_flt(mpfr_val, MPFR_RNDN); } 379 | 380 | double m_get_double(mpfr_t mpfr_val) { return mpfr_get_d(mpfr_val, MPFR_RNDN); } 381 | 382 | long double m_get_longdouble(temp_entry *real) { 383 | return mpfr_get_ld(real->val, MPFR_RNDN); 384 | } 385 | 386 | #ifdef METADATA_AS_TRIE 387 | 388 | smem_entry* m_get_shadowaddress(size_t address){ 389 | size_t addrInt = address >> 2; 390 | size_t primary_index = (addrInt >> SECONDARY_INDEX_BITS ); 391 | smem_entry* primary_ptr = m_shadow_memory[primary_index]; 392 | if (primary_ptr == NULL) { 393 | size_t sec_length = (SS_SEC_TABLE_ENTRIES) * sizeof(smem_entry); 394 | primary_ptr = (smem_entry*)mmap(0, sec_length, PROT_READ| PROT_WRITE, 395 | MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0); 396 | m_shadow_memory[primary_index] = primary_ptr; 397 | } 398 | size_t offset = (addrInt) & SECONDARY_MASK; 399 | smem_entry* realAddr = primary_ptr + offset; 400 | if(!realAddr->is_init){ 401 | realAddr->is_init = true; 402 | mpfr_init2(realAddr->val, m_precision); 403 | } 404 | return realAddr; 405 | } 406 | 407 | #else 408 | 409 | smem_entry* m_get_shadowaddress (size_t address){ 410 | size_t addr_int = address >> 2; 411 | size_t index = addr_int % HASH_TABLE_ENTRIES; 412 | smem_entry* realAddr = m_shadow_memory + index; 413 | if(!realAddr->is_init){ 414 | realAddr->is_init = true; 415 | mpfr_init2(realAddr->val, m_precision); 416 | } 417 | return realAddr; 418 | } 419 | 420 | #endif 421 | 422 | extern "C" void fpsan_handle_memset(void *toAddr, int val, 423 | int size) { 424 | 425 | size_t toAddrInt = (size_t)(toAddr); 426 | for (int i = 0; i < size; i++) { 427 | smem_entry *dst = m_get_shadowaddress(toAddrInt + i); 428 | if (!dst->is_init) { 429 | dst->is_init = true; 430 | mpfr_init2(dst->val, m_precision); 431 | } 432 | mpfr_set_d(dst->val, val, MPFR_RNDN); 433 | 434 | #ifdef TRACING 435 | dst->error = 0; 436 | dst->lock = m_key_stack_top; 437 | dst->key = m_lock_key_map[m_key_stack_top]; 438 | dst->tmp_ptr = 0; 439 | #endif 440 | 441 | dst->is_init = true; 442 | dst->lineno = 0; 443 | dst->computed = val; 444 | dst->opcode = CONSTANT; 445 | } 446 | } 447 | 448 | extern "C" void fpsan_handle_memcpy(void* toAddr, void* fromAddr, int size){ 449 | 450 | size_t toAddrInt = (size_t) (toAddr); 451 | size_t fromAddrInt = (size_t) (fromAddr); 452 | for(int i=0; ival), &(src->val)); 456 | 457 | #ifdef TRACING 458 | dst->error = src->error; 459 | dst->lock = m_key_stack_top; 460 | dst->key = m_lock_key_map[m_key_stack_top]; 461 | dst->tmp_ptr = src->tmp_ptr; 462 | #endif 463 | 464 | dst->is_init = true; 465 | dst->lineno = src->lineno; 466 | dst->computed = src->computed; 467 | dst->opcode = src->opcode; 468 | } 469 | } 470 | void m_print_real(mpfr_t mpfr_val){ 471 | 472 | mpfr_out_str (stdout, 10, 15, mpfr_val, MPFR_RNDN); 473 | } 474 | 475 | 476 | /* storing metadata for constants */ 477 | 478 | extern "C" void fpsan_store_shadow_fconst(void* toAddr, float op, unsigned int linenumber){ 479 | 480 | size_t toAddrInt = (size_t) toAddr; 481 | smem_entry* dest = m_get_shadowaddress(toAddrInt); 482 | fpsan_init_store_shadow_fconst(dest, op, linenumber); 483 | dest->is_init = true; 484 | } 485 | 486 | /* storing metadata for constants */ 487 | 488 | extern "C" void fpsan_store_shadow_dconst(void* toAddr, double op, 489 | unsigned int linenumber){ 490 | 491 | size_t toAddrInt = (size_t) toAddr; 492 | smem_entry* dest = m_get_shadowaddress(toAddrInt); 493 | fpsan_init_store_shadow_dconst(dest, op, linenumber); 494 | dest->is_init = true; 495 | 496 | } 497 | 498 | extern "C" void fpsan_copy_phi(temp_entry* src, temp_entry* dst){ 499 | 500 | if(src != NULL){ 501 | m_set_mpfr(&(dst->val), &(src->val)); 502 | dst->computed = src->computed; 503 | dst->opcode = src->opcode; 504 | dst->lineno = src->lineno; 505 | dst->is_init = true; 506 | 507 | #ifdef TRACING 508 | dst->lock = m_key_stack_top; 509 | dst->key = m_lock_key_map[m_key_stack_top]; 510 | dst->error = src->error; 511 | 512 | dst->op1_lock = src->op1_lock; 513 | dst->op1_key = src->op1_key; 514 | dst->lhs = src->lhs; 515 | dst->op2_lock = src->op2_lock; 516 | dst->op2_key = src->op2_key; 517 | dst->rhs = src->rhs; 518 | dst->timestamp = src->timestamp; 519 | #endif 520 | } 521 | } 522 | 523 | extern "C" void fpsan_store_shadow(void* toAddr, temp_entry* src){ 524 | 525 | if(src == NULL){ 526 | std::cout<<"Error !!! __set_real trying to read invalid memory\n"; 527 | return; 528 | } 529 | 530 | size_t toAddrInt = (size_t) toAddr; 531 | smem_entry* dest = m_get_shadowaddress(toAddrInt); 532 | 533 | /*copy val*/ 534 | m_set_mpfr(&(dest->val), &(src->val)); 535 | /*copy everything else except res key and opcode*/ 536 | #ifdef TRACING 537 | dest->error = src->error; 538 | dest->lock = m_key_stack_top; 539 | dest->key = m_lock_key_map[m_key_stack_top]; 540 | dest->tmp_ptr = src; 541 | #endif 542 | 543 | dest->is_init = true; 544 | dest->lineno = src->lineno; 545 | dest->computed = src->computed; 546 | dest->opcode = src->opcode; 547 | 548 | } 549 | 550 | extern "C" void fpsan_load_shadow_fconst(temp_entry *src, void *Addr, float d){ 551 | 552 | if(src == NULL) { 553 | if(debug){ 554 | printf("__load_d:Error !!! __load_d trying to load from invalid stack\n"); 555 | } 556 | return; 557 | } 558 | 559 | size_t AddrInt = (size_t) Addr; 560 | smem_entry* dest = m_get_shadowaddress(AddrInt); 561 | 562 | #ifdef SELECTIVE 563 | 564 | double orig = (double) d; 565 | if(orig != dest->computed){ 566 | fpsan_store_tempmeta_fconst(src, d, 0); //for global variables 567 | return; 568 | } 569 | #endif 570 | 571 | /* copy the metadata from shadow memory to temp metadata*/ 572 | m_set_mpfr(&(src->val), &(dest->val)); 573 | #ifdef TRACING 574 | src->lock = m_key_stack_top; 575 | src->key = m_lock_key_map[m_key_stack_top]; 576 | src->error = dest->error; 577 | #endif 578 | 579 | src->lineno = dest->lineno; 580 | src->computed = dest->computed; 581 | src->opcode = dest->opcode; 582 | 583 | 584 | #ifdef TRACING 585 | /* if the temp metadata is not available (i.e, the function 586 | producing the value has returned), then treat the value loaded 587 | from the shadow memory as a constant from the perspective of 588 | tracing */ 589 | 590 | if( dest->tmp_ptr != NULL && 591 | m_lock_key_map[dest->lock] == dest->key){ 592 | 593 | src->op1_lock = dest->tmp_ptr->op1_lock; 594 | src->op1_key = dest->tmp_ptr->op1_key; 595 | src->lhs = dest->tmp_ptr->lhs; 596 | 597 | src->op2_lock = dest->tmp_ptr->op2_lock; 598 | src->op2_key = dest->tmp_ptr->op2_key; 599 | src->rhs = dest->tmp_ptr->rhs; 600 | 601 | src->timestamp = dest->tmp_ptr->timestamp; 602 | } 603 | else{ 604 | /* No trace information available, treat like a constant */ 605 | if(debug) 606 | std::cout<<"__load_d copying default\n"; 607 | 608 | #if 0 609 | /* This looks redundant with fpsan_store_tempmeta_fconst operations */ 610 | src->op1_lock = 0; 611 | src->op1_key = 0; 612 | src->op2_lock = 0; 613 | src->op2_key = 0; 614 | src->lhs = NULL; 615 | src->rhs = NULL; 616 | src->timestamp = m_timestamp++; 617 | #endif 618 | fpsan_store_tempmeta_fconst(src, d, 0); //for global variables 619 | } 620 | #endif 621 | 622 | } 623 | 624 | extern "C" void fpsan_load_shadow_dconst(temp_entry *src, void *Addr, double d){ 625 | 626 | if(src == NULL){ 627 | if(debug){ 628 | printf("__load_d:Error !!! __load_d trying to load from invalid stack\n"); 629 | } 630 | return; 631 | } 632 | 633 | size_t AddrInt = (size_t) Addr; 634 | smem_entry* dest = m_get_shadowaddress(AddrInt); 635 | 636 | #ifdef SELECTIVE 637 | /* double value in the metadata space mismatches with the computed 638 | value */ 639 | if(d != dest->computed){ 640 | fpsan_store_tempmeta_dconst(src, d, 0); 641 | return; 642 | } 643 | #endif 644 | 645 | m_set_mpfr(&(src->val), &(dest->val)); 646 | src->lineno = dest->lineno; 647 | src->computed = dest->computed; 648 | src->opcode = dest->opcode; 649 | 650 | #ifdef TRACING 651 | src->lock = m_key_stack_top; 652 | src->key = m_lock_key_map[m_key_stack_top]; 653 | src->error = dest->error; 654 | 655 | /* if the temp metadata is not available (i.e, the function 656 | producing the value has returned), then treat the value loaded 657 | from the shadow memory as a constant from the perspective of 658 | tracing */ 659 | 660 | if( dest->tmp_ptr != NULL && 661 | m_lock_key_map[dest->lock] == dest->key){ 662 | src->op1_lock = dest->tmp_ptr->op1_lock; 663 | src->op1_key = dest->tmp_ptr->op1_key; 664 | src->op2_lock = dest->tmp_ptr->op2_lock; 665 | src->op2_key = dest->tmp_ptr->op2_key; 666 | src->lhs = dest->tmp_ptr->lhs; 667 | src->rhs = dest->tmp_ptr->rhs; 668 | src->timestamp = dest->tmp_ptr->timestamp; 669 | } 670 | else{ 671 | if(debug){ 672 | std::cout<<"__load_d copying default\n"; 673 | } 674 | fpsan_store_tempmeta_dconst(src, d, 0); //for global variables 675 | } 676 | #endif 677 | } 678 | 679 | void handle_math_d(fp_op opCode, double op1d, temp_entry *op, 680 | double computedResd, temp_entry *res, 681 | unsigned int linenumber) { 682 | 683 | switch(opCode){ 684 | case SQRT: 685 | mpfr_sqrt(res->val, op->val, MPFR_RNDN); 686 | break; 687 | case FLOOR: 688 | mpfr_floor(res->val, op->val); 689 | break; 690 | case CEIL: 691 | mpfr_ceil(res->val, op->val); 692 | break; 693 | case TAN: 694 | mpfr_tan(res->val, op->val, MPFR_RNDN); 695 | break; 696 | case TANH: 697 | mpfr_tanh(res->val, op->val, MPFR_RNDN); 698 | break; 699 | case SIN: 700 | mpfr_sin(res->val, op->val, MPFR_RNDN); 701 | break; 702 | case SINH: 703 | mpfr_sinh(res->val, op->val, MPFR_RNDN); 704 | break; 705 | case COS: 706 | mpfr_cos(res->val, op->val, MPFR_RNDN); 707 | break; 708 | case COSH: 709 | mpfr_cosh(res->val, op->val, MPFR_RNDN); 710 | break; 711 | case ACOS: 712 | mpfr_acos(res->val, op->val, MPFR_RNDN); 713 | break; 714 | case ATAN: 715 | mpfr_atan(res->val, op->val, MPFR_RNDN); 716 | break; 717 | case ABS: 718 | mpfr_abs(res->val, op->val, MPFR_RNDN); 719 | break; 720 | case LOG: 721 | mpfr_log(res->val, op->val, MPFR_RNDN); 722 | break; 723 | case LOG10: 724 | mpfr_log10(res->val, op->val, MPFR_RNDN); 725 | break; 726 | case ASIN: 727 | mpfr_asin(res->val, op->val, MPFR_RNDN); 728 | break; 729 | case EXP: 730 | mpfr_exp(res->val, op->val, MPFR_RNDN); 731 | break; 732 | default: 733 | std::cout<<"Error!!! Math function not supported\n\n"; 734 | exit(1); 735 | break; 736 | } 737 | if(isinf(computedResd)) 738 | infCount++; 739 | if (computedResd != computedResd) 740 | nanCount++; 741 | 742 | #ifdef TRACING 743 | int bitsError = m_update_error(res, computedResd); 744 | res->op1_lock = op->lock; 745 | res->op1_key = m_lock_key_map[op->lock]; 746 | res->op2_lock = 0; 747 | res->op2_key = 0; 748 | res->lock = m_key_stack_top; 749 | res->key = m_lock_key_map[m_key_stack_top]; 750 | res->lhs = op; 751 | res->rhs = nullptr; 752 | res->timestamp = m_timestamp++; 753 | res->error = bitsError; 754 | #endif 755 | 756 | res->lineno = linenumber; 757 | res->opcode = opCode; 758 | res->computed = computedResd; 759 | } 760 | 761 | void m_compute(fp_op opCode, double op1d, 762 | temp_entry *op1, double op2d, 763 | temp_entry *op2, double computedResd, 764 | temp_entry *res, size_t lineNo) { 765 | 766 | switch(opCode) { 767 | case FADD: 768 | mpfr_add (res->val, op1->val, op2->val, MPFR_RNDN); 769 | break; 770 | 771 | case FSUB: 772 | mpfr_sub (res->val, op1->val, op2->val, MPFR_RNDN); 773 | break; 774 | 775 | case FMUL: 776 | mpfr_mul (res->val, op1->val, op2->val, MPFR_RNDN); 777 | break; 778 | 779 | case FDIV: 780 | mpfr_div (res->val, op1->val, op2->val, MPFR_RNDN); 781 | break; 782 | 783 | default: 784 | // do nothing 785 | break; 786 | } 787 | 788 | if (computedResd != computedResd) 789 | nanCount++; 790 | if(debug){ 791 | printf("compute: res:%p\n", res); 792 | m_print_real(res->val); 793 | printf("compute: res:%p\n", res); 794 | } 795 | 796 | #ifdef TRACING 797 | int bitsError = m_update_error(res, computedResd); 798 | res->op1_lock = op1->lock; 799 | res->op2_lock = op2->lock; 800 | res->op1_key = m_lock_key_map[op1->lock]; 801 | res->op2_key = m_lock_key_map[op2->lock]; 802 | res->lock = m_key_stack_top; 803 | res->key = m_lock_key_map[m_key_stack_top]; 804 | res->lhs = op1; 805 | res->rhs = op2; 806 | res->timestamp = m_timestamp++; 807 | res->error = bitsError; 808 | #endif 809 | 810 | res->lineno = lineNo; 811 | res->opcode = opCode; 812 | res->computed = computedResd; 813 | } 814 | 815 | unsigned int m_get_exact_bits( 816 | double opD, int precBits, 817 | temp_entry *shadow){ 818 | 819 | mpfr_set_d(computed, opD, MPFR_RNDN); 820 | 821 | mpfr_sub(temp_diff, shadow->val, computed, MPFR_RNDN); 822 | 823 | mpfr_exp_t exp_real = mpfr_get_exp(shadow->val); 824 | mpfr_exp_t exp_computed = mpfr_get_exp(computed); 825 | mpfr_exp_t exp_diff = mpfr_get_exp(temp_diff); 826 | 827 | if(mpfr_cmp(computed, shadow->val) == 0){ 828 | return precBits; 829 | } 830 | else if(exp_real != exp_computed){ 831 | return 0; 832 | } 833 | else{ 834 | if(mpfr_cmp_ui(temp_diff, 0) != 0) { 835 | if(precBits < abs(exp_real - exp_diff)){ 836 | return precBits; 837 | } 838 | else{ 839 | return abs(exp_real - exp_diff); 840 | } 841 | } 842 | else{ 843 | return 0; 844 | } 845 | } 846 | } 847 | 848 | mpfr_exp_t m_get_cancelled_bits(double op1, double op2, double res){ 849 | mpfr_set_d(op1_mpfr, op1, MPFR_RNDN); 850 | 851 | mpfr_set_d(op2_mpfr, op2, MPFR_RNDN); 852 | 853 | mpfr_set_d(res_mpfr, res, MPFR_RNDN); 854 | 855 | mpfr_exp_t exp_op1 = mpfr_get_exp(op1_mpfr); 856 | mpfr_exp_t exp_op2 = mpfr_get_exp(op2_mpfr); 857 | mpfr_exp_t exp_res = mpfr_get_exp(res_mpfr); 858 | 859 | mpfr_exp_t max_exp; 860 | if( mpfr_regular_p(op1_mpfr) == 0 || 861 | mpfr_regular_p(op2_mpfr) == 0 || 862 | mpfr_regular_p(res_mpfr) == 0) 863 | return 0; 864 | 865 | if(exp_op1 > exp_op2) 866 | max_exp = exp_op1; 867 | else 868 | max_exp = exp_op2; 869 | 870 | if(max_exp > exp_res) 871 | return abs(max_exp - exp_res); 872 | else 873 | return 0; 874 | } 875 | 876 | unsigned int m_get_cbad(mpfr_exp_t cbits, 877 | unsigned int ebitsOp1, 878 | unsigned int ebitsOp2){ 879 | unsigned int min_ebits; 880 | if (ebitsOp1 > ebitsOp2) 881 | min_ebits = ebitsOp2; 882 | else 883 | min_ebits = ebitsOp1; 884 | int badness = 1 + cbits - min_ebits; 885 | if(badness > 0) 886 | return badness; 887 | else 888 | return 0; 889 | } 890 | 891 | #ifdef TRACING 892 | unsigned int m_check_cc(double op1, 893 | double op2, 894 | double res, 895 | int precBits, 896 | temp_entry *shadowOp1, 897 | temp_entry *shadowOp2, 898 | temp_entry *shadowVal){ 899 | 900 | /* If op1 or op2 is NaR, then it is not catastrophic cancellation*/ 901 | if (isnan(op1) || isnan(op2)) return 0; 902 | /* If result is 0 and it has error, then it is catastrophic cancellation*/ 903 | if ((res == 0) && shadowVal->error != 0) return 1; 904 | 905 | unsigned int ebitsOp1 = m_get_exact_bits(op1, precBits, shadowOp1); 906 | unsigned int ebitsOp2 = m_get_exact_bits(op2, precBits, shadowOp2); 907 | mpfr_exp_t cbits = m_get_cancelled_bits(op1, op2, res); 908 | unsigned int cbad = m_get_cbad(cbits, ebitsOp1, ebitsOp2); 909 | return cbad; 910 | } 911 | #endif 912 | 913 | extern "C" void fpsan_mpfr_fneg(temp_entry *op1Idx, temp_entry *res, 914 | unsigned int linenumber) { 915 | 916 | mpfr_t zero; 917 | mpfr_init2(zero, m_precision); 918 | mpfr_set_d(zero, 0, MPFR_RNDN); 919 | 920 | mpfr_sub(res->val, zero, op1Idx->val, MPFR_RNDN); 921 | mpfr_clear(zero); 922 | #ifdef TRACING 923 | res->op1_lock = op1Idx->op1_lock; 924 | res->op2_lock = op1Idx->op2_lock; 925 | res->op1_key = op1Idx->op1_key; 926 | res->op2_key = op1Idx->op2_key; 927 | res->lock = op1Idx->lock; 928 | res->key = op1Idx->key; 929 | res->lhs = op1Idx->lhs; 930 | res->rhs = op1Idx->rhs; 931 | res->timestamp = op1Idx->timestamp; 932 | res->error = op1Idx->error; 933 | #endif 934 | 935 | res->opcode = op1Idx->opcode; 936 | res->computed = -op1Idx->computed; 937 | } 938 | 939 | extern "C" void fpsan_mpfr_fadd_f( temp_entry* op1Idx, 940 | temp_entry* op2Idx, 941 | temp_entry* res, 942 | float op1d, 943 | float op2d, 944 | float computedResD, 945 | unsigned long long int instId, 946 | bool debugInfoAvail, 947 | unsigned int linenumber, 948 | unsigned int colnumber) { 949 | 950 | m_compute(FADD, op1d, op1Idx, op2d, op2Idx, 951 | computedResD, res, linenumber); 952 | 953 | #ifdef TRACING 954 | unsigned int cbad = 0; 955 | if(((op1d < 0) && (op2d > 0)) || 956 | ((op1d > 0) && (op2d < 0))){ 957 | cbad = m_check_cc(op1d, op2d, computedResD, m_prec_bits_f, op1Idx, op2Idx, res); 958 | if(cbad > 0) 959 | ccCount++; 960 | } 961 | #endif 962 | } 963 | 964 | extern "C" void fpsan_mpfr_fsub_f( temp_entry* op1Idx, 965 | temp_entry* op2Idx, 966 | temp_entry* res, 967 | float op1d, 968 | float op2d, 969 | float computedResD, 970 | unsigned long long int instId, 971 | bool debugInfoAvail, 972 | unsigned int linenumber, 973 | unsigned int colnumber) { 974 | 975 | m_compute(FSUB, op1d, op1Idx, op2d, op2Idx, 976 | computedResD, res, linenumber); 977 | 978 | #ifdef TRACING 979 | unsigned int cbad = 0; 980 | if(((op1d < 0) && (op2d < 0)) || 981 | ((op1d > 0) && (op2d > 0))){ 982 | cbad = m_check_cc(op1d, op2d, computedResD, m_prec_bits_f, op1Idx, op2Idx, res); 983 | if(cbad > 0) 984 | ccCount++; 985 | } 986 | #endif 987 | } 988 | 989 | extern "C" void fpsan_mpfr_fmul_f( temp_entry* op1Idx, 990 | temp_entry* op2Idx, 991 | temp_entry* res, 992 | float op1d, 993 | float op2d, 994 | float computedResD, 995 | unsigned long long int instId, 996 | bool debugInfoAvail, 997 | unsigned int linenumber, 998 | unsigned int colnumber) { 999 | 1000 | m_compute(FMUL, op1d, op1Idx, op2d, op2Idx, 1001 | computedResD, res, linenumber); 1002 | } 1003 | 1004 | extern "C" void fpsan_mpfr_fdiv_f( temp_entry* op1Idx, 1005 | temp_entry* op2Idx, 1006 | temp_entry* res, 1007 | float op1d, 1008 | float op2d, 1009 | float computedResD, 1010 | unsigned long long int instId, 1011 | bool debugInfoAvail, 1012 | unsigned int linenumber, 1013 | unsigned int colnumber) { 1014 | 1015 | m_compute(FDIV, op1d, op1Idx, op2d, op2Idx, 1016 | computedResD, res, linenumber); 1017 | if(isinf(computedResD)) 1018 | infCount++; 1019 | } 1020 | 1021 | extern "C" void fpsan_mpfr_fadd( temp_entry* op1Idx, 1022 | temp_entry* op2Idx, 1023 | temp_entry* res, 1024 | double op1d, 1025 | double op2d, 1026 | double computedResD, 1027 | unsigned long long int instId, 1028 | bool debugInfoAvail, 1029 | unsigned int linenumber, 1030 | unsigned int colnumber) { 1031 | 1032 | m_compute(FADD, op1d, op1Idx, op2d, op2Idx, 1033 | computedResD, res, linenumber); 1034 | 1035 | #ifdef TRACING 1036 | unsigned int cbad = 0; 1037 | if(((op1d < 0) && (op2d > 0)) || 1038 | ((op1d > 0) && (op2d < 0))){ 1039 | cbad = m_check_cc(op1d, op2d, computedResD, m_prec_bits_d, op1Idx, op2Idx, res); 1040 | if(cbad > 0) 1041 | ccCount++; 1042 | } 1043 | #endif 1044 | } 1045 | 1046 | extern "C" void fpsan_mpfr_fsub( temp_entry* op1Idx, 1047 | temp_entry* op2Idx, 1048 | temp_entry* res, 1049 | double op1d, 1050 | double op2d, 1051 | double computedResD, 1052 | unsigned long long int instId, 1053 | bool debugInfoAvail, 1054 | unsigned int linenumber, 1055 | unsigned int colnumber) { 1056 | 1057 | m_compute(FSUB, op1d, op1Idx, op2d, op2Idx, 1058 | computedResD, res, linenumber); 1059 | 1060 | #ifdef TRACING 1061 | unsigned int cbad = 0; 1062 | if(((op1d < 0) && (op2d < 0)) || 1063 | ((op1d > 0) && (op2d > 0))){ 1064 | cbad = m_check_cc(op1d, op2d, computedResD, m_prec_bits_d, op1Idx, op2Idx, res); 1065 | if(cbad > 0) 1066 | ccCount++; 1067 | } 1068 | #endif 1069 | } 1070 | 1071 | extern "C" void fpsan_mpfr_fmul( temp_entry* op1Idx, 1072 | temp_entry* op2Idx, 1073 | temp_entry* res, 1074 | double op1d, 1075 | double op2d, 1076 | double computedResD, 1077 | unsigned long long int instId, 1078 | bool debugInfoAvail, 1079 | unsigned int linenumber, 1080 | unsigned int colnumber) { 1081 | 1082 | m_compute(FMUL, op1d, op1Idx, op2d, op2Idx, 1083 | computedResD, res, linenumber); 1084 | } 1085 | 1086 | extern "C" void fpsan_mpfr_fdiv( temp_entry* op1Idx, 1087 | temp_entry* op2Idx, 1088 | temp_entry* res, 1089 | double op1d, 1090 | double op2d, 1091 | double computedResD, 1092 | unsigned long long int instId, 1093 | bool debugInfoAvail, 1094 | unsigned int linenumber, 1095 | unsigned int colnumber) { 1096 | 1097 | m_compute(FDIV, op1d, op1Idx, op2d, op2Idx, 1098 | computedResD, res, linenumber); 1099 | if(isinf(computedResD)) 1100 | infCount++; 1101 | } 1102 | 1103 | bool m_check_branch(mpfr_t* op1, mpfr_t* op2, 1104 | size_t fcmpFlag){ 1105 | bool realRes = false; 1106 | int ret = mpfr_cmp(*op1, *op2); 1107 | 1108 | switch(fcmpFlag){ 1109 | case 0: 1110 | realRes = false; 1111 | break; 1112 | case 1: /*oeq*/ 1113 | if(!m_isnan(*op1) && !m_isnan(*op2)){ 1114 | if(ret == 0) 1115 | realRes = true; 1116 | } 1117 | break; 1118 | case 2: /*ogt*/ 1119 | if(!m_isnan(*op1) && !m_isnan(*op2)){ 1120 | if(ret > 0){ 1121 | realRes = true; 1122 | } 1123 | } 1124 | break; 1125 | case 3: 1126 | if(!m_isnan(*op1) && !m_isnan(*op2)){ 1127 | if(ret > 0 || ret == 0){ 1128 | realRes = true; 1129 | } 1130 | } 1131 | break; 1132 | case 4: /*olt*/ 1133 | if(!m_isnan(*op1) && !m_isnan(*op2)){ 1134 | if(ret < 0){ 1135 | realRes = true; 1136 | } 1137 | } 1138 | break; 1139 | case 5: 1140 | if(!m_isnan(*op1) && !m_isnan(*op2)){ 1141 | if(ret < 0 || ret == 0){ 1142 | realRes = true; 1143 | } 1144 | } 1145 | break; 1146 | case 6: 1147 | if(!m_isnan(*op1) && !m_isnan(*op2)){ 1148 | if(ret != 0){ 1149 | realRes = true; 1150 | } 1151 | } 1152 | break; 1153 | case 7: 1154 | if(!m_isnan(*op1) && !m_isnan(*op2)){ 1155 | realRes = true; 1156 | } 1157 | break; 1158 | case 8: 1159 | if(m_isnan(*op1) && m_isnan(*op2)){ 1160 | realRes = true; 1161 | } 1162 | break; 1163 | case 9: 1164 | if(m_isnan(*op1) || m_isnan(*op2) || ret == 0) 1165 | realRes = true; 1166 | break; 1167 | case 10: 1168 | if(m_isnan(*op1) || m_isnan(*op2) || ret > 0) 1169 | realRes = true; 1170 | break; 1171 | case 11: 1172 | if(m_isnan(*op1) || m_isnan(*op2) || ret >= 0) 1173 | realRes = true; 1174 | break; 1175 | case 12: 1176 | if(m_isnan(*op1) || m_isnan(*op2) || ret < 0) 1177 | realRes = true; 1178 | break; 1179 | case 13: 1180 | if(m_isnan(*op1) || m_isnan(*op2) || ret <= 0) 1181 | realRes = true; 1182 | break; 1183 | case 14: 1184 | if(m_isnan(*op1) || m_isnan(*op2) || ret != 0){ 1185 | realRes = true; 1186 | } 1187 | break; 1188 | case 15: 1189 | realRes = true; 1190 | break; 1191 | } 1192 | return realRes; 1193 | } 1194 | 1195 | 1196 | 1197 | std::string m_get_string_opcode_fpcore(size_t opcode){ 1198 | switch(opcode){ 1199 | case FADD: 1200 | return "+"; 1201 | case FMUL: 1202 | return "*"; 1203 | case FSUB: 1204 | return "-"; 1205 | case FDIV: 1206 | return "/"; 1207 | case CONSTANT: 1208 | return "CONSTANT"; 1209 | case SQRT: 1210 | return "sqrt"; 1211 | case FLOOR: 1212 | return "floor"; 1213 | case TAN: 1214 | return "tan"; 1215 | case SIN: 1216 | return "sin"; 1217 | case COS: 1218 | return "cos"; 1219 | case ATAN: 1220 | return "atan"; 1221 | case ABS: 1222 | return "abs"; 1223 | case LOG: 1224 | return "log"; 1225 | case ASIN: 1226 | return "asin"; 1227 | case EXP: 1228 | return "exp"; 1229 | case POW: 1230 | return "pow"; 1231 | default: 1232 | return "Unknown"; 1233 | } 1234 | } 1235 | std::string m_get_string_opcode(size_t opcode){ 1236 | switch(opcode){ 1237 | case FADD: 1238 | return "FADD"; 1239 | case FMUL: 1240 | return "FMUL"; 1241 | case FSUB: 1242 | return "FSUB"; 1243 | case FDIV: 1244 | return "FDIV"; 1245 | case CONSTANT: 1246 | return "CONSTANT"; 1247 | case SQRT: 1248 | return "SQRT"; 1249 | case FLOOR: 1250 | return "FLOOR"; 1251 | case TAN: 1252 | return "TAN"; 1253 | case SIN: 1254 | return "SIN"; 1255 | case COS: 1256 | return "COS"; 1257 | case ATAN: 1258 | return "ATAN"; 1259 | case ABS: 1260 | return "ABS"; 1261 | case LOG: 1262 | return "LOG"; 1263 | case ASIN: 1264 | return "ASIN"; 1265 | case EXP: 1266 | return "EXP"; 1267 | case POW: 1268 | return "POW"; 1269 | default: 1270 | return "Unknown"; 1271 | } 1272 | } 1273 | 1274 | #ifdef TRACING 1275 | int m_get_depth(temp_entry *current){ 1276 | int depth = 0; 1277 | m_expr.push_back(current); 1278 | int level; 1279 | while(!m_expr.empty()){ 1280 | level = m_expr.size(); 1281 | std::cout<<"\n"; 1282 | while(level > 0){ 1283 | temp_entry *cur = m_expr.front(); 1284 | if(cur == NULL){ 1285 | return depth; 1286 | } 1287 | if(m_lock_key_map[cur->op1_lock] != cur->op1_key ){ 1288 | return depth; 1289 | } 1290 | if(m_lock_key_map[cur->op2_lock] != cur->op2_key){ 1291 | return depth; 1292 | } 1293 | if(cur->lhs != NULL){ 1294 | if(cur->lhs->timestamp < cur->timestamp){ 1295 | m_expr.push_back(cur->lhs); 1296 | } 1297 | } 1298 | if(cur->rhs != NULL){ 1299 | if(cur->rhs->timestamp < cur->timestamp){ 1300 | m_expr.push_back(cur->rhs); 1301 | } 1302 | } 1303 | m_expr.pop_front(); 1304 | level--; 1305 | } 1306 | depth++; 1307 | } 1308 | return depth; 1309 | } 1310 | #endif 1311 | 1312 | extern "C" void fpsan_func_init(long totalArgs) { 1313 | 1314 | #ifdef TRACING 1315 | m_key_stack_top++; 1316 | m_key_counter++; 1317 | m_lock_key_map[m_key_stack_top] = m_key_counter; 1318 | #endif 1319 | 1320 | m_stack_top = m_stack_top + totalArgs; 1321 | } 1322 | 1323 | extern "C" void fpsan_func_exit(long totalArgs) { 1324 | 1325 | #ifdef TRACING 1326 | m_lock_key_map[m_key_stack_top] = 0; 1327 | m_key_stack_top--; 1328 | #endif 1329 | 1330 | m_stack_top = m_stack_top - totalArgs; 1331 | 1332 | 1333 | } 1334 | 1335 | /* Copy the metadata of the return value of the function and insert 1336 | into the shadow stack. The space for the return value is allocated 1337 | by the caller. This happens in the callee. */ 1338 | 1339 | extern "C" void fpsan_set_return(temp_entry* src, size_t totalArgs, double op) { 1340 | 1341 | /* Santosh: revisit this design, make 0 distance from the stack top 1342 | as the return */ 1343 | 1344 | temp_entry *dest = &(m_shadow_stack[m_stack_top - totalArgs]); 1345 | if(src != NULL){ 1346 | m_set_mpfr(&(dest->val), &(src->val)); 1347 | dest->computed = src->computed; 1348 | dest->opcode = src->opcode; 1349 | dest->lineno = src->lineno; 1350 | dest->is_init = true; 1351 | 1352 | #ifdef TRACING 1353 | dest->error = src->error; 1354 | dest->lock = m_key_stack_top; 1355 | dest->key = m_lock_key_map[m_key_stack_top]; 1356 | 1357 | dest->op1_lock = src->op1_lock; 1358 | dest->op1_key = src->op1_key; 1359 | dest->lhs = src->lhs; 1360 | dest->op2_lock = src->op2_lock; 1361 | dest->op2_key = src->op2_key; 1362 | dest->rhs = src->rhs; 1363 | dest->timestamp = src->timestamp; 1364 | 1365 | #endif 1366 | 1367 | } 1368 | else{ 1369 | std::cout<<"__set_return copying src is null:"<<"\n"; 1370 | fpsan_store_tempmeta_dconst(dest, op, 0); 1371 | // m_store_shadow_dconst(dest, op, 0); //when we return tmp 1372 | //we don't need to set metadata as it is null 1373 | } 1374 | /* one of set_return or func_exit is called, so cleanup the 1375 | shadow stack */ 1376 | m_stack_top = m_stack_top - totalArgs; 1377 | 1378 | #ifdef TRACING 1379 | m_lock_key_map[m_key_stack_top] = 0; 1380 | m_key_stack_top--; 1381 | #endif 1382 | 1383 | } 1384 | 1385 | /* Retrieve the metadata for the return value from the shadow 1386 | stack. This happens in the caller. */ 1387 | extern "C" void fpsan_get_return(temp_entry* dest) { 1388 | 1389 | temp_entry *src = &(m_shadow_stack[m_stack_top]); //save return m_stack_top - totalArgs 1390 | m_set_mpfr(&(dest->val), &(src->val)); 1391 | dest->computed = src->computed; 1392 | dest->lineno = src->lineno; 1393 | dest->opcode = src->opcode; 1394 | 1395 | #ifdef TRACING 1396 | dest->lock = m_key_stack_top; 1397 | dest->key = m_lock_key_map[m_key_stack_top]; 1398 | dest->error = src->error; 1399 | dest->timestamp = m_timestamp++; 1400 | 1401 | dest->op1_lock = src->op1_lock; 1402 | dest->op1_key = src->op1_key; 1403 | dest->op2_lock = src->op2_lock; 1404 | dest->op2_key = src->op2_key; 1405 | dest->lhs = src->lhs; 1406 | dest->rhs = src->rhs; 1407 | 1408 | #endif 1409 | 1410 | } 1411 | 1412 | /* The callee retrieves the metadata from the shadow stack */ 1413 | 1414 | extern "C" temp_entry* fpsan_get_arg(size_t argIdx, double op) { 1415 | 1416 | temp_entry *dst = &(m_shadow_stack[m_stack_top-argIdx]); 1417 | 1418 | #ifdef TRACING 1419 | dst->lock = m_key_stack_top; 1420 | dst->key = m_lock_key_map[m_key_stack_top]; 1421 | #endif 1422 | 1423 | if(!dst->is_init){ //caller maybe is not instrumented for set_arg 1424 | fpsan_store_tempmeta_dconst(dst, op, 0); 1425 | //m_store_shadow_dconst(dst, op, 0); 1426 | } 1427 | 1428 | return dst; 1429 | } 1430 | 1431 | extern "C" void fpsan_set_arg_f(size_t argIdx, temp_entry* src, float op) { 1432 | 1433 | temp_entry *dest = &(m_shadow_stack[argIdx+m_stack_top]); 1434 | assert(argIdx < MAX_STACK_SIZE && "Arg index is more than MAX_STACK_SIZE"); 1435 | 1436 | /* Santosh: Check if we will ever have src == NULL with arguments */ 1437 | if(src != NULL){ 1438 | m_set_mpfr(&(dest->val), &(src->val)); 1439 | dest->computed = src->computed; 1440 | dest->opcode = src->opcode; 1441 | dest->lineno = src->lineno; 1442 | dest->is_init = true; 1443 | 1444 | #ifdef TRACING 1445 | dest->lock = m_key_stack_top; 1446 | dest->key = m_lock_key_map[m_key_stack_top]; 1447 | dest->error = src->error; 1448 | 1449 | dest->op1_lock = src->op1_lock; 1450 | dest->op1_key = src->op1_key; 1451 | dest->lhs = src->lhs; 1452 | dest->op2_lock = src->op2_lock; 1453 | dest->op2_key = src->op2_key; 1454 | dest->rhs = src->rhs; 1455 | dest->timestamp = src->timestamp; 1456 | #endif 1457 | } 1458 | else{ 1459 | fpsan_store_tempmeta_fconst(dest, op, 0); 1460 | dest->is_init = true; 1461 | } 1462 | } 1463 | 1464 | extern "C" void fpsan_set_arg_d(size_t argIdx, temp_entry* src, double op) { 1465 | 1466 | temp_entry *dest = &(m_shadow_stack[argIdx+m_stack_top]); 1467 | assert(argIdx < MAX_STACK_SIZE && "Arg index is more than MAX_STACK_SIZE"); 1468 | 1469 | /* Santosh: Check if we will ever have src == NULL with arguments */ 1470 | if(src != NULL){ 1471 | m_set_mpfr(&(dest->val), &(src->val)); 1472 | dest->computed = src->computed; 1473 | dest->lineno = src->lineno; 1474 | dest->opcode = src->opcode; 1475 | dest->is_init = true; 1476 | 1477 | #ifdef TRACING 1478 | dest->lock = m_key_stack_top; 1479 | dest->key = m_lock_key_map[m_key_stack_top]; 1480 | dest->error = src->error; 1481 | 1482 | dest->op1_lock = src->op1_lock; 1483 | dest->op1_key = src->op1_key; 1484 | dest->lhs = src->lhs; 1485 | dest->op2_lock = src->op2_lock; 1486 | dest->op2_key = src->op2_key; 1487 | dest->rhs = src->rhs; 1488 | dest->timestamp = src->timestamp; 1489 | #endif 1490 | } 1491 | else{ 1492 | fpsan_store_tempmeta_fconst(dest, op, 0); 1493 | dest->is_init = true; 1494 | } 1495 | } 1496 | 1497 | unsigned long m_ulpd(double x, double y) { 1498 | if (x == 0) 1499 | x = 0; // -0 == 0 1500 | if (y == 0) 1501 | y = 0; // -0 == 0 1502 | 1503 | /* if (x != x && y != y) return 0; */ 1504 | if (x != x) 1505 | return ULLONG_MAX - 1; // Maximum error 1506 | if (y != y) 1507 | return ULLONG_MAX - 1; // Maximum error 1508 | 1509 | long long xx = *((long long *)&x); 1510 | xx = xx < 0 ? LLONG_MIN - xx : xx; 1511 | 1512 | long long yy = *((long long *)&y); 1513 | yy = yy < 0 ? LLONG_MIN - yy : yy; 1514 | return xx >= yy ? xx - yy : yy - xx; 1515 | } 1516 | 1517 | 1518 | extern "C" void fpsan_finish() { 1519 | 1520 | if (!m_init_flag) { 1521 | return; 1522 | } 1523 | fprintf(m_errfile, "Error above %d bits found %zd\n", ERRORTHRESHOLD, errorCount); 1524 | fprintf(m_errfile, "Total NaN found %zd\n", nanCount); 1525 | fprintf(m_errfile, "Total Inf found %zd\n", infCount); 1526 | fprintf(m_errfile, "Total branch flips found %zd\n", flipsCount); 1527 | fprintf(m_errfile, "Total catastrophic cancellation found %zd\n", ccCount); 1528 | 1529 | fclose(m_errfile); 1530 | fclose(m_brfile); 1531 | } 1532 | 1533 | int m_update_error(temp_entry *real, double computedVal){ 1534 | double shadowRounded = m_get_double(real->val); 1535 | unsigned long ulpsError = m_ulpd(shadowRounded, computedVal); 1536 | 1537 | double bitsError = log2(ulpsError + 1); 1538 | 1539 | if(bitsError > ERRORTHRESHOLD) 1540 | errorCount++; 1541 | 1542 | if (debugerror){ 1543 | std::cout<<"\nThe shadow value is "; 1544 | m_print_real(real->val); 1545 | if (computedVal != computedVal){ 1546 | std::cout<<", but NaN was computed.\n"; 1547 | } else { 1548 | std::cout<<", but "; 1549 | printf("%e", computedVal); 1550 | std::cout<<" was computed.\n"; 1551 | std::cout<<"m_update_error: computedVal:"<val); 1566 | unsigned long ulpsError = m_ulpd(shadowRounded, computed); 1567 | 1568 | printf("getError real:"); 1569 | m_print_real(dest->val); 1570 | printf("\n"); 1571 | printf("getError computed: %e", computed); 1572 | printf("\n"); 1573 | double bitsError = log2(ulpsError + 1); 1574 | fprintf(m_errfile, "computed:%e real:%e Error: %lu ulps (%lf bits)\n", computed, shadowRounded, ulpsError, bitsError); 1575 | } 1576 | 1577 | 1578 | /* Math library functions */ 1579 | extern "C" void fpsan_mpfr_sqrt(temp_entry* op1, 1580 | double op1d, 1581 | temp_entry* res, 1582 | double computedRes, 1583 | unsigned long long int instId, 1584 | bool debugInfoAvail, 1585 | unsigned int linenumber, 1586 | unsigned int colnumber){ 1587 | 1588 | handle_math_d(SQRT, op1d, op1, computedRes, res, linenumber); 1589 | 1590 | } 1591 | 1592 | extern "C" void fpsan_mpfr_sqrtf(temp_entry* op1, 1593 | float op1d, 1594 | temp_entry* res, 1595 | float computedRes, 1596 | unsigned long long int instId, 1597 | bool debugInfoAvail, 1598 | unsigned int linenumber, 1599 | unsigned int colnumber){ 1600 | 1601 | handle_math_d(SQRT, op1d, op1, computedRes, res, linenumber); 1602 | 1603 | } 1604 | 1605 | extern "C" void fpsan_mpfr_floor(temp_entry* op1, 1606 | double op1d, 1607 | temp_entry* res, 1608 | double computedRes, 1609 | unsigned long long int instId, 1610 | bool debugInfoAvail, 1611 | unsigned int linenumber, 1612 | unsigned int colnumber){ 1613 | 1614 | handle_math_d(FLOOR, op1d, op1, computedRes, res, linenumber); 1615 | 1616 | } 1617 | 1618 | extern "C" void fpsan_mpfr_llvm_f(temp_entry* op1, 1619 | float op1d, 1620 | temp_entry* res, 1621 | float computedRes, 1622 | unsigned long long int instId, 1623 | bool debugInfoAvail, 1624 | unsigned int linenumber, 1625 | unsigned int colnumber){ 1626 | 1627 | handle_math_d(FLOOR, op1d, op1, computedRes, res, linenumber); 1628 | 1629 | } 1630 | 1631 | extern "C" void fpsan_mpfr_tanh(temp_entry* op1, 1632 | double op1d, 1633 | temp_entry* res, 1634 | double computedRes, 1635 | unsigned long long int instId, 1636 | bool debugInfoAvail, 1637 | unsigned int linenumber, 1638 | unsigned int colnumber){ 1639 | 1640 | handle_math_d(TANH, op1d, op1, computedRes, res, linenumber); 1641 | 1642 | } 1643 | 1644 | extern "C" void fpsan_mpfr_tan(temp_entry* op1, 1645 | double op1d, 1646 | temp_entry* res, 1647 | double computedRes, 1648 | unsigned long long int instId, 1649 | bool debugInfoAvail, 1650 | unsigned int linenumber, 1651 | unsigned int colnumber){ 1652 | 1653 | handle_math_d(TAN, op1d, op1, computedRes, res, linenumber); 1654 | 1655 | } 1656 | 1657 | extern "C" void fpsan_mpfr_acos(temp_entry* op1, 1658 | double op1d, 1659 | temp_entry* res, 1660 | double computedRes, 1661 | unsigned long long int instId, 1662 | bool debugInfoAvail, 1663 | unsigned int linenumber, 1664 | unsigned int colnumber){ 1665 | 1666 | handle_math_d(ACOS, op1d, op1, computedRes, res, linenumber); 1667 | } 1668 | 1669 | extern "C" void fpsan_mpfr_cosh(temp_entry* op1, 1670 | double op1d, 1671 | temp_entry* res, 1672 | double computedRes, 1673 | unsigned long long int instId, 1674 | bool debugInfoAvail, 1675 | unsigned int linenumber, 1676 | unsigned int colnumber){ 1677 | 1678 | handle_math_d(COSH, op1d, op1, computedRes, res, linenumber); 1679 | 1680 | } 1681 | 1682 | extern "C" void fpsan_mpfr_cos(temp_entry* op1, 1683 | double op1d, 1684 | temp_entry* res, 1685 | double computedRes, 1686 | unsigned long long int instId, 1687 | bool debugInfoAvail, 1688 | unsigned int linenumber, 1689 | unsigned int colnumber){ 1690 | 1691 | handle_math_d(COS, op1d, op1, computedRes, res, linenumber); 1692 | 1693 | } 1694 | 1695 | extern "C" void fpsan_mpfr_llvm_cos_f64(temp_entry* op1, 1696 | double op1d, 1697 | temp_entry* res, 1698 | double computedRes, 1699 | unsigned long long int instId, 1700 | bool debugInfoAvail, 1701 | unsigned int linenumber, 1702 | unsigned int colnumber){ 1703 | 1704 | handle_math_d(COS, op1d, op1, computedRes, res, linenumber); 1705 | 1706 | } 1707 | 1708 | extern "C" void fpsan_mpfr_atan(temp_entry* op1, 1709 | double op1d, 1710 | temp_entry* res, 1711 | double computedRes, 1712 | unsigned long long int instId, 1713 | bool debugInfoAvail, 1714 | unsigned int linenumber, 1715 | unsigned int colnumber){ 1716 | 1717 | handle_math_d(ATAN, op1d, op1, computedRes, res, linenumber); 1718 | } 1719 | 1720 | extern "C" void fpsan_mpfr_llvm_ceil(temp_entry* op1, 1721 | double op1d, 1722 | temp_entry* res, 1723 | double computedRes, 1724 | unsigned long long int instId, 1725 | bool debugInfoAvail, 1726 | unsigned int linenumber, 1727 | unsigned int colnumber){ 1728 | 1729 | handle_math_d(CEIL, op1d, op1, computedRes, res, linenumber); 1730 | 1731 | } 1732 | 1733 | extern "C" void fpsan_mpfr_llvm_floor(temp_entry* op1Idx, 1734 | double op1d, 1735 | temp_entry* res, 1736 | double computedRes, 1737 | unsigned long long int instId, 1738 | bool debugInfoAvail, 1739 | unsigned int linenumber, 1740 | unsigned int colnumber){ 1741 | 1742 | handle_math_d(FLOOR, op1d, op1Idx, computedRes, res, linenumber); 1743 | 1744 | } 1745 | 1746 | extern "C" void fpsan_mpfr_llvm_floor_f(temp_entry* op1Idx, 1747 | double op1d, 1748 | temp_entry* res, 1749 | double computedRes, 1750 | unsigned long long int instId, 1751 | bool debugInfoAvail, 1752 | unsigned int linenumber, 1753 | unsigned int colnumber){ 1754 | 1755 | handle_math_d(FLOOR, op1d, op1Idx, computedRes, res, linenumber); 1756 | 1757 | } 1758 | extern "C" void fpsan_mpfr_exp(temp_entry* op1Idx, 1759 | double op1d, 1760 | temp_entry* res, 1761 | double computedRes, 1762 | unsigned long long int instId, 1763 | bool debugInfoAvail, 1764 | unsigned int linenumber, 1765 | unsigned int colnumber){ 1766 | handle_math_d(EXP, op1d, op1Idx, computedRes, res, linenumber); 1767 | 1768 | } 1769 | 1770 | extern "C" void fpsan_mpfr_GSL_MIN_DBL2(temp_entry* op1Idx, double op1d, 1771 | temp_entry* op2Idx, double op2d, 1772 | temp_entry* res, double computedRes, 1773 | unsigned long long int instId, 1774 | bool debugInfoAvail, 1775 | unsigned int linenumber, 1776 | unsigned int colnumber){ 1777 | 1778 | mpfr_min(res->val, op1Idx->val, op2Idx->val, MPFR_RNDN); 1779 | res->lineno = linenumber; 1780 | res->opcode = MIN; 1781 | res->computed = computedRes; 1782 | 1783 | #ifdef TRACING 1784 | int bitsError = m_update_error(res, computedRes); 1785 | res->op1_lock = op1Idx->lock; 1786 | res->op1_key = m_lock_key_map[op1Idx->lock]; 1787 | res->op2_lock = op2Idx->lock; 1788 | res->op2_key = m_lock_key_map[op2Idx->lock]; 1789 | res->lock = m_key_stack_top; 1790 | res->key = m_lock_key_map[m_key_stack_top]; 1791 | res->lhs = op1Idx; 1792 | res->rhs = op2Idx; 1793 | res->timestamp = m_timestamp++; 1794 | res->error = bitsError; 1795 | #endif 1796 | 1797 | } 1798 | 1799 | 1800 | extern "C" void fpsan_mpfr_GSL_MAX_DBL2(temp_entry* op1Idx, double op1d, 1801 | temp_entry* op2Idx, double op2d, 1802 | temp_entry* res, double computedRes, 1803 | unsigned long long int instId, 1804 | bool debugInfoAvail, 1805 | unsigned int linenumber, 1806 | unsigned int colnumber){ 1807 | 1808 | mpfr_max(res->val, op1Idx->val, op2Idx->val, MPFR_RNDN); 1809 | res->opcode = MAX; 1810 | res->computed = computedRes; 1811 | res->lineno = linenumber; 1812 | 1813 | #ifdef TRACING 1814 | 1815 | int bitsError = m_update_error(res, computedRes); 1816 | res->op1_lock = op1Idx->lock; 1817 | res->op1_key = m_lock_key_map[op1Idx->lock]; 1818 | res->op2_lock = op2Idx->lock; 1819 | res->op2_key = m_lock_key_map[op2Idx->lock]; 1820 | res->lock = m_key_stack_top; 1821 | res->key = m_lock_key_map[m_key_stack_top]; 1822 | res->lhs = op1Idx; 1823 | res->rhs = op2Idx; 1824 | res->timestamp = m_timestamp++; 1825 | res->error = bitsError; 1826 | #endif 1827 | 1828 | } 1829 | 1830 | extern "C" void fpsan_mpfr_ldexp2(temp_entry* op1Idx, double op1d, 1831 | int op2d, 1832 | temp_entry* res, double computedRes, 1833 | unsigned long long int instId, 1834 | bool debugInfoAvail, 1835 | unsigned int linenumber, 1836 | unsigned int colnumber){ 1837 | 1838 | //op1*2^(op2) 1839 | mpfr_t exp; 1840 | mpfr_init2(exp, m_precision); 1841 | mpfr_set_si(exp, op2d, MPFR_RNDN); 1842 | mpfr_exp2(res->val, exp, MPFR_RNDN); 1843 | mpfr_mul(res->val, op1Idx->val, res->val, MPFR_RNDN); 1844 | 1845 | mpfr_clear(exp); 1846 | 1847 | res->lineno = linenumber; 1848 | res->opcode = LDEXP; 1849 | res->computed = computedRes; 1850 | 1851 | #ifdef TRACING 1852 | int bitsError = m_update_error(res, computedRes); 1853 | res->op1_lock = op1Idx->lock; 1854 | res->op1_key = m_lock_key_map[op1Idx->lock]; 1855 | res->op2_lock = 0; 1856 | res->op2_key = 0; 1857 | res->lock = m_key_stack_top; 1858 | res->key = m_lock_key_map[m_key_stack_top]; 1859 | res->lhs = op1Idx; 1860 | res->rhs = NULL; 1861 | res->timestamp = m_timestamp++; 1862 | res->error = bitsError; 1863 | #endif 1864 | 1865 | } 1866 | 1867 | extern "C" void fpsan_mpfr_fmod2(temp_entry* op1Idx, double op1d, 1868 | temp_entry* op2Idx, double op2d, 1869 | temp_entry* res, double computedRes, 1870 | unsigned long long int instId, 1871 | bool debugInfoAvail, 1872 | unsigned int linenumber, 1873 | unsigned int colnumber){ 1874 | 1875 | mpfr_fmod(res->val, op1Idx->val, op2Idx->val, MPFR_RNDN); 1876 | res->opcode = FMOD; 1877 | res->computed = computedRes; 1878 | res->lineno = linenumber; 1879 | 1880 | #ifdef TRACING 1881 | int bitsError = m_update_error(res, computedRes); 1882 | res->op1_lock = op1Idx->lock; 1883 | res->op1_key = m_lock_key_map[op1Idx->lock]; 1884 | res->op2_lock = op2Idx->lock; 1885 | res->op2_key = m_lock_key_map[op2Idx->lock]; 1886 | res->lock = m_key_stack_top; 1887 | res->key = m_lock_key_map[m_key_stack_top]; 1888 | res->lhs = op1Idx; 1889 | res->rhs = op2Idx; 1890 | res->timestamp = m_timestamp++; 1891 | res->error = bitsError; 1892 | #endif 1893 | 1894 | } 1895 | 1896 | extern "C" void fpsan_mpfr_atan22(temp_entry* op1, double op1d, 1897 | temp_entry* op2, double op2d, 1898 | temp_entry* res, double computedRes, 1899 | unsigned long long int instId, 1900 | bool debugInfoAvail, 1901 | unsigned int linenumber, 1902 | unsigned int colnumber){ 1903 | 1904 | mpfr_atan2(res->val, op1->val, op2->val, MPFR_RNDN); 1905 | res->opcode = ATAN2; 1906 | res->computed = computedRes; 1907 | res->lineno = linenumber; 1908 | 1909 | #ifdef TRACING 1910 | 1911 | int bitsError = m_update_error(res, computedRes); 1912 | res->op1_lock = op1->lock; 1913 | res->op1_key = m_lock_key_map[op1->lock]; 1914 | res->op2_lock = op2->lock; 1915 | res->op2_key = m_lock_key_map[op2->lock]; 1916 | res->lock = m_key_stack_top; 1917 | res->key = m_lock_key_map[m_key_stack_top]; 1918 | res->lhs = op1; 1919 | res->rhs = op2; 1920 | res->timestamp = m_timestamp++; 1921 | res->error = bitsError; 1922 | 1923 | #endif 1924 | } 1925 | 1926 | extern "C" void fpsan_mpfr_hypot2(temp_entry* op1, double op1d, 1927 | temp_entry* op2, double op2d, 1928 | temp_entry* res, double computedRes, 1929 | unsigned long long int instId, 1930 | bool debugInfoAvail, 1931 | unsigned int linenumber, 1932 | unsigned int colnumber){ 1933 | 1934 | mpfr_hypot(res->val, op1->val, op2->val, MPFR_RNDN); 1935 | res->opcode = HYPOT; 1936 | res->computed = computedRes; 1937 | res->lineno = linenumber; 1938 | 1939 | #ifdef TRACING 1940 | 1941 | int bitsError = m_update_error(res, computedRes); 1942 | res->op1_lock = op1->lock; 1943 | res->op1_key = m_lock_key_map[op1->lock]; 1944 | res->op2_lock = op2->lock; 1945 | res->op2_key = m_lock_key_map[op2->lock]; 1946 | res->lock = m_key_stack_top; 1947 | res->key = m_lock_key_map[m_key_stack_top]; 1948 | res->lhs = op1; 1949 | res->rhs = op2; 1950 | res->timestamp = m_timestamp++; 1951 | res->error = bitsError; 1952 | #endif 1953 | 1954 | } 1955 | 1956 | extern "C" void fpsan_mpfr_pow2(temp_entry* op1, double op1d, 1957 | temp_entry* op2, double op2d, 1958 | temp_entry* res, double computedRes, 1959 | unsigned long long int instId, 1960 | bool debugInfoAvail, 1961 | unsigned int linenumber, 1962 | unsigned int colnumber){ 1963 | 1964 | mpfr_pow(res->val, op1->val, op2->val, MPFR_RNDN); 1965 | res->opcode = POW; 1966 | res->computed = computedRes; 1967 | res->lineno = linenumber; 1968 | 1969 | #ifdef TRACING 1970 | int bitsError = m_update_error(res, computedRes); 1971 | res->op1_lock = op1->lock; 1972 | res->op1_key = m_lock_key_map[op1->lock]; 1973 | res->op2_lock = op2->lock; 1974 | res->op2_key = m_lock_key_map[op2->lock]; 1975 | res->lock = m_key_stack_top; 1976 | res->key = m_lock_key_map[m_key_stack_top]; 1977 | res->lhs = op1; 1978 | res->rhs = op2; 1979 | 1980 | res->timestamp = m_timestamp++; 1981 | res->error = bitsError; 1982 | #endif 1983 | 1984 | } 1985 | 1986 | extern "C" void fpsan_mpfr_llvm_fabs(temp_entry* op1, 1987 | double op1d, 1988 | temp_entry* res, 1989 | double computedRes, 1990 | unsigned long long int instId, 1991 | bool debugInfoAvail, 1992 | unsigned int linenumber, 1993 | unsigned int colnumber){ 1994 | 1995 | handle_math_d(ABS, op1d, op1, computedRes, res, linenumber); 1996 | 1997 | } 1998 | 1999 | extern "C" void fpsan_mpfr_abs(temp_entry* op1, temp_entry* res, 2000 | double op1d, double computedRes, 2001 | unsigned long long int instId, 2002 | bool debugInfoAvail, unsigned int linenumber, 2003 | unsigned int colnumber){ 2004 | 2005 | 2006 | handle_math_d(ABS, op1d, op1, computedRes, res, linenumber); 2007 | 2008 | } 2009 | 2010 | extern "C" void fpsan_mpfr_log10(temp_entry* op1, temp_entry* res, 2011 | double op1d, double computedRes, 2012 | unsigned long long int instId, 2013 | bool debugInfoAvail, unsigned int linenumber, 2014 | unsigned int colnumber){ 2015 | 2016 | handle_math_d(LOG10, op1d, op1, computedRes, res, linenumber); 2017 | 2018 | } 2019 | 2020 | extern "C" void fpsan_mpfr_log(temp_entry* op1, temp_entry* res, 2021 | double op1d, double computedRes, 2022 | unsigned long long int instId, 2023 | bool debugInfoAvail, unsigned int linenumber, 2024 | unsigned int colnumber){ 2025 | 2026 | handle_math_d(LOG, op1d, op1, computedRes, res, linenumber); 2027 | 2028 | } 2029 | 2030 | extern "C" void fpsan_mpfr_sinh(temp_entry* op1, temp_entry* res, 2031 | double op1d, double computedRes, 2032 | unsigned long long int instId, 2033 | bool debugInfoAvail, unsigned int linenumber, 2034 | unsigned int colnumber){ 2035 | 2036 | handle_math_d(SIN, op1d, op1, computedRes, res, linenumber); 2037 | 2038 | } 2039 | 2040 | extern "C" void fpsan_mpfr_sin(temp_entry* op1, temp_entry* res, 2041 | double op1d, double computedRes, 2042 | unsigned long long int instId, 2043 | bool debugInfoAvail, unsigned int linenumber, 2044 | unsigned int colnumber){ 2045 | handle_math_d(SIN, op1d, op1, computedRes, res, linenumber); 2046 | 2047 | } 2048 | 2049 | extern "C" void fpsan_mpfr_llvm_sin_f64(temp_entry* op1, temp_entry* res, 2050 | double op1d, double computedRes, 2051 | unsigned long long int instId, 2052 | bool debugInfoAvail, unsigned int linenumber, 2053 | unsigned int colnumber){ 2054 | handle_math_d(SIN, op1d, op1, computedRes, res, linenumber); 2055 | 2056 | } 2057 | 2058 | extern "C" void fpsan_mpfr_asin(temp_entry* op1, 2059 | temp_entry* res, 2060 | double op1d, 2061 | double computedRes, 2062 | unsigned long long int instId, 2063 | bool debugInfoAvail, 2064 | unsigned int linenumber, 2065 | unsigned int colnumber){ 2066 | handle_math_d(ASIN, op1d, op1, computedRes, res, linenumber); 2067 | } 2068 | -------------------------------------------------------------------------------- /fpsan_runtime/handleReal.h: -------------------------------------------------------------------------------- 1 | #ifndef __FPSAN_RUNTIME_H__ 2 | #define __FPSAN_RUNTIME_H__ 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 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | FILE * m_fpcore; 34 | FILE * m_errfile; 35 | FILE * m_brfile; 36 | 37 | 38 | enum fp_op{FADD, FSUB, FMUL, FDIV, CONSTANT, SQRT, CEIL, FLOOR, TAN, SIN, 39 | COS, ATAN, ABS, LOG, LOG10, ASIN, EXP, POW, MIN, MAX, LDEXP, FMOD, ATAN2, 40 | HYPOT, COSH, SINH, TANH, ACOS, UNKNOWN}; 41 | 42 | struct error_info { 43 | double error; 44 | unsigned int cbad; 45 | unsigned int regime; 46 | unsigned int linenumber; 47 | unsigned int colnumber; 48 | bool debugInfoAvail; 49 | }; 50 | 51 | /* smem_entry: metadata maintained with each shadow memory location. 52 | * val : mpfr value for the shadow execution 53 | * computed: double value 54 | * lineno: line number in the source file 55 | * is_init: is the MPFR initialized 56 | * opcode: opcode of the operation that created the result 57 | 58 | * error : number of bits in error. Why is it here? (TRACING) 59 | * lock: CETS style metadata for validity of the temporary metadata pointer (TRACING) 60 | * key: CETS style metadata for validity of the temporary metadata pointer (TRACING) 61 | * tmp_ptr: Pointer to the metadata of the temporary (TRACING) 62 | */ 63 | struct smem_entry{ 64 | 65 | mpfr_t val; 66 | double computed; 67 | unsigned int lineno; 68 | enum fp_op opcode; 69 | bool is_init; 70 | 71 | #ifdef TRACING 72 | int error; 73 | unsigned int lock; 74 | unsigned int key; 75 | struct temp_entry *tmp_ptr; 76 | #endif 77 | 78 | }; 79 | 80 | struct temp_entry{ 81 | 82 | mpfr_t val; 83 | double computed; 84 | unsigned int lineno; 85 | enum fp_op opcode; 86 | bool is_init; 87 | 88 | #ifdef TRACING 89 | int error; 90 | size_t lock; 91 | size_t key; 92 | 93 | size_t op1_lock; 94 | size_t op1_key; 95 | struct temp_entry* lhs; 96 | 97 | size_t op2_lock; 98 | size_t op2_key; 99 | struct temp_entry* rhs; 100 | size_t timestamp; 101 | #endif 102 | 103 | 104 | }; 105 | 106 | #define MMAP_FLAGS (MAP_PRIVATE| MAP_ANONYMOUS| MAP_NORESERVE) 107 | #define MAX_STACK_SIZE 500 108 | #define MAX_SIZE 1000 109 | 110 | //#define METADATA_AS_TRIE 0 111 | 112 | /* Assumption: float types are 4-byte aligned. */ 113 | 114 | #ifdef METADATA_AS_TRIE 115 | 116 | const size_t SS_PRIMARY_TABLE_ENTRIES = ((size_t) 4194304);//2^22 117 | const size_t SS_SEC_TABLE_ENTRIES = ((size_t) 16*(size_t) 1024 * (size_t) 1024); // 2^24 118 | const size_t PRIMARY_INDEX_BITS = 22; 119 | const size_t SECONDARY_INDEX_BITS = 24; 120 | const size_t SECONDARY_MASK = 0xffffff; 121 | 122 | smem_entry ** m_shadow_memory; 123 | 124 | #else 125 | /* 32 million entries in the hash table */ 126 | const size_t HASH_TABLE_ENTRIES = ((size_t) 32 * (size_t) 1024 * (size_t) 1024); 127 | 128 | smem_entry * m_shadow_memory; 129 | 130 | #endif 131 | 132 | #define debug 0 133 | #define debugtrace 0 134 | #define debugerror 0 135 | #define ERRORTHRESHOLD 50 136 | 137 | 138 | # if !defined(PREC_128) && !defined(PREC_256) && !defined(PREC_512) && !defined(PREC_1024) 139 | # define PREC_512 140 | # endif 141 | 142 | # if !defined(PRECISION) 143 | # ifdef PREC_128 144 | # define PRECISION 128 145 | # endif 146 | # ifdef PREC_256 147 | # define PRECISION 256 148 | # endif 149 | # ifdef PREC_512 150 | # define PRECISION 512 151 | # endif 152 | # ifdef PREC_1024 153 | # define PRECISION 1024 154 | # endif 155 | #endif 156 | 157 | #ifdef TRACING 158 | size_t * m_lock_key_map; 159 | #endif 160 | 161 | temp_entry * m_shadow_stack; 162 | 163 | 164 | int m_prec_bits_f = 0; 165 | int m_prec_bits_d = 0; 166 | size_t m_precision = PRECISION; 167 | 168 | size_t m_stack_top = 0; 169 | 170 | #ifdef TRACING 171 | size_t m_timestamp = 0; 172 | size_t m_key_stack_top = 0; 173 | size_t m_key_counter = 0; 174 | #endif 175 | 176 | bool m_init_flag = false; 177 | size_t varCount = 0; 178 | size_t infCount = 0; 179 | size_t nanCount = 0; 180 | size_t errorCount = 0; 181 | size_t flipsCount = 0; 182 | size_t ccCount = 0; 183 | 184 | std::map m_inst_error_map; 185 | std::map m_var_map; 186 | 187 | std::string varString; 188 | std::list m_expr; 189 | std::string m_get_string_opcode(size_t); 190 | std::string m_get_string_opcode_fpcore(size_t); 191 | unsigned long m_ulpd(double x, double y); 192 | unsigned long m_ulpf(float x, float y); 193 | int m_update_error(temp_entry *mpfr_val, double computedVal); 194 | void m_print_error(size_t opcode, 195 | temp_entry * real, 196 | double d_value, 197 | unsigned int cbad, 198 | unsigned long long int instId, 199 | bool debugInfoAvail, 200 | unsigned int linenumber, 201 | unsigned int colnumber); 202 | void m_print_real(mpfr_t); 203 | void m_print_trace (void); 204 | int m_isnan(mpfr_t real); 205 | int m_get_depth(temp_entry*); 206 | void m_compute(fp_op , double, temp_entry *, double, 207 | temp_entry *, double, temp_entry *, size_t); 208 | 209 | void m_store_shadow_dconst(smem_entry *, double , unsigned int); 210 | void m_store_shadow_fconst(smem_entry *, float , unsigned int); 211 | bool m_check_branch(mpfr_t*, mpfr_t*, size_t); 212 | #endif 213 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import shutil 4 | import subprocess 5 | 6 | def PrintFound() : 7 | print(u"\u001b[1mFOUND\u001b[0m ", end="") 8 | def PrintExpected() : 9 | print(u"(\u001b[32mexpected\u001b[0m)") 10 | def PrintUnexpected() : 11 | print(u"(\u001b[31munexpected\u001b[0m)") 12 | 13 | objDir = "correctness_obj" 14 | commonFilesPath = "makefiles" 15 | commonFilesInCorrectness = ["mathFunc.txt", "Makefile"] 16 | totBenchmarks = 0 17 | totCataCancelCount = 0 18 | totBranchFlipCount = 0 19 | totCastErrorCount = 0 20 | totNaNErrorCount = 0 21 | totInfCount = 0 22 | unexpectedCount = 0 23 | 24 | correctnessPath = "src" 25 | if len(sys.argv) == 2 : 26 | correctnessPath = str(sys.argv[1]) 27 | 28 | # Create a separate obj folder to execute correctness test 29 | if not os.path.exists(objDir) : 30 | os.makedirs(objDir) 31 | 32 | for path, dirs, files in os.walk(correctnessPath) : 33 | for filename in files: 34 | if filename.endswith(".c") : 35 | totBenchmarks = totBenchmarks + 1 36 | fileBaseName = os.path.splitext(os.path.basename(filename))[0] 37 | print("Running test: " + fileBaseName) 38 | # Create a directory with the filename in correctness_obj 39 | newDir = os.path.join(objDir, fileBaseName) 40 | expectedPath = os.path.join("correctness_test_expected", fileBaseName) 41 | if not os.path.exists(newDir) : 42 | os.makedirs(newDir) 43 | 44 | # copy the c file to the new directory 45 | shutil.copyfile(os.path.join(path, filename), os.path.join(newDir, filename)) 46 | 47 | for commonFiles in commonFilesInCorrectness : 48 | shutil.copyfile(os.path.join(commonFilesPath, commonFiles), os.path.join(newDir, commonFiles)) 49 | 50 | proc = subprocess.Popen(["make"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=newDir) 51 | proc.communicate() 52 | proc = subprocess.Popen(["./" + fileBaseName + ".o"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=newDir) 53 | proc.communicate() 54 | 55 | errorLog = open(os.path.join(newDir, "error.log"), "r") 56 | logContent = errorLog.readlines() 57 | expectedExists = False 58 | if os.path.exists(expectedPath): 59 | expectedLog = open(os.path.join(expectedPath, "error.log"), "r") 60 | expectedContent = expectedLog.readlines() 61 | expectedExists = True 62 | 63 | # Did we catch NaN as expected? 64 | foundNaNCount = int(logContent[1].split()[3]) 65 | print("\tNaN result: ", end="") 66 | if foundNaNCount > 0: 67 | totNaNErrorCount = totNaNErrorCount + 1 68 | PrintFound() 69 | else : 70 | print("NOT found ", end="") 71 | if expectedExists : 72 | expectedNaRCount = int(expectedContent[1].split()[3]) 73 | if foundNaNCount == expectedNaRCount: 74 | PrintExpected() 75 | else : 76 | PrintUnexpected() 77 | else : 78 | print() 79 | 80 | # Did we catch catastrophic cancellation as expected? 81 | foundCataCancelCount = int(logContent[4].split()[4]) 82 | print("\tCatastrophic Cancellation: ", end="") 83 | if foundCataCancelCount > 0 : 84 | totCataCancelCount = totCataCancelCount + 1 85 | PrintFound() 86 | else : 87 | print("NOT found ", end="") 88 | if expectedExists : 89 | expectedCataCancelCount = int(expectedContent[4].split()[4]) 90 | if foundCataCancelCount == expectedCataCancelCount : 91 | PrintExpected() 92 | else : 93 | PrintUnexpected() 94 | else : 95 | print() 96 | # Did we catch Inf as expected? 97 | foundInfCount = int(logContent[2].split()[3]) 98 | print("\tInf: ", end="") 99 | if foundInfCount > 0: 100 | totInfCount = totInfCount + 1 101 | PrintFound() 102 | else : 103 | print("NOT found ", end="") 104 | if expectedExists : 105 | expectedInfCount = int(expectedContent[2].split()[3]) 106 | if foundInfCount == expectedInfCount: 107 | PrintExpected() 108 | else : 109 | PrintUnexpected() 110 | unexpectedCount = unexpectedCount + 1 111 | else : 112 | print() 113 | 114 | # Did we catch branch flip as expected? 115 | foundBrFlipCount = int(logContent[3].split()[4]) 116 | print("\tBranch Flip: ", end="") 117 | if foundBrFlipCount > 0: 118 | totBranchFlipCount = totBranchFlipCount + 1 119 | PrintFound() 120 | else : 121 | print("NOT found ", end="") 122 | if expectedExists : 123 | expectedBrFlipCount = int(expectedContent[3].split()[4]) 124 | if foundBrFlipCount == expectedBrFlipCount: 125 | PrintExpected() 126 | else : 127 | PrintUnexpected() 128 | unexpectedCount = unexpectedCount + 1 129 | else : 130 | print() 131 | 132 | errorLog.close() 133 | if expectedExists : 134 | expectedLog.close() 135 | 136 | print("Total number of benchmarks: " + str(totBenchmarks), end="") 137 | if (totBenchmarks == 42) : 138 | PrintExpected() 139 | else : 140 | PrintUnexpected() 141 | print("Number of benchmarks with catastrophic cancellation error: " + str(totCataCancelCount), end="") 142 | if (totCataCancelCount == 15) : 143 | PrintExpected() 144 | else : 145 | PrintUnexpected() 146 | print("Number of benchmarks with NaN computation: " + str(totNaNErrorCount), end="") 147 | if (totNaNErrorCount == 0) : 148 | PrintExpected() 149 | else : 150 | PrintUnexpected() 151 | print("Number of benchmarks with Inf computation: " + str(totInfCount), end="") 152 | if (totInfCount == 2) : 153 | PrintExpected() 154 | else : 155 | PrintUnexpected() 156 | print("Number of benchmarks with branch flip: " + str(totBranchFlipCount), end="") 157 | if (totBranchFlipCount == 5) : 158 | PrintExpected() 159 | else : 160 | PrintUnexpected() 161 | print("Number of benchmarks with integer conversion error: " + str(totCastErrorCount), end="") 162 | if (totCastErrorCount == 0) : 163 | PrintExpected() 164 | else : 165 | PrintUnexpected() 166 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/ContinuedFraction1/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 4 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/MindlessG/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 29995 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 1 5 | Total catastrophic cancellation found 19984 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/ParallelResistance/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 2 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/SimpsonsRule/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 40000002 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/SinTaylorExpansion/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/cc/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/compare-zero-self/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/cordic_cos/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 29 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 19 5 | Total catastrophic cancellation found 37 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/cordic_sin/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 29 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 19 5 | Total catastrophic cancellation found 37 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/diff-roots-simple/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 1 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/diff-roots/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 23 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 23 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/diff-simple/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 1 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/dotproduct1/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/dotproduct2/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/exact-ranges/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 2 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 2 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/gromacs-bondfree-580/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 14 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/gsl-modpi/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 1 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/indirect/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/mini/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/multi-args/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 1 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/naturalnumber/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 1 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/newtonraphson/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/newtonraphsonsqrt/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 4 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 3 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/onthefly/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 6 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/redir/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/rootfinding1/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/rootfinding2/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/same-small/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/simpl-swallow-testa/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/simpl-swallow-testb/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 1 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/simpl-swallow-testc/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 1 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/simpl-swallow-testd/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/simple-negate/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 1 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/small/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/some-trig/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 4 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 1 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/sqrtf/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/sum-50/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 1 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/sum-500/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/tiny/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/var-test-2/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/correctness_test_expected/var-test/error.log: -------------------------------------------------------------------------------- 1 | Error above 50 bits found 0 2 | Total NaN found 0 3 | Total Inf found 0 4 | Total branch flips found 0 5 | Total catastrophic cancellation found 0 6 | -------------------------------------------------------------------------------- /fpsanitizer_test/makefiles/Makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS=-O1 -fno-slp-vectorize -std=c11 -L$(FPROOT)/obj -lfpsanitizer -lmpfr -lm -pthread -ltbb -lstdc++ 2 | CFLAGS=-O0 -fno-slp-vectorize -g -std=c11 -L$(FPSAN_HOME)/fpsan_runtime/obj -lfpsanitizer -lmpfr -lm -lstdc++ 3 | CAMLFLAGs= 4 | CSRC = $(wildcard *.c) 5 | COUT = $(patsubst %.c,%.o,$(CSRC)) 6 | 7 | CC = clang -pg -Xclang -load -Xclang $(FPSAN_HOME)/fpsan_pass/build/FPSan/libFPSanitizer.so 8 | 9 | all: $(COUT) $(CAMLOUT) 10 | 11 | %.o: %.c 12 | $(CC) -o $@ $< $(CFLAGS) 13 | chmod u+x $@ 14 | 15 | %.sout: %.s 16 | $(CC) -o $@ $< $(CFLAGS) 17 | chmod u+x $@ 18 | 19 | %.s: %.c 20 | $(CC) $(CFLAGS) -S -o $@ $< 21 | 22 | 23 | clean: 24 | rm -rf *.o *.sout *.dSYM *~ *.log functions.txt *.out 25 | -------------------------------------------------------------------------------- /fpsanitizer_test/makefiles/mathFunc.txt: -------------------------------------------------------------------------------- 1 | sqrt 2 | sqrtf 3 | cos 4 | sin 5 | tan 6 | cosec 7 | log 8 | exp 9 | pow 10 | hypot 11 | llvm.floor.f64 12 | acos 13 | sinh 14 | cosh 15 | tanh 16 | atan 17 | atan2 18 | llvm.fabs.f64 19 | GSL_MIN_DBL 20 | GSL_MAX_DBL 21 | llvm.ceil.f64 22 | fmod 23 | ldexp 24 | factor 25 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/ContinuedFraction1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // What happens when there is no infinity? 4 | // This continueed fraction experiences divide by 0 for x = 1, 2, 3, and 4 5 | // From William Kahan's commentary on "The End of Error ..." 6 | void ContinuedFraction1(float x) { 7 | printf("Calculating Continued Fraction of a formula with input x = %lf\n", x); 8 | 9 | float temp = 2 / (x - 3); 10 | temp = x - 2 - temp; 11 | temp = 10 / temp; 12 | temp = x - 7 + temp; 13 | temp = 1 / temp; 14 | temp = x - 2 - temp; 15 | temp = 12 / temp; 16 | float fresult = 13 - temp; 17 | 18 | printf("float result: %lf\n", fresult); 19 | } 20 | 21 | int main( int argc, const char* argv[] ) 22 | { 23 | ContinuedFraction1(1.0); 24 | ContinuedFraction1(2.0); 25 | ContinuedFraction1(3.0); 26 | ContinuedFraction1(4.0); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/MindlessG.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // William Kahan's Mindless G example. 5 | double T(double z) 6 | { 7 | double k, diff; 8 | if (z == 0.0) { 9 | k = 1.0f; 10 | } else { 11 | diff = exp(z) - 1.0f; 12 | k = (diff) / z; 13 | } 14 | return k; 15 | } 16 | 17 | double Q(double y) 18 | { 19 | double z1 = y * y + 1.0f; 20 | double z2 = y - sqrt(z1); 21 | double t1 = fabs(z2); 22 | double t2 = 1.0f / (y + sqrt(z1)); 23 | return t1 - t2; 24 | } 25 | 26 | double G(double x) 27 | { 28 | return T(Q(x) * Q(x)); 29 | } 30 | 31 | int main( int argc, const char* argv[] ) 32 | { 33 | printf("Starting Mindless_G testing. The result should be G(n) = 1 for all n\n"); 34 | for (int i = 0; i < 9999; i++) { 35 | double res = G(i); 36 | printf("G(%d) = %.10e\n", i, res); 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/ParallelResistance.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Let's calculate the parallel resistance function. 5 | // The parallel resistance of two resistors is 1 / (1/r1 + 1/r2) 6 | // Benchmark inspired by https://randomascii.wordpress.com/2012/04/21/exceptional-floating-point/ 7 | int main(int argc, const char* argv[] ) 8 | { 9 | float r1 = 0; 10 | float r2 = 0; 11 | printf("Parallel resistance of %lf and %lf\n", r1, r2); 12 | float ft1 = 1/r1; 13 | float ft2 = 1/r2; 14 | float result = 1 / (ft1 + ft2); 15 | 16 | printf("Float result: %lf\n", result); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/SimpsonsRule.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | float f(float x) { 6 | return x * x; 7 | } 8 | 9 | float f2(float x) { 10 | return sqrtf(x) / (x * x - 1); 11 | } 12 | 13 | void floatSimpsonsRuleV1F1(float lrange, float urange, int n) { 14 | if (n % 2 != 0) { 15 | printf("n has to be an even number\n"); 16 | return; 17 | } 18 | float step = (urange - lrange) / (float)n; 19 | 20 | float sum = f(lrange); 21 | for (int i = 1; i < n; i = i + 2) { 22 | // even-th term: 4 * f(x_{i}) 23 | sum += 4 * f(lrange + (float)i * step); 24 | // odd-th term: 2 * f(x_{i+1}) 25 | sum += 2 * f(lrange + (float)(i + 1) * step); 26 | } 27 | sum += f(urange); 28 | sum *= (step / 3.0); 29 | 30 | printf("V1: %.50e\n", sum); 31 | } 32 | 33 | void floatSimpsonsRuleV1F2(float lrange, float urange, int n) { 34 | if (n % 2 != 0) { 35 | printf("n has to be an even number\n"); 36 | return; 37 | } 38 | float step = (urange - lrange) / (float)n; 39 | 40 | float sum = f2(lrange); 41 | for (int i = 1; i < n; i = i + 2) { 42 | // even-th term: 4 * f(x_{i}) 43 | sum += 4 * f2(lrange + (float)i * step); 44 | // odd-th term: 2 * f(x_{i+1}) 45 | sum += 2 * f2(lrange + (float)(i + 1) * step); 46 | } 47 | sum += f2(urange); 48 | sum *= (step / 3.0); 49 | 50 | printf("V1: %.50e\n", sum); 51 | } 52 | void floatSimpsonsRuleV2F1(float lrange, float urange, int n) { 53 | if (n % 2 != 0) { 54 | printf("n has to be an even number\n"); 55 | return; 56 | } 57 | float step = (urange - lrange) / (float)n; 58 | 59 | float sum = f(lrange) * (step / 3.0); 60 | for (int i = 1; i < n; i = i + 2) { 61 | // even-th term: 4 * f(x_{i}) 62 | sum += 4 * f(lrange + (float)i * step) * (step / 3.0); 63 | // odd-th term: 2 * f(x_{i+1}) 64 | sum += 2 * f(lrange + (float)(i + 1) * step) * (step / 3.0); 65 | } 66 | sum += f(urange) * (step / 3.0); 67 | 68 | printf("V2: %.50e\n", sum); 69 | } 70 | void floatSimpsonsRuleV2F2(float lrange, float urange, int n) { 71 | if (n % 2 != 0) { 72 | printf("n has to be an even number\n"); 73 | return; 74 | } 75 | float step = (urange - lrange) / (float)n; 76 | 77 | float sum = f2(lrange) * (step / 3.0); 78 | for (int i = 1; i < n; i = i + 2) { 79 | // even-th term: 4 * f(x_{i}) 80 | sum += 4 * f2(lrange + (float)i * step) * (step / 3.0); 81 | // odd-th term: 2 * f(x_{i+1}) 82 | sum += 2 * f2(lrange + (float)(i + 1) * step) * (step / 3.0); 83 | } 84 | sum += f2(urange) * (step / 3.0); 85 | 86 | printf("V2: %.50e\n", sum); 87 | } 88 | 89 | int main(int argc, char** argv) { 90 | floatSimpsonsRuleV1F1(13223113, 14223113, 20000000); 91 | 92 | } 93 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/SinTaylorExpansion.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // I expected taylor expansions to have trouble, but it looks like they do not! 5 | // Posit is almost as good as float here. 6 | int main( int argc, const char* argv[] ) 7 | { 8 | float fx = 0.875f; 9 | 10 | float fcoeff[7] = { 11 | 1.0, 12 | -1.6666667163372039794921875e-01, 13 | 8.333333767950534820556640625e-03, 14 | -1.98412701138295233249664306640625e-04, 15 | 2.755731884462875314056873321533203125e-06, 16 | -2.505210972003624192439019680023193359375e-08, 17 | 1.605904298429550181026570498943328857421875e-10 18 | }; 19 | 20 | // Compute Taylor's expansion of sin: 21 | float fx2 = fx * fx; 22 | float fxaccum = 0.875f; 23 | float fresult = 0; 24 | for (int i = 0; i < 7; i++){ 25 | fresult += fcoeff[i] * fxaccum; 26 | fxaccum *= fx2; 27 | } 28 | 29 | printf("float result: %.50e\n", fresult); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/cc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | float x = 1.0; 6 | float y = 0.9999999; 7 | float z = x - y; 8 | printf("z:%e", z); 9 | } 10 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/compare-zero-self.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | volatile double x; 5 | int cmp; 6 | x = 0.0; 7 | cmp = (x == 0.0); 8 | printf("%d\n", cmp); 9 | } 10 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/cordic_cos.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const double angles[60] = { 5 | 7.8539816339744830962E-01, 6 | 4.6364760900080611621E-01, 7 | 2.4497866312686415417E-01, 8 | 1.2435499454676143503E-01, 9 | 6.2418809995957348474E-02, 10 | 3.1239833430268276254E-02, 11 | 1.5623728620476830803E-02, 12 | 7.8123410601011112965E-03, 13 | 3.9062301319669718276E-03, 14 | 1.9531225164788186851E-03, 15 | 9.7656218955931943040E-04, 16 | 4.8828121119489827547E-04, 17 | 2.4414062014936176402E-04, 18 | 1.2207031189367020424E-04, 19 | 6.1035156174208775022E-05, 20 | 3.0517578115526096862E-05, 21 | 1.5258789061315762107E-05, 22 | 7.6293945311019702634E-06, 23 | 3.8146972656064962829E-06, 24 | 1.9073486328101870354E-06, 25 | 9.5367431640596087942E-07, 26 | 4.7683715820308885993E-07, 27 | 2.3841857910155798249E-07, 28 | 1.1920928955078068531E-07, 29 | 5.9604644775390554414E-08, 30 | 2.9802322387695303677E-08, 31 | 1.4901161193847655147E-08, 32 | 7.4505805969238279871E-09, 33 | 3.7252902984619140453E-09, 34 | 1.8626451492309570291E-09, 35 | 9.3132257461547851536E-10, 36 | 4.6566128730773925778E-10, 37 | 2.3283064365386962890E-10, 38 | 1.1641532182693481445E-10, 39 | 5.8207660913467407226E-11, 40 | 2.9103830456733703613E-11, 41 | 1.4551915228366851807E-11, 42 | 7.2759576141834259033E-12, 43 | 3.6379788070917129517E-12, 44 | 1.8189894035458564758E-12, 45 | 9.0949470177292823792E-13, 46 | 4.5474735088646411896E-13, 47 | 2.2737367544323205948E-13, 48 | 1.1368683772161602974E-13, 49 | 5.6843418860808014870E-14, 50 | 2.8421709430404007435E-14, 51 | 1.4210854715202003717E-14, 52 | 7.1054273576010018587E-15, 53 | 3.5527136788005009294E-15, 54 | 1.7763568394002504647E-15, 55 | 8.8817841970012523234E-16, 56 | 4.4408920985006261617E-16, 57 | 2.2204460492503130808E-16, 58 | 1.1102230246251565404E-16, 59 | 5.5511151231257827021E-17, 60 | 2.7755575615628913511E-17, 61 | 1.3877787807814456755E-17, 62 | 6.9388939039072283776E-18, 63 | 3.4694469519536141888E-18, 64 | 1.7347234759768070944E-18 }; 65 | 66 | float cordic_cos (float z) { 67 | float x = 0.60725293500888125617; 68 | float y = 0.0; 69 | float di = 0.0; 70 | float pow2 = 1.0; 71 | float rot_ang; 72 | 73 | for (int i = 0; i < 50; i++) { 74 | if (z >= 0) di = 1.0; 75 | else di = -1.0; 76 | 77 | rot_ang = angles[i]; 78 | 79 | float x_prime = x - y * di * pow2; 80 | float y_prime = y + x * di * pow2; 81 | float z_prime = z - di * rot_ang; 82 | 83 | pow2 = pow2 / 2.0; 84 | x = x_prime; 85 | y = y_prime; 86 | z = z_prime; 87 | } 88 | 89 | return x; 90 | } 91 | 92 | int main(int argc, char** argv) { 93 | float cos = cordic_cos(1.0E-8); 94 | printf("cos:%e\n", cos); 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/cordic_sin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const double angles[60] = { 5 | 7.8539816339744830962E-01, 6 | 4.6364760900080611621E-01, 7 | 2.4497866312686415417E-01, 8 | 1.2435499454676143503E-01, 9 | 6.2418809995957348474E-02, 10 | 3.1239833430268276254E-02, 11 | 1.5623728620476830803E-02, 12 | 7.8123410601011112965E-03, 13 | 3.9062301319669718276E-03, 14 | 1.9531225164788186851E-03, 15 | 9.7656218955931943040E-04, 16 | 4.8828121119489827547E-04, 17 | 2.4414062014936176402E-04, 18 | 1.2207031189367020424E-04, 19 | 6.1035156174208775022E-05, 20 | 3.0517578115526096862E-05, 21 | 1.5258789061315762107E-05, 22 | 7.6293945311019702634E-06, 23 | 3.8146972656064962829E-06, 24 | 1.9073486328101870354E-06, 25 | 9.5367431640596087942E-07, 26 | 4.7683715820308885993E-07, 27 | 2.3841857910155798249E-07, 28 | 1.1920928955078068531E-07, 29 | 5.9604644775390554414E-08, 30 | 2.9802322387695303677E-08, 31 | 1.4901161193847655147E-08, 32 | 7.4505805969238279871E-09, 33 | 3.7252902984619140453E-09, 34 | 1.8626451492309570291E-09, 35 | 9.3132257461547851536E-10, 36 | 4.6566128730773925778E-10, 37 | 2.3283064365386962890E-10, 38 | 1.1641532182693481445E-10, 39 | 5.8207660913467407226E-11, 40 | 2.9103830456733703613E-11, 41 | 1.4551915228366851807E-11, 42 | 7.2759576141834259033E-12, 43 | 3.6379788070917129517E-12, 44 | 1.8189894035458564758E-12, 45 | 9.0949470177292823792E-13, 46 | 4.5474735088646411896E-13, 47 | 2.2737367544323205948E-13, 48 | 1.1368683772161602974E-13, 49 | 5.6843418860808014870E-14, 50 | 2.8421709430404007435E-14, 51 | 1.4210854715202003717E-14, 52 | 7.1054273576010018587E-15, 53 | 3.5527136788005009294E-15, 54 | 1.7763568394002504647E-15, 55 | 8.8817841970012523234E-16, 56 | 4.4408920985006261617E-16, 57 | 2.2204460492503130808E-16, 58 | 1.1102230246251565404E-16, 59 | 5.5511151231257827021E-17, 60 | 2.7755575615628913511E-17, 61 | 1.3877787807814456755E-17, 62 | 6.9388939039072283776E-18, 63 | 3.4694469519536141888E-18, 64 | 1.7347234759768070944E-18 }; 65 | 66 | float cordic_sin (float z) { 67 | float x = 0.60725293500888125617; 68 | float y = 0.0; 69 | float di = 0.0; 70 | float pow2 = 1.0; 71 | float rot_ang; 72 | for (int i = 0; i < 50; i++) { 73 | if (z >= 0) di = 1.0; 74 | else di = -1.0; 75 | 76 | rot_ang = angles[i]; 77 | 78 | float x_prime = x - y * di * pow2; //0.6 79 | float y_prime = y + x * di * pow2; //0.6 80 | float z_prime = z - di * rot_ang; // -7.85 81 | 82 | pow2 = pow2 / 2.0; //0.5 83 | x = x_prime; //0.67 84 | y = y_prime; //0.67 85 | z = z_prime; //-0.7 86 | } 87 | 88 | return y; 89 | } 90 | 91 | int main(int argc, char** argv) { 92 | float sin = cordic_sin(1E-8); 93 | printf("sin:%e\n", sin); 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/diff-roots-simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | volatile double x,y; 6 | x = 1e16; 7 | y = sqrt(x + 1) - sqrt(x); 8 | printf("%e\n", y); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/diff-roots.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double inputs[100] = { 5 | 1.06687256697924407457e+41, 6 | 2.30621218311210083827e+120, 7 | -2.10451314108857164377e+114, 8 | -3.98287816164808775168e+160, 9 | 3.81207391841274208945e-116, 10 | 2.68453448641700704000e+17, 11 | 1.06546124232961481324e+243, 12 | 4.94824606498177197880e-272, 13 | -3.58815353236457336865e+114, 14 | -2.70516505420671781626e+122, 15 | -1.24341015264021222067e-139, 16 | -5.33208238031160635464e-112, 17 | -1.56624727634140838291e+158, 18 | -1.88870182567587114969e-279, 19 | -1.58399828349251637756e-278, 20 | -1.17018378209676721224e+234, 21 | -4.86176876475447074882e+99, 22 | 3.97692241301810525572e-138, 23 | 1.65862691030757259444e-103, 24 | 1.17761473064608939671e+268, 25 | 3.55132102756105245913e+68, 26 | 5.02368133168268487181e-275, 27 | -8.07962738000718517751e-235, 28 | -1.56840498928907855205e-133, 29 | -3.22147640728587994886e-23, 30 | -7.56317177421849100000e+15, 31 | 7.16530630667136292367e-01, 32 | -6.88432014237391884302e+36, 33 | -3.46884496778514072160e-114, 34 | 4.18799811387271712776e-122, 35 | 1.38951487960984559322e+03, 36 | 5.89722421060091614682e+80, 37 | -3.06067338369208136379e-05, 38 | 3.58119601749257739818e-256, 39 | 4.57629941425916427566e+307, 40 | -3.82505062095224454865e-199, 41 | -5.38942468612722137503e-161, 42 | -7.11910715705631480441e+297, 43 | -2.59861371693873848819e-295, 44 | 2.09010324513067489116e-80, 45 | 4.61241854409933185307e-279, 46 | 7.42142423749652886574e+124, 47 | 3.25927614396184193777e-222, 48 | 4.29409772204035628182e+232, 49 | -7.76525214345772975679e+25, 50 | 4.19415258959758602908e-302, 51 | 2.32551648161687303564e-303, 52 | -7.82565572742261967021e-126, 53 | 2.61316306462938785916e-303, 54 | 1.96823259795867241896e+232, 55 | 3.93146132141588476362e+265, 56 | -1.66230097133718119186e+96, 57 | -1.55094602861113354331e+197, 58 | 1.96888558818343951332e-182, 59 | -8.83286436633954709784e-297, 60 | -1.68911178435464871178e+294, 61 | -3.17578306023338954139e+280, 62 | -2.56940060809168512889e-103, 63 | -1.15523599495993865230e+171, 64 | 3.35803970353416343268e-107, 65 | -8.86978739144672947761e+46, 66 | 1.60725439076535416082e-257, 67 | 2.89228393388974344760e-71, 68 | -3.36512950815614041815e-50, 69 | 2.95133288034021741509e-175, 70 | 8.98342376056038399259e-216, 71 | 5.95950598623411290451e-165, 72 | -6.29698779798445414511e+232, 73 | -7.02397058860905493613e-99, 74 | -7.61731582920582421875e+12, 75 | -1.30900510530832673938e+193, 76 | -3.62276349548375508948e-295, 77 | -3.16330388332889045899e+97, 78 | 1.72814474521259360248e+223, 79 | 2.07709057504226312588e-10, 80 | -7.38607486669759332343e-256, 81 | -1.51782972175049440370e-282, 82 | 5.32217723166920738472e-140, 83 | 1.62708564917769718147e-112, 84 | -4.71494061284311441378e-93, 85 | 2.78066647738459499287e+144, 86 | -9.05920561705418056814e+287, 87 | -1.95811597725921696014e+91, 88 | 3.44664616079981774382e+126, 89 | -1.08216117605327583291e+106, 90 | -1.55449971194022549715e-72, 91 | -3.49814276005425691605e+08, 92 | -3.46804141304839311163e-140, 93 | 3.97703892765640416282e+299, 94 | -3.53918690912702950346e-162, 95 | 3.69624041201316149386e+84, 96 | 6.33648926354710800571e+208, 97 | -3.20616173310556976465e+176, 98 | 5.41653867191774113705e-200, 99 | -1.23785255070938831953e+207, 100 | -1.24252314923185500160e+19, 101 | -1.99252934441723820513e-241, 102 | -2.79590038934860226217e-302, 103 | -3.91764153525876590231e-257, 104 | -9.70840407053036266314e+78 105 | }; 106 | 107 | int main() { 108 | volatile double x,y; 109 | for (int i = 0; i < 100; i++){ 110 | x = fabs(inputs[i]); 111 | y = sqrt(x + 1) - sqrt(x); 112 | printf("%e\n", y); 113 | } 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/diff-simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | double x,y; 6 | x = 1e16; 7 | y = (x + 1) - x; 8 | printf("%e\n", y); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/dotproduct1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // calculating dot product. The intermediate result has less precision bits in posit than float. 4 | // Altered from End of error example. 5 | int main( int argc, const char* argv[] ) 6 | { 7 | float fa[4] = {1.000010223508783104E+18, 1.00002781569482752E+17, -1.000010223508783104E+18, -1.00002781569482752E+17}; 8 | float fb[4] = {1.000010223508783104E+18, 1.00002781569482752E+17, 1.000010223508783104E+18, -1.00002781569482752E+17}; 9 | float fresult = 0.0; 10 | for (int i = 0; i < 4; i++) { 11 | fresult += fa[i] * fb[i]; 12 | } 13 | 14 | printf("float result: %.50e\n", fresult); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/dotproduct2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // calculating dot product. The intermediate result goes close to the maximum dynamic range of posit, which will result in significant error in posit. 4 | int main( int argc, const char* argv[] ) 5 | { 6 | float fa[4] = {3.200000000000000177635683940025E+0, 1.0E+0, -1.0E+0, 8.0E+0}; 7 | float fb[4] = {4.0E+6, 1.0E+0, -1.0E+0, -1.6E+6}; 8 | float fresult = 0.0; 9 | for (int i = 0; i < 4; i++) { 10 | fresult += fa[i] * fb[i]; 11 | } 12 | printf("Float result: %lf\n", fresult); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/exact-ranges.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double inputs[12] = { 5 | 0.7745966692414830, 0.7745966692414831, 0.7745966692414832, 0.7745966692414833, 6 | 0.7745966692414834, 0.7745966692414835, 0.7745966692414836, 0.7745966692414837, 7 | 0.7745966692414838, 0.7745966692414840, 0.7745966692414841, 0.7745966692414842 8 | }; 9 | 10 | int main() { 11 | volatile double x, y; 12 | for (int i = 0; i < 12; i++) { 13 | x = inputs[i]; 14 | y = 5.0*x*x - 3.0; 15 | printf("%e\n", y); 16 | } 17 | return 0; 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/functions.txt: -------------------------------------------------------------------------------- 1 | foo 2 | bar 3 | main 4 | f 5 | df 6 | floatNewtonRaphson 7 | main 8 | foo 9 | sum 10 | main 11 | T 12 | Q 13 | G 14 | main 15 | cordic_sin 16 | main 17 | cordic_cos 18 | main 19 | foo 20 | sum 21 | main 22 | main 23 | foo 24 | bar 25 | main 26 | main 27 | main 28 | iprod 29 | main 30 | main 31 | foo 32 | bar 33 | main 34 | f 35 | df 36 | floatNewtonRaphson 37 | main 38 | f 39 | f2 40 | floatSimpsonsRuleV1F1 41 | floatSimpsonsRuleV1F2 42 | floatSimpsonsRuleV2F1 43 | floatSimpsonsRuleV2F2 44 | main 45 | main 46 | ContinuedFraction1 47 | main 48 | calcY 49 | main 50 | main 51 | main 52 | main 53 | main 54 | addTwo 55 | main 56 | main 57 | main 58 | add 59 | main 60 | main 61 | main 62 | foo 63 | bar 64 | main 65 | main 66 | main 67 | main 68 | main 69 | convertToInt 70 | main 71 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/gromacs-bondfree-580.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | float iprod(float* a,float* b) 5 | { 6 | return (a[0]*b[0]+a[1]*b[1]+a[2]*b[2]); 7 | } 8 | 9 | float r_kj[10][3] = { 10 | {268453443323035648, 0.71653062105178833008, 1389.514892578125}, 11 | {2.0770905828637609147e-10, 4.5552733528942065653e-24, 2.793811015866509706e-10}, 12 | {0.092040725052356719971, 0.0022920905612409114838, 5.4301075065642613301e-21}, 13 | {943433600, 5.7629808612905003154e-30, 1.9748078868190349535e-40}, 14 | {3.715846901286568027e-07, 184.290313720703125, 1.8683431344172884485e-29}, 15 | {4.208303749919650727e-08, 1.8677865192031556994e-39, 3.7274539151040134087e-43}, 16 | {5.8237964177339397468e-42, 4.9045446251368597482e-44, 3.2664267203411485923e-42}, 17 | {340.728424072265625, 2.7634128318965167637e-10, 1205.4989013671875}, 18 | {1056530038784, 1067773132800, 4.8185892015429297611e-37}, 19 | {0.0053226999007165431976, 1.2250422945568828905e-22, 8.1286535331538631898e-39} 20 | }; 21 | 22 | int main() { 23 | float nrkj2, nrkj; 24 | for (int i = 0; i < 10; i++){ 25 | nrkj2 = iprod(r_kj[i], r_kj[i]); 26 | nrkj = sqrt(nrkj2); 27 | printf("%e\n", nrkj); 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/gsl-modpi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | double theta = 7e20; 6 | 7 | const double P1 = 4 * 7.85398125648498535156e-01; 8 | const double P2 = 4 * 3.77489470793079817668e-08; 9 | const double P3 = 4 * 2.69515142907905952645e-15; 10 | const double TwoPi = 2*(P1 + P2 + P3); 11 | 12 | double y = 2*floor(theta/TwoPi); 13 | double r = ((theta - y*P1) - y*P2) - y*P3; 14 | 15 | printf("%e\n", r); 16 | } 17 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/indirect.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double foo(double a) { 5 | return (a*sqrt(a)); 6 | } 7 | 8 | double sum(double (*fn)(double)) { 9 | int i; 10 | double b = 2.3; 11 | 12 | // for (i = 0; i < 100; ++i) { 13 | b = fn(b); 14 | // b = foo(b); 15 | // } 16 | 17 | return b; 18 | } 19 | 20 | int main(int argc, char *argv[]) { 21 | double x = sum(foo); 22 | printf("x:%e", x); 23 | } 24 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/indirect1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double foo(double a) { 5 | return (a*sqrt(a))/(a+0.1); 6 | } 7 | 8 | double sum(double (*fn)(double)) { 9 | int i; 10 | double b = 0; 11 | 12 | for (i = 0; i < 100; ++i) { 13 | b += fn(b); 14 | } 15 | 16 | return b; 17 | } 18 | 19 | int main(int argc, char *argv[]) { 20 | double x = sum(foo); 21 | printf("x:%e", x); 22 | } 23 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/mini.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | volatile double x,y; 6 | x = 3; 7 | y = sqrt(x + 1); 8 | printf("%e\n", y); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/multi-args.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | double xs[2] = {1.2, 1e-12}; 5 | double ys[2] = {0.5, 1e12}; 6 | double x, y, z; 7 | for(int i = 0; i < 2; ++i){ 8 | x = xs[i]; 9 | y = ys[i]; 10 | z = ( x + y ) - y; 11 | printf("%f\n", z); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/naturalnumber.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Float: 2.7182819843292236328125 5 | // Real : 2.7182818284590452353602874713527... 6 | // Posit: 2.7182818353176116943359375 7 | int main(int argc, char** argv) { 8 | float e = 2.0f; 9 | float prevE = 0.0f; 10 | 11 | float step = 2.0f; 12 | float prevStep = 0.0f; 13 | 14 | float denom = 2.0f; 15 | while (e != prevE && step != prevStep) { 16 | float term = 1.0f / denom; 17 | prevE = e; 18 | e += term; 19 | prevStep = step; 20 | step += 1.0f; 21 | denom *= step; 22 | } 23 | 24 | printf("%.50e\n", e); 25 | } 26 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/newtonraphson.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double f(double x) { 5 | return 3 * x - x * x - x * x * x + 16; 6 | } 7 | 8 | double df(double x) { 9 | return 3 - 2 * x - 3 * x * x; 10 | } 11 | 12 | void floatNewtonRaphson() { 13 | double oldX, x = 25.0f; 14 | double eps = 0.00001f; 15 | int maxStep = 100; 16 | int iter = 0; 17 | double d; 18 | 19 | oldX = x; 20 | double diffX = df(x); 21 | if (fabs(diffX) != 0.0 && !isnan(diffX)) { 22 | x = x - f(x) / diffX; 23 | } 24 | else { 25 | printf("Unexpected slope\n"); 26 | exit(1); 27 | } 28 | d = fabs(oldX - x); 29 | while (d > eps && iter < maxStep){ 30 | oldX = x; 31 | double diffX = df(x); 32 | if (fabs(diffX) != 0.0 && !isnan(diffX)) { 33 | x = x - f(x) / diffX; 34 | } 35 | else { 36 | printf("Unexpected slope\n"); 37 | exit(1); 38 | } 39 | iter ++; 40 | d = fabs(oldX - x); 41 | } 42 | printf("%.50e\n", x); 43 | } 44 | 45 | 46 | 47 | int main() { 48 | floatNewtonRaphson(); 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/newtonraphsonsqrt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | float f(float x, float v) { 6 | return x * x - v; 7 | } 8 | 9 | float df(float x) { 10 | return 2 * x; 11 | } 12 | 13 | void floatNewtonRaphson() { 14 | float v = 1771.0; 15 | float oldX, x = 25.0f; 16 | float eps = 0.00001f; 17 | int maxStep = 100; 18 | int iter = 0; 19 | float d; 20 | oldX = x; 21 | float diffX = df(x); 22 | if (fabs(diffX) != 0.0 && diffX != 0) { 23 | x = x - f(x, v) / diffX; 24 | } 25 | else { 26 | printf("Unexpected slope\n"); 27 | exit(1); 28 | } 29 | d = fabs(oldX - x); 30 | while ( d > eps && iter < maxStep){ 31 | oldX = x; 32 | float diffX = df(x); 33 | if (fabs(diffX) != 0.0 && diffX != 0) { 34 | x = x - f(x, v) / diffX; 35 | } 36 | else { 37 | printf("Unexpected slope\n"); 38 | exit(1); 39 | } 40 | iter ++; 41 | d = fabs(oldX - x); 42 | } 43 | printf("%.50e\n", x); 44 | } 45 | 46 | 47 | 48 | int main() { 49 | floatNewtonRaphson(); 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/onthefly.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // From the motivation example of Tao Bao's Oopsla13 "On the fly..." paper 5 | // In float, zi = 0. 6 | // In reals, zi = 1. 7 | 8 | int main( int argc, const char* argv[] ) 9 | { 10 | float x = 184.08964199999999777901393827051E+0; 11 | float z = x * x * x * x - 4 * x * x * x + 6 * x * x - 4 * x + 1; 12 | // Round to nearest integer 13 | z = z + 0.5; 14 | int zi = (int)(z + 0.5); 15 | printf("%d\n", zi); 16 | printf("%e\n", z); 17 | return 0; 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/redir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | volatile double x = 0.0; 6 | for (int i = 0; i < 2; ++i) { 7 | x += sqrt(i); 8 | } 9 | printf("%e\n", x); 10 | } 11 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/rootfinding1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // sqrt(b^2 - 4ac) is correct. Even -b +/- sqrt(b^2 - 4ac) might look correct. 5 | // But then the roots turn out to be completely wrong. 6 | int main( int argc, const char* argv[] ) 7 | { 8 | printf("rootfinding test case 2\n"); 9 | float fa = 1; 10 | float fb = 54.32; 11 | float fc = 0.1; 12 | 13 | float fbb = fb * fb; 14 | float f4ac = 4.0 * fa * fc; 15 | float fresult = fbb - f4ac; 16 | fresult = sqrtf(fresult); 17 | float fnumer1 = -1.0 * fb + fresult; 18 | float fnumer2 = -1.0 * fb - fresult; 19 | float froot1 = fnumer1 / (2.0 * fa); 20 | float froot2 = fnumer2 / (2.0 * fa); 21 | 22 | printf("float root1: %.50e\n", froot1); 23 | printf("float root2: %.50e\n", froot2); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/rootfinding2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // From Kahan "A survey of error analysis" 5 | int main( int argc, const char* argv[] ) 6 | { 7 | float fa = 7169.0; 8 | float fb = -8686.0; 9 | float fc = 2631.0; 10 | 11 | float fbb = fb * fb; 12 | float f4ac = 4.0 * fa * fc; 13 | float sub = fbb - f4ac; 14 | float fsqt = sqrtf(sub); 15 | float numer1 = -1.0 * fb + fsqt; 16 | float root1 = numer1 / (2.0 * fa); 17 | float numer2 = -1.0 * fb - fsqt; 18 | float root2 = numer2 / (2.0 * fa); 19 | printf("%.50e\n", root1); 20 | printf("%.50e\n", root2); 21 | return 0; 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/same-small.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | volatile double x = 1.0; 5 | double y = x + x; 6 | printf("%e\n", y); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/simpl-swallow-testa.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double foo(double x){ 4 | return ((x * 5) + 1) - (x * 5); 5 | } 6 | 7 | double bar(double x, double y){ 8 | return ((x * 5) + (1 + y)) - ((x * 5) + y); 9 | } 10 | 11 | int main(int argc, char** argv){ 12 | volatile double x, y, z, t; 13 | x = 1.0; 14 | y = 1.0e16; 15 | z = foo(x); 16 | printf("z = %e\n", z); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/simpl-swallow-testb.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double foo(double x){ 4 | return ((x * 5) + 1) - (x * 5); 5 | } 6 | 7 | double bar(double x, double y){ 8 | return ((x * 5) + (1 + y)) - ((x * 5) + y); 9 | } 10 | 11 | int main(int argc, char** argv){ 12 | volatile double x, y, z, t; 13 | x = 1.0; 14 | y = 1.0e16; 15 | t = foo(y); 16 | printf("t = %e\n", t); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/simpl-swallow-testc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double foo(double x){ 4 | return ((x * 5) + 1) - (x * 5); 5 | } 6 | 7 | double bar(double x, double y){ 8 | return ((x * 5) + (1 + y)) - ((x * 5) + y); 9 | } 10 | 11 | int main(int argc, char** argv){ 12 | volatile double x, y, z, t; 13 | x = 1.0; 14 | y = 1.0e16; 15 | volatile double a, b; 16 | a = bar(y, 8); 17 | printf("a = %e\n", a); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/simpl-swallow-testd.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double foo(double x){ 4 | return ((x * 5) + 1) - (x * 5); 5 | } 6 | 7 | double bar(double x, double y){ 8 | return ((x * 5) + (1 + y)) - ((x * 5) + y); 9 | } 10 | 11 | int main(int argc, char** argv){ 12 | volatile double x, y, z, t; 13 | x = 1.0; 14 | y = 1.0e16; 15 | volatile double a, b; 16 | b = bar(x, 9); 17 | printf("b = %e\n", b); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/simple-negate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | volatile float x = 1e-20; 6 | volatile float y = x * (-1); 7 | volatile float z = 5.0; 8 | float w = (y + z) - z; 9 | printf("%e\n", w); 10 | } 11 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/small.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void calcY(double* y, double x){ 5 | *y = sqrt(x + 1) - sqrt(x); 6 | } 7 | 8 | int main() { 9 | double x,y; 10 | x = 1e10; 11 | calcY(&y, x); 12 | calcY(&y, x); 13 | printf("%e\n", y); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/some-trig.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | double x, y; 6 | x = atan(1.0) * (40002); 7 | y = tan(x) - (sin(x)/cos(x)); 8 | printf("%e\n", y); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/sqrtf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | volatile float x, y; 6 | x = 4.0f; 7 | y = sqrtf(x); 8 | printf("%e\n", y); 9 | } 10 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/sum-50.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | volatile double x = 0; 5 | while(x < 10.0){ 6 | x += 0.2; 7 | } 8 | printf("%.20g\n", x); 9 | } 10 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/sum-500.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | volatile double x = 0.0; 5 | while(x < 100.0) { 6 | x += 0.2; 7 | } 8 | printf("%.20g\n", x); 9 | } 10 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/tiny.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x; 5 | x = 1 + 2; 6 | printf("%d\n", x); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/var-test-2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double addTwo(double x, double y){ 4 | return x + y; 5 | } 6 | 7 | int main() { 8 | volatile double x, y, z; 9 | z = 3; 10 | x = addTwo(z + 2, 4); 11 | y = addTwo(5, 7); 12 | printf("%e\n%e\n", x, y); 13 | } 14 | -------------------------------------------------------------------------------- /fpsanitizer_test/src/var-test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double add(double x, double y){ 4 | return x + y; 5 | } 6 | int main() { 7 | volatile double x, y, z1, z2, z3; 8 | z1 = 5; 9 | z2 = 6; 10 | z3 = z1 + z2; 11 | x = add(4, 5); 12 | y = add(6, z3); 13 | } 14 | --------------------------------------------------------------------------------