From 906573611559f18f1ba25533ab05d62053a934c9 Mon Sep 17 00:00:00 2001 From: hjwLab Date: Fri, 21 Apr 2023 15:16:43 +0800 Subject: [PATCH 01/54] Set up the environment for testing dd by implementing showOrder and modifying codes --- include/geneCode.hpp | 2 ++ src/geneCode.cpp | 60 ++++++++++++++++++++++++++++++-- src/main.cpp | 26 +++++++++++--- srcTest/test1paramFPEDParallel.c | 2 +- 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 66dfb90..9b42bac 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -41,6 +41,8 @@ string geneFinalCode(string exprStr, string uniqueLabel, vector exprIn void getDepth(ast_ptr &expr, int &depth); +void showOrder(ast_ptr &expr); + int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail); #endif \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index d19338e..0003441 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -324,7 +324,8 @@ string geneHerbieCode(string uniqueLabel) return herbieExpr; } fprintf(stderr, "ERROR: geneHerbieCode: we can not support %s now\n", uniqueLabel.c_str()); - exit(EXIT_FAILURE); + return ""; + // exit(EXIT_FAILURE); } string geneDaisyCode(string uniqueLabel) @@ -416,7 +417,8 @@ string geneDaisyCode(string uniqueLabel) return daisyExpr; } fprintf(stderr, "ERROR: geneDaisyCode: we can not support %s now\n", uniqueLabel.c_str()); - exit(EXIT_FAILURE); + return ""; + // exit(EXIT_FAILURE); } string geneMpfrCode(const ast_ptr &exprAst, const string uniqueLabel, vector vars) @@ -873,6 +875,58 @@ vector setOrder(ast_ptr &expr) return opOrder; } +void showOrdersKernel(ast_ptr &expr, int &orderNow) +{ + auto type = expr->type(); + if(type == "Number") + { + string tmp = "NO." + std::to_string(orderNow) + ": "; + printExpr(expr, tmp); + orderNow++; + } + else if(type == "Variable") + { + string tmp = "NO." + std::to_string(orderNow) + ": "; + printExpr(expr, tmp); + orderNow++; + } + else if(type == "Call") + { + CallExprAST *callPtr = dynamic_cast(expr.get()); + auto &args = callPtr->getArgs(); + vector paramOrders; + for(auto& arg : args) + { + showOrdersKernel(arg, orderNow); + } + string tmp = "NO." + std::to_string(orderNow) + ": "; + printExpr(expr, tmp); + orderNow++; + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + showOrdersKernel(lhs, orderNow); + showOrdersKernel(rhs, orderNow); + string tmp = "NO." + std::to_string(orderNow) + ": "; + printExpr(expr, tmp); + orderNow++; + } + else + { + fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); + exit(EXIT_FAILURE); + } +} + +void showOrder(ast_ptr &expr) +{ + int order = 0; + showOrdersKernel(expr, order); +} + static std::map opMap = { {'+', "add"}, {'-', "sub"}, @@ -1179,7 +1233,7 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // currentNum = currentNum >> 1; // } - vector dataTypes = {"DD", "ld", "double"}; + vector dataTypes = {"DD", "double"}; int lenDataTypes = dataTypes.size(); int maxNum = pow(lenDataTypes, lenOp); // for dataTypes = {"ld", "double"}, maxNum = 1 << lenOp; for(int num = 0; num < maxNum; num++) diff --git a/src/main.cpp b/src/main.cpp index f192b85..5958e83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -279,7 +279,28 @@ int main() auto exprHerbie = geneHerbieCode(uniqueLabel); auto exprDaisy = geneDaisyCode(uniqueLabel); auto funcNameMpfr = geneMpfrCode(inputStr, uniqueLabel, vars); - + printExpr(originExpr, "the origin expr: "); + showOrder(originExpr); + auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd"); + vector startNowIdxs(dimension, 0); + vector startOriginIntervals; + vector steps; + for (int i = 0; i < dimension; i++) + { + auto &startOriginInterval = intervals.at(i * 2); + auto &endOriginInterval = intervals.at(i * 2 + 1); + startOriginIntervals.push_back(startOriginInterval); + double width = endOriginInterval - startOriginInterval; + double step = width / (double)scales.at(i); + steps.push_back(step); + } + for(int i = 0; i < maxNum; i++) { + string tmp = "dd_" + std::to_string(i); + testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, true); + } + // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); + fprintf(stderr, GREEN "ready> " RESET); + continue; // if(exprOrigin != "") // { // originPerformance = testPerformance(uniqueLabel, "origin", intervals); @@ -455,9 +476,6 @@ int main() auto funcNameFinal = geneFinalCodeKernel(inputStr, uniqueLabel, exprInfoVector, vars); cout << "=-=-=-=-=-=-=-=-=-=-=-=-= test final code's error and performance start =-=-=-=-=-=-=-=-=-=-=-=-=\n"; - vector startNowIdxs(dimension, 0); - vector startOriginIntervals; - vector steps; for (int i = 0; i < dimension; i++) { auto &startOriginInterval = intervals.at(i * 2); diff --git a/srcTest/test1paramFPEDParallel.c b/srcTest/test1paramFPEDParallel.c index 8e9f5a2..1fce010 100644 --- a/srcTest/test1paramFPEDParallel.c +++ b/srcTest/test1paramFPEDParallel.c @@ -254,7 +254,7 @@ int main(int argc, char **argv) } printf("average ulp\tmax ulp\n"); printf("%.16le\t%.16le\n", aveError, maxError); - // printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); + printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); fprintf(fErr, "average ulp\tmax ulp\n"); fprintf(fErr, "%.16le\t%.16le\n", aveError, maxError); fprintf(fErr, "\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); -- Gitee From 96e8c0fbc9c93069f9be711b9c2cd01e50d54e58 Mon Sep 17 00:00:00 2001 From: hjwLab Date: Sat, 22 Apr 2023 10:39:06 +0800 Subject: [PATCH 02/54] Enhance error detecting methods --- detectErrorOneFPEDParallel.sh | 3 ++- includeTEST/common.h | 4 ++++ srcTest/computeULP.c | 32 ++++++++++++++++++++++++++++++++ srcTest/test1paramFPEDParallel.c | 32 +++++++++++++++++++------------- 4 files changed, 57 insertions(+), 14 deletions(-) diff --git a/detectErrorOneFPEDParallel.sh b/detectErrorOneFPEDParallel.sh index 140564f..9a336c3 100755 --- a/detectErrorOneFPEDParallel.sh +++ b/detectErrorOneFPEDParallel.sh @@ -4,6 +4,7 @@ path=`pwd` cd ${path} CC=mpicc +ERRORMODEL=ABSOLUTE uniqueLabel=${1} # unique number x0Start=${2} @@ -49,7 +50,7 @@ sourceFile=${prefix}_${suffix} fileNameKernel=${prefix}__${middle}_${suffix} # echo "${CC} ${testFileName}.c ${sourceFile}.c ${prefix}_mpfr.c computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -O3 -o ${testFileName}.exe" -${CC} ./srcTest/${testFileName}.c ${directory}/${sourceFile}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -DERRFILE=${errfile} -Llibs -lTGen -lmpfr -lm -lqd -o ${testFileName}.exe +${CC} ./srcTest/${testFileName}.c ${directory}/${sourceFile}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -DERRFILE=${errfile} -D${ERRORMODEL} -Llibs -lTGen -lmpfr -lm -lqd -o ${testFileName}.exe # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${fileNameKernel}" mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${fileNameKernel} ${uniqueLabel} # mv outputs/${fileNameKernel}_error.txt ./outputs/${uniqueLabel}/${fileNameKernel}_error.txt diff --git a/includeTEST/common.h b/includeTEST/common.h index d1f852e..c298ce9 100644 --- a/includeTEST/common.h +++ b/includeTEST/common.h @@ -33,6 +33,10 @@ double computeUlpDiff(mpfr_t correctValue, mpfr_t myValue); double computeUlpDiffF(mpfr_t correctValue, mpfr_t myValue); +double computeAbs(mpfr_t correctValue, mpfr_t myValue); + +double computeRel(mpfr_t correctValue, mpfr_t myValue); + #define _EXP_BITS 11 #define SIGN_BIT 0x8000000000000000 #define EXP_BIT 0x7FF0000000000000 diff --git a/srcTest/computeULP.c b/srcTest/computeULP.c index febfa08..d2b4d84 100644 --- a/srcTest/computeULP.c +++ b/srcTest/computeULP.c @@ -96,3 +96,35 @@ double computeUlpDiffF(mpfr_t correctValue, mpfr_t myValue) { mpfr_clears(mpfrDiff, mpfrReUlp, (mpfr_ptr) 0); return reUlp; } + +double computeAbs(mpfr_t correctValue, mpfr_t myValue) { + double result; + mpfr_t mpfrDiff; + + mpfr_inits2(PRECISION, mpfrDiff, (mpfr_ptr)0); + + mpfr_sub(mpfrDiff, correctValue, myValue, MPFR_RNDN); + result = mpfr_get_d(mpfrDiff, MPFR_RNDN); + result = fabs(result); + + // mpfr clear + mpfr_clears(mpfrDiff, (mpfr_ptr)0); + return result; +} + +double computeRel(mpfr_t correctValue, mpfr_t myValue) +{ + double result; + mpfr_t mpfrDiff; + + mpfr_inits2(PRECISION, mpfrDiff, (mpfr_ptr)0); + + mpfr_sub(mpfrDiff, correctValue, myValue, MPFR_RNDN); + mpfr_div(mpfrDiff, mpfrDiff, correctValue, MPFR_RNDN); + result = mpfr_get_d(mpfrDiff, MPFR_RNDN); + result = fabs(result); + + // mpfr clear + mpfr_clears(mpfrDiff, (mpfr_ptr)0); + return result; +} \ No newline at end of file diff --git a/srcTest/test1paramFPEDParallel.c b/srcTest/test1paramFPEDParallel.c index 1fce010..47abd2e 100644 --- a/srcTest/test1paramFPEDParallel.c +++ b/srcTest/test1paramFPEDParallel.c @@ -46,7 +46,7 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int DL maxInputX0; int i0; // int flag; - double x0, reUlp, sumError, aveReUlp, maxReUlp, lenX0; + double x0, error, sumError, aveReUlp, maxReUlp, lenX0; // mpfr mpfr_t mpfrOrcle, mpfrResult; @@ -85,29 +85,35 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int x0 = x0startOriginInterval + stepX0 * i0; computeResult1param(x0, mpfrResult); computeOrcle1param(x0, mpfrOrcle); - #ifdef SINGLE - reUlp = computeUlpDiffF(mpfrOrcle, mpfrResult); - #else // compute Double ULP as default - reUlp = computeUlpDiff(mpfrOrcle, mpfrResult); + #if (defined ABSOLUTE) + error = computeAbs(mpfrOrcle, mpfrResult); + #elif (defined RELATIVE) + error = computeRel(mpfrOrcle, mpfrResult); + #else + #if (defined SINGLE) + error = computeUlpDiffF(mpfrOrcle, mpfrResult); + #else // compute Double ULP as default + error = computeUlpDiff(mpfrOrcle, mpfrResult); + #endif #endif - // if(reUlp <= 0.5) { - // reUlp = 0; + // if(error <= 0.5) { + // error = 0; // } - // if(isfinite(reUlp) == 0) { + // if(isfinite(error) == 0) { // printf("happen to NaN or inf\n"); // exit(1); // } - if (isnormal(reUlp) != 0) + if (isnormal(error) != 0) { #if ERRFILE - fprintf(f, "%le\t%le\n", x0, reUlp); + fprintf(f, "%le\t%le\n", x0, error); #endif - sumError += reUlp; - if (reUlp > maxReUlp) { + sumError += error; + if (error > maxReUlp) { // flag = 0; maxInputX0.d = x0; - maxReUlp = reUlp; + maxReUlp = error; } } -- Gitee From 491ef11604a08add33d47d7027550b77b0a04d49 Mon Sep 17 00:00:00 2001 From: hjwLab Date: Sun, 23 Apr 2023 10:56:02 +0800 Subject: [PATCH 03/54] Modify absolute error detecting method for 1 param --- includeTEST/common.h | 2 +- src/main.cpp | 10 +++++++++- srcTest/computeULP.c | 7 +------ srcTest/test1paramFPEDParallel.c | 8 ++++---- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/includeTEST/common.h b/includeTEST/common.h index c298ce9..e5051a7 100644 --- a/includeTEST/common.h +++ b/includeTEST/common.h @@ -33,7 +33,7 @@ double computeUlpDiff(mpfr_t correctValue, mpfr_t myValue); double computeUlpDiffF(mpfr_t correctValue, mpfr_t myValue); -double computeAbs(mpfr_t correctValue, mpfr_t myValue); +double computeAbs(mpfr_t correctValue, mpfr_t myValue, mpfr_t mpfrDiff); double computeRel(mpfr_t correctValue, mpfr_t myValue); diff --git a/src/main.cpp b/src/main.cpp index 5958e83..733f5be 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -294,9 +294,17 @@ int main() double step = width / (double)scales.at(i); steps.push_back(step); } + vector infos; for(int i = 0; i < maxNum; i++) { string tmp = "dd_" + std::to_string(i); - testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, true); + auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + infos.push_back(infoTmp); + } + cout << "No\taverage Err\tmax Err\n"; + for(size_t i = 0; i < infos.size(); i++) + { + auto &info = infos.at(i); + cout << i << "\t" << info.aveError << "\t" << info.maxError << "\n"; } // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); fprintf(stderr, GREEN "ready> " RESET); diff --git a/srcTest/computeULP.c b/srcTest/computeULP.c index d2b4d84..5bb3c04 100644 --- a/srcTest/computeULP.c +++ b/srcTest/computeULP.c @@ -97,18 +97,13 @@ double computeUlpDiffF(mpfr_t correctValue, mpfr_t myValue) { return reUlp; } -double computeAbs(mpfr_t correctValue, mpfr_t myValue) { +double computeAbs(mpfr_t correctValue, mpfr_t myValue, mpfr_t mpfrDiff) { double result; - mpfr_t mpfrDiff; - - mpfr_inits2(PRECISION, mpfrDiff, (mpfr_ptr)0); mpfr_sub(mpfrDiff, correctValue, myValue, MPFR_RNDN); result = mpfr_get_d(mpfrDiff, MPFR_RNDN); result = fabs(result); - // mpfr clear - mpfr_clears(mpfrDiff, (mpfr_ptr)0); return result; } diff --git a/srcTest/test1paramFPEDParallel.c b/srcTest/test1paramFPEDParallel.c index 47abd2e..dde1b65 100644 --- a/srcTest/test1paramFPEDParallel.c +++ b/srcTest/test1paramFPEDParallel.c @@ -49,8 +49,8 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int double x0, error, sumError, aveReUlp, maxReUlp, lenX0; // mpfr - mpfr_t mpfrOrcle, mpfrResult; - mpfr_inits2(PRECISION, mpfrOrcle, mpfrResult, (mpfr_ptr) 0); + mpfr_t mpfrOrcle, mpfrResult, mpfrDiff; + mpfr_inits2(PRECISION, mpfrOrcle, mpfrResult, mpfrDiff, (mpfr_ptr) 0); // write error data to file #if ERRFILE @@ -86,7 +86,7 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int computeResult1param(x0, mpfrResult); computeOrcle1param(x0, mpfrOrcle); #if (defined ABSOLUTE) - error = computeAbs(mpfrOrcle, mpfrResult); + error = computeAbs(mpfrOrcle, mpfrResult, mpfrDiff); #elif (defined RELATIVE) error = computeRel(mpfrOrcle, mpfrResult); #else @@ -133,7 +133,7 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int fclose(f); free(fileNameSample); #endif - mpfr_clears(mpfrOrcle, mpfrResult, (mpfr_ptr) 0); + mpfr_clears(mpfrOrcle, mpfrResult, mpfrDiff, (mpfr_ptr) 0); struct errorInfo err; err.sumError = sumError; err.maxError = maxReUlp; -- Gitee From 1a3a794d23ca6edb23122821ae3e28cb5996ac2f Mon Sep 17 00:00:00 2001 From: hjwLab Date: Sun, 23 Apr 2023 15:46:36 +0800 Subject: [PATCH 04/54] Set up the environment for testing dd by implementing showOrder and modifying codes --- include/geneCode.hpp | 2 ++ src/geneCode.cpp | 61 ++++++++++++++++++++++++++++++-- src/main.cpp | 21 ++++++++--- srcTest/test1paramFPEDParallel.c | 2 +- 4 files changed, 78 insertions(+), 8 deletions(-) diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 66dfb90..3a30611 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -41,6 +41,8 @@ string geneFinalCode(string exprStr, string uniqueLabel, vector exprIn void getDepth(ast_ptr &expr, int &depth); +int showOrder(ast_ptr &expr); + int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail); #endif \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index d19338e..a4bfc63 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -324,7 +324,8 @@ string geneHerbieCode(string uniqueLabel) return herbieExpr; } fprintf(stderr, "ERROR: geneHerbieCode: we can not support %s now\n", uniqueLabel.c_str()); - exit(EXIT_FAILURE); + return ""; + // exit(EXIT_FAILURE); } string geneDaisyCode(string uniqueLabel) @@ -416,7 +417,8 @@ string geneDaisyCode(string uniqueLabel) return daisyExpr; } fprintf(stderr, "ERROR: geneDaisyCode: we can not support %s now\n", uniqueLabel.c_str()); - exit(EXIT_FAILURE); + return ""; + // exit(EXIT_FAILURE); } string geneMpfrCode(const ast_ptr &exprAst, const string uniqueLabel, vector vars) @@ -873,6 +875,59 @@ vector setOrder(ast_ptr &expr) return opOrder; } +void showOrdersKernel(ast_ptr &expr, int &orderNow) +{ + auto type = expr->type(); + if(type == "Number") + { + string tmp = "NO." + std::to_string(orderNow) + ": "; + printExpr(expr, tmp); + orderNow++; + } + else if(type == "Variable") + { + string tmp = "NO." + std::to_string(orderNow) + ": "; + printExpr(expr, tmp); + orderNow++; + } + else if(type == "Call") + { + CallExprAST *callPtr = dynamic_cast(expr.get()); + auto &args = callPtr->getArgs(); + vector paramOrders; + for(auto& arg : args) + { + showOrdersKernel(arg, orderNow); + } + string tmp = "NO." + std::to_string(orderNow) + ": "; + printExpr(expr, tmp); + orderNow++; + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + showOrdersKernel(lhs, orderNow); + showOrdersKernel(rhs, orderNow); + string tmp = "NO." + std::to_string(orderNow) + ": "; + printExpr(expr, tmp); + orderNow++; + } + else + { + fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); + exit(EXIT_FAILURE); + } +} + +int showOrder(ast_ptr &expr) +{ + int order = 0; + showOrdersKernel(expr, order); + return order; +} + static std::map opMap = { {'+', "add"}, {'-', "sub"}, @@ -1179,7 +1234,7 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // currentNum = currentNum >> 1; // } - vector dataTypes = {"DD", "ld", "double"}; + vector dataTypes = {"DD", "double"}; int lenDataTypes = dataTypes.size(); int maxNum = pow(lenDataTypes, lenOp); // for dataTypes = {"ld", "double"}, maxNum = 1 << lenOp; for(int num = 0; num < maxNum; num++) diff --git a/src/main.cpp b/src/main.cpp index f192b85..de01ce1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -279,7 +279,23 @@ int main() auto exprHerbie = geneHerbieCode(uniqueLabel); auto exprDaisy = geneDaisyCode(uniqueLabel); auto funcNameMpfr = geneMpfrCode(inputStr, uniqueLabel, vars); - + printExpr(originExpr, "the origin expr: "); + showOrder(originExpr); + vector startNowIdxs(dimension, 0); + vector startOriginIntervals; + vector steps; + for (int i = 0; i < dimension; i++) + { + auto &startOriginInterval = intervals.at(i * 2); + auto &endOriginInterval = intervals.at(i * 2 + 1); + startOriginIntervals.push_back(startOriginInterval); + double width = endOriginInterval - startOriginInterval; + double step = width / (double)scales.at(i); + steps.push_back(step); + } + testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); + fprintf(stderr, GREEN "ready> " RESET); + continue; // if(exprOrigin != "") // { // originPerformance = testPerformance(uniqueLabel, "origin", intervals); @@ -455,9 +471,6 @@ int main() auto funcNameFinal = geneFinalCodeKernel(inputStr, uniqueLabel, exprInfoVector, vars); cout << "=-=-=-=-=-=-=-=-=-=-=-=-= test final code's error and performance start =-=-=-=-=-=-=-=-=-=-=-=-=\n"; - vector startNowIdxs(dimension, 0); - vector startOriginIntervals; - vector steps; for (int i = 0; i < dimension; i++) { auto &startOriginInterval = intervals.at(i * 2); diff --git a/srcTest/test1paramFPEDParallel.c b/srcTest/test1paramFPEDParallel.c index 8e9f5a2..1fce010 100644 --- a/srcTest/test1paramFPEDParallel.c +++ b/srcTest/test1paramFPEDParallel.c @@ -254,7 +254,7 @@ int main(int argc, char **argv) } printf("average ulp\tmax ulp\n"); printf("%.16le\t%.16le\n", aveError, maxError); - // printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); + printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); fprintf(fErr, "average ulp\tmax ulp\n"); fprintf(fErr, "%.16le\t%.16le\n", aveError, maxError); fprintf(fErr, "\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); -- Gitee From ac2c7b98396f270cef0f79bb123bb49f8b631681 Mon Sep 17 00:00:00 2001 From: hjwLab Date: Tue, 25 Apr 2023 23:10:30 +0800 Subject: [PATCH 05/54] support shadowValue initially --- Makefile | 2 +- include/basic.hpp | 48 +- include/funclist.hpp | 48 + include/mpreal.h | 3337 +++++++++++++++++++++++++++++++++++++++ include/shadowValue.hpp | 10 + src/basic.cpp | 52 + src/funclist.cpp | 87 + src/main.cpp | 22 + src/shadowValue.cpp | 213 +++ 9 files changed, 3813 insertions(+), 6 deletions(-) create mode 100644 include/funclist.hpp create mode 100644 include/mpreal.h create mode 100644 include/shadowValue.hpp create mode 100644 src/funclist.cpp create mode 100644 src/shadowValue.cpp diff --git a/Makefile b/Makefile index 291ac1e..4cba888 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CC = gcc CPP = g++ INCLUDE = -Iinclude -I/usr/include/python3.8 # LIBS= -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -lpython3.8 # may need -L to assign the Python lobrary path -LIBS = -lm -lpython3.8 -lfmt +LIBS = -lm -lpython3.8 -lfmt -lmpfr ECHO = printf # $(info $(CFLAGS) ) diff --git a/include/basic.hpp b/include/basic.hpp index ec01f59..a6d20a2 100644 --- a/include/basic.hpp +++ b/include/basic.hpp @@ -12,6 +12,9 @@ #include #include #include +#include +#include "mpreal.h" +#include "funclist.hpp" using std::string; using std::vector; @@ -41,6 +44,22 @@ public: size_t rewriteID; }; +typedef std::function singleCall; +typedef std::function doubleCall; +typedef std::function tribleCall; +typedef std::function quadCall; +typedef std::function)> commonCall; +typedef std::function doubleRealCall; +typedef std::function)> commonRealCall; + +extern std::map singleCall_map; +extern std::map doubleCall_map; +extern std::map tribleCall_map; +extern std::map quadCall_map; +extern std::map commonCall_map; +extern std::map doubleRealCall_map; +extern std::map commonRealCall_map; + //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// @@ -110,9 +129,14 @@ class BinaryExprAST : public ExprAST { char Op; std::unique_ptr LHS, RHS; - + doubleCall func; + doubleRealCall realFunc; public: - BinaryExprAST(char Op, std::unique_ptr LHS, std::unique_ptr RHS) : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + BinaryExprAST(char Op, std::unique_ptr LHS, std::unique_ptr RHS) : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) { + string Opstr(1,Op); + func = doubleCall_map.find(Opstr)->second; + realFunc = doubleRealCall_map.find(Opstr)->second; + } void printExpr() { @@ -124,10 +148,12 @@ public: string type() { return "Binary"; } char getOp() { return Op; } - void setOp(char opNew) { Op = opNew; } std::unique_ptr &getLHS() { return LHS; } std::unique_ptr &getRHS() { return RHS; } + doubleCall getCallback() { return func; } + doubleRealCall getRealCallback() { return realFunc; } + void setOp(char opNew) { Op = opNew; } void setLHS(std::unique_ptr &newLHS) { LHS = newLHS->Clone(); } void setRHS(std::unique_ptr &newRHS) { RHS = newRHS->Clone(); } @@ -144,11 +170,19 @@ class CallExprAST : public ExprAST { string Callee; vector> Args; + commonCall call; + commonRealCall realCall; public: - CallExprAST(const string &Callee, vector> Args) : Callee(Callee), Args(std::move(Args)) {} + CallExprAST(const string &Callee, vector> Args) : Callee(Callee), Args(std::move(Args)) { + call = commonCall_map.find(Callee)->second; + realCall = commonRealCall_map.find(Callee)->second; + } - CallExprAST(std::unique_ptr &func) : Callee(func->Callee), Args(std::move(func->Args)) {} + CallExprAST(std::unique_ptr &func) : Callee(func->Callee), Args(std::move(func->Args)) { + call = commonCall_map.find(Callee)->second; + realCall = commonRealCall_map.find(Callee)->second; + } void printExpr() { @@ -164,6 +198,8 @@ public: string getCallee() { return Callee; } vector> &getArgs() { return Args; } + commonCall getCallback() { return call; } + commonRealCall getRealCallback() { return realCall; } std::unique_ptr Clone() { @@ -264,4 +300,6 @@ void write_to_file(const string &uniqueLabel, const string &exprOriginBest, cons void write_to_file_wrapper(string uniqueLabel, string exprOriginBest, int dimension, int numIntervalsBefore, double numOfIntervals, const vector &numIntervalsSoloBefore, const vector &numIntervalsSoloAfter, int numOfExprs, vector thresholds, const exprInfo &originExprInfo, const exprInfo &herbieExprInfo, const exprInfo &finalInfo, double originPerformance, double elapsed_seconds, double init_seconds, double matlab_seconds, double regime_seconds, double rewrite_seconds, double final_seconds, double matlabKernelTime); // } // end anonymous namespace +std::map setVarsValue(const vector &vars, const vector &values); + #endif \ No newline at end of file diff --git a/include/funclist.hpp b/include/funclist.hpp new file mode 100644 index 0000000..20bb690 --- /dev/null +++ b/include/funclist.hpp @@ -0,0 +1,48 @@ +#ifndef _FUNCLIST +#define _FUNCLIST +#include +#include "mpreal.h" + +using std::vector; + +double mineadd(double x, double y); + +double minesub(double x, double y); + +double minemul(double x, double y); + +double minediv(double x, double y); + +double minesin(double x); + +double minecos(double x); + +double minetan(double x); + +double mineexp(double x); + +double minelog(double x); + +double mineasin(double x); + +double mineacos(double x); + +double mineatan(double x); + +double common_sin(vector args); + +double common_cos(vector args); + +double common_tan(vector args); + +mpfr::mpreal realadd(mpfr::mpreal x, mpfr::mpreal y); + +mpfr::mpreal realsub(mpfr::mpreal x, mpfr::mpreal y); + +mpfr::mpreal realmul(mpfr::mpreal x, mpfr::mpreal y); + +mpfr::mpreal realdiv(mpfr::mpreal x, mpfr::mpreal y); + +mpfr::mpreal real_tan(vector args); + +#endif \ No newline at end of file diff --git a/include/mpreal.h b/include/mpreal.h new file mode 100644 index 0000000..426da2f --- /dev/null +++ b/include/mpreal.h @@ -0,0 +1,3337 @@ +/* + MPFR C++: Multi-precision floating point number class for C++. + Based on MPFR library: http://mpfr.org + + Project homepage: http://www.holoborodko.com/pavel/mpfr + Contact e-mail: pavel@holoborodko.com + + Copyright (c) 2008-2022 Pavel Holoborodko + + Contributors: + Dmitriy Gubanov, Konstantin Holoborodko, Brian Gladman, + Helmut Jarausch, Fokko Beekhof, Ulrich Mutze, Heinz van Saanen, + Pere Constans, Peter van Hoof, Gael Guennebaud, Tsai Chia Cheng, + Alexei Zubanov, Jauhien Piatlicki, Victor Berger, John Westwood, + Petr Aleksandrov, Orion Poplawski, Charles Karney, Arash Partow, + Rodney James, Jorge Leitao, Jerome Benoit, Michal Maly. + + Licensing: + (A) MPFR C++ is under GNU General Public License ("GPL"). + + (B) Non-free licenses may also be purchased from the author, for users who + do not want their programs protected by the GPL. + + The non-free licenses are for users that wish to use MPFR C++ in + their products but are unwilling to release their software + under the GPL (which would require them to release source code + and allow free redistribution). + + Such users can purchase an unlimited-use license from the author. + Contact us for more details. + + GNU General Public License ("GPL") copyright permissions statement: + ************************************************************************** + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __MPREAL_H__ +#define __MPREAL_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Options +#define MPREAL_HAVE_MSVC_DEBUGVIEW // Enable Debugger Visualizer for "Debug" builds in MSVC. +#define MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS // Enable extended std::numeric_limits specialization. + // Meaning that "digits", "round_style" and similar members are defined as functions, not constants. + // See std::numeric_limits at the end of the file for more information. + +// Library version +#define MPREAL_VERSION_MAJOR 3 +#define MPREAL_VERSION_MINOR 6 +#define MPREAL_VERSION_PATCHLEVEL 9 +#define MPREAL_VERSION_STRING "3.6.9" + +// Detect compiler using signatures from http://predef.sourceforge.net/ +#if defined(__GNUC__) && defined(__INTEL_COMPILER) + #define IsInf(x) isinf(x) // Intel ICC compiler on Linux + +#elif defined(_MSC_VER) // Microsoft Visual C++ + #define IsInf(x) (!_finite(x)) + +#else + #define IsInf(x) std::isinf(x) // GNU C/C++ (and/or other compilers), just hope for C99 conformance +#endif + +// A Clang feature extension to determine compiler features. +#ifndef __has_feature + #define __has_feature(x) 0 +#endif + +// Detect support for r-value references (move semantic). +// Move semantic should be enabled with great care in multi-threading environments, +// especially if MPFR uses custom memory allocators. +// Everything should be thread-safe and support passing ownership over thread boundary. +#if (__has_feature(cxx_rvalue_references) || \ + defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) && !defined(MPREAL_DISABLE_MOVE_SEMANTIC)) + + #define MPREAL_HAVE_MOVE_SUPPORT + + // Use fields in mpfr_t structure to check if it was initialized / set dummy initialization + #define mpfr_is_initialized(x) (0 != (x)->_mpfr_d) + #define mpfr_set_uninitialized(x) ((x)->_mpfr_d = 0 ) +#endif + +// Detect support for explicit converters. +#if (__has_feature(cxx_explicit_conversions) || \ + (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC_MINOR >= 5) || __cplusplus >= 201103L || \ + (defined(_MSC_VER) && _MSC_VER >= 1800) || \ + (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1300)) + + #define MPREAL_HAVE_EXPLICIT_CONVERTERS +#endif + +#define MPFR_USE_INTMAX_T // Enable 64-bit integer types - should be defined before mpfr.h + +#if defined(MPREAL_HAVE_MSVC_DEBUGVIEW) && defined(_MSC_VER) && defined(_DEBUG) + #define MPREAL_MSVC_DEBUGVIEW_CODE DebugView = toString(); + #define MPREAL_MSVC_DEBUGVIEW_DATA std::string DebugView; +#else + #define MPREAL_MSVC_DEBUGVIEW_CODE + #define MPREAL_MSVC_DEBUGVIEW_DATA +#endif + +#define MPFR_USE_NO_MACRO +#include + +#if (MPFR_VERSION < MPFR_VERSION_NUM(3,0,0)) + #include // Needed for random() +#endif + +// Less important options +#define MPREAL_DOUBLE_BITS_OVERFLOW -1 // Triggers overflow exception during conversion to double if mpreal + // cannot fit in MPREAL_DOUBLE_BITS_OVERFLOW bits + // = -1 disables overflow checks (default) + +// Fast replacement for mpfr_set_zero(x, +1): +// (a) uses low-level data members, might not be forward compatible +// (b) sign is not set, add (x)->_mpfr_sign = 1; +#define mpfr_set_zero_fast(x) ((x)->_mpfr_exp = __MPFR_EXP_ZERO) + +#if defined(__GNUC__) + #define MPREAL_PERMISSIVE_EXPR __extension__ +#else + #define MPREAL_PERMISSIVE_EXPR +#endif + +namespace mpfr { + +class mpreal { +private: + mpfr_t mp; + +public: + + // Get default rounding mode & precision + inline static mp_rnd_t get_default_rnd() { return (mp_rnd_t)(mpfr_get_default_rounding_mode()); } + inline static mp_prec_t get_default_prec() { return (mpfr_get_default_prec)(); } + + // Constructors && type conversions + mpreal(); + mpreal(const mpreal& u); + mpreal(const mpf_t u); + mpreal(const mpz_t u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const mpq_t u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const double u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const long double u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const unsigned long long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const long long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const unsigned long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const unsigned int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const long int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const int u, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t mode = mpreal::get_default_rnd()); + + // Construct mpreal from mpfr_t structure. + // shared = true allows to avoid deep copy, so that mpreal and 'u' share the same data & pointers. + mpreal(const mpfr_t u, bool shared = false); + + mpreal(const char* s, mp_prec_t prec = mpreal::get_default_prec(), int base = 10, mp_rnd_t mode = mpreal::get_default_rnd()); + mpreal(const std::string& s, mp_prec_t prec = mpreal::get_default_prec(), int base = 10, mp_rnd_t mode = mpreal::get_default_rnd()); + + ~mpreal(); + +#ifdef MPREAL_HAVE_MOVE_SUPPORT + mpreal& operator=(mpreal&& v); + mpreal(mpreal&& u); +#endif + + // Operations + // = + // +, -, *, /, ++, --, <<, >> + // *=, +=, -=, /=, + // <, >, ==, <=, >= + + // = + mpreal& operator=(const mpreal& v); + mpreal& operator=(const mpf_t v); + mpreal& operator=(const mpz_t v); + mpreal& operator=(const mpq_t v); + mpreal& operator=(const long double v); + mpreal& operator=(const double v); + mpreal& operator=(const unsigned long int v); + mpreal& operator=(const unsigned long long int v); + mpreal& operator=(const long long int v); + mpreal& operator=(const unsigned int v); + mpreal& operator=(const long int v); + mpreal& operator=(const int v); + mpreal& operator=(const char* s); + mpreal& operator=(const std::string& s); + template mpreal& operator= (const std::complex& z); + + // + + mpreal& operator+=(const mpreal& v); + mpreal& operator+=(const mpf_t v); + mpreal& operator+=(const mpz_t v); + mpreal& operator+=(const mpq_t v); + mpreal& operator+=(const long double u); + mpreal& operator+=(const double u); + mpreal& operator+=(const unsigned long int u); + mpreal& operator+=(const unsigned int u); + mpreal& operator+=(const long int u); + mpreal& operator+=(const int u); + + mpreal& operator+=(const long long int u); + mpreal& operator+=(const unsigned long long int u); + mpreal& operator-=(const long long int u); + mpreal& operator-=(const unsigned long long int u); + mpreal& operator*=(const long long int u); + mpreal& operator*=(const unsigned long long int u); + mpreal& operator/=(const long long int u); + mpreal& operator/=(const unsigned long long int u); + + const mpreal operator+() const; + mpreal& operator++ (); + const mpreal operator++ (int); + + // - + mpreal& operator-=(const mpreal& v); + mpreal& operator-=(const mpz_t v); + mpreal& operator-=(const mpq_t v); + mpreal& operator-=(const long double u); + mpreal& operator-=(const double u); + mpreal& operator-=(const unsigned long int u); + mpreal& operator-=(const unsigned int u); + mpreal& operator-=(const long int u); + mpreal& operator-=(const int u); + const mpreal operator-() const; + friend const mpreal operator-(const unsigned long int b, const mpreal& a); + friend const mpreal operator-(const unsigned int b, const mpreal& a); + friend const mpreal operator-(const long int b, const mpreal& a); + friend const mpreal operator-(const int b, const mpreal& a); + friend const mpreal operator-(const double b, const mpreal& a); + mpreal& operator-- (); + const mpreal operator-- (int); + + // * + mpreal& operator*=(const mpreal& v); + mpreal& operator*=(const mpz_t v); + mpreal& operator*=(const mpq_t v); + mpreal& operator*=(const long double v); + mpreal& operator*=(const double v); + mpreal& operator*=(const unsigned long int v); + mpreal& operator*=(const unsigned int v); + mpreal& operator*=(const long int v); + mpreal& operator*=(const int v); + + // / + mpreal& operator/=(const mpreal& v); + mpreal& operator/=(const mpz_t v); + mpreal& operator/=(const mpq_t v); + mpreal& operator/=(const long double v); + mpreal& operator/=(const double v); + mpreal& operator/=(const unsigned long int v); + mpreal& operator/=(const unsigned int v); + mpreal& operator/=(const long int v); + mpreal& operator/=(const int v); + friend const mpreal operator/(const unsigned long int b, const mpreal& a); + friend const mpreal operator/(const unsigned int b, const mpreal& a); + friend const mpreal operator/(const long int b, const mpreal& a); + friend const mpreal operator/(const int b, const mpreal& a); + friend const mpreal operator/(const double b, const mpreal& a); + + //<<= Fast Multiplication by 2^u + mpreal& operator<<=(const unsigned long int u); + mpreal& operator<<=(const unsigned int u); + mpreal& operator<<=(const long int u); + mpreal& operator<<=(const int u); + + //>>= Fast Division by 2^u + mpreal& operator>>=(const unsigned long int u); + mpreal& operator>>=(const unsigned int u); + mpreal& operator>>=(const long int u); + mpreal& operator>>=(const int u); + + // Type Conversion operators + bool toBool ( ) const; + long toLong (mp_rnd_t mode = GMP_RNDZ) const; + unsigned long toULong (mp_rnd_t mode = GMP_RNDZ) const; + long long toLLong (mp_rnd_t mode = GMP_RNDZ) const; + unsigned long long toULLong (mp_rnd_t mode = GMP_RNDZ) const; + float toFloat (mp_rnd_t mode = GMP_RNDN) const; + double toDouble (mp_rnd_t mode = GMP_RNDN) const; + long double toLDouble (mp_rnd_t mode = GMP_RNDN) const; + +#if defined (MPREAL_HAVE_EXPLICIT_CONVERTERS) + explicit operator bool () const { return toBool(); } + explicit operator signed char () const { return (signed char)toLong(); } + explicit operator unsigned char () const { return (unsigned char)toULong(); } + explicit operator short () const { return (short)toLong(); } + explicit operator unsigned short () const { return (unsigned short)toULong();} + explicit operator int () const { return (int)toLong(); } + explicit operator unsigned int () const { return (unsigned int)toULong(); } + explicit operator long () const { return toLong(); } + explicit operator unsigned long () const { return toULong(); } + explicit operator long long () const { return toLLong(); } + explicit operator unsigned long long () const { return toULLong(); } + explicit operator float () const { return toFloat(); } + explicit operator double () const { return toDouble(); } + explicit operator long double () const { return toLDouble(); } +#endif + + // Get raw pointers so that mpreal can be directly used in raw mpfr_* functions + ::mpfr_ptr mpfr_ptr(); + ::mpfr_srcptr mpfr_ptr() const; + ::mpfr_srcptr mpfr_srcptr() const; + + // Convert mpreal to string with n significant digits in base b + // n = -1 -> convert with the maximum available digits + std::string toString(int n = -1, int b = 10, mp_rnd_t mode = mpreal::get_default_rnd()) const; + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + std::string toString(const std::string& format) const; +#endif + + std::ostream& output(std::ostream& os) const; + + // Math Functions + friend const mpreal sqr (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal sqrt(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal sqrt(const unsigned long int v, mp_rnd_t rnd_mode); + friend const mpreal cbrt(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal root(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode); + friend const mpreal pow (const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode); + friend const mpreal pow (const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode); + friend const mpreal pow (const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode); + friend const mpreal pow (const mpreal& a, const long int b, mp_rnd_t rnd_mode); + friend const mpreal pow (const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode); + friend const mpreal pow (const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode); + friend const mpreal fabs(const mpreal& v, mp_rnd_t rnd_mode); + + friend const mpreal abs(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode); + friend inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode); + friend inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode); + friend inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode); + friend inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode); + friend int cmpabs(const mpreal& a,const mpreal& b); + + friend const mpreal log (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal log2 (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal logb (const mpreal& v, mp_rnd_t rnd_mode); + friend mp_exp_t ilogb(const mpreal& v); + friend const mpreal log10(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal exp (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal exp2 (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal exp10(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal log1p(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal expm1(const mpreal& v, mp_rnd_t rnd_mode); + + friend const mpreal nextpow2(const mpreal& v, mp_rnd_t rnd_mode); + + friend const mpreal cos(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal sin(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal tan(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal sec(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal csc(const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal cot(const mpreal& v, mp_rnd_t rnd_mode); + friend int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode); + + friend const mpreal acos (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal asin (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal atan (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode); + friend const mpreal acot (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal asec (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal acsc (const mpreal& v, mp_rnd_t rnd_mode); + + friend const mpreal cosh (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal sinh (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal tanh (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal sech (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal csch (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal coth (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal acosh (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal asinh (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal atanh (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal acoth (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal asech (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal acsch (const mpreal& v, mp_rnd_t rnd_mode); + + friend const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); + + friend const mpreal fac_ui (unsigned long int v, mp_prec_t prec, mp_rnd_t rnd_mode); + friend const mpreal eint (const mpreal& v, mp_rnd_t rnd_mode); + + friend const mpreal gamma (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal tgamma (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal lngamma (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal lgamma (const mpreal& v, int *signp, mp_rnd_t rnd_mode); + friend const mpreal zeta (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal erf (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal erfc (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal besselj0 (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal besselj1 (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal besseljn (long n, const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal bessely0 (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal bessely1 (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal besselyn (long n, const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode); + friend const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode); + friend const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode); + friend const mpreal sum (const mpreal tab[], const unsigned long int n, int& status, mp_rnd_t rnd_mode); + friend int sgn (const mpreal& v); + +// MPFR 2.4.0 Specifics +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + friend int sinh_cosh (mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal li2 (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); + friend const mpreal rec_sqrt (const mpreal& v, mp_rnd_t rnd_mode); + + // MATLAB's semantic equivalents + friend const mpreal rem (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); // Remainder after division + friend const mpreal mod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); // Modulus after division +#endif + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) + friend const mpreal digamma (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal ai (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal urandom (gmp_randstate_t& state, mp_rnd_t rnd_mode); // use gmp_randinit_default() to init state, gmp_randclear() to clear +#endif + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,1,0)) + friend const mpreal grandom (gmp_randstate_t& state, mp_rnd_t rnd_mode); // use gmp_randinit_default() to init state, gmp_randclear() to clear + friend const mpreal grandom (unsigned int seed); +#endif + + // Uniformly distributed random number generation in [0,1] using + // Mersenne-Twister algorithm by default. + // Use parameter to setup seed, e.g.: random((unsigned)time(NULL)) + // Check urandom() for more precise control. + friend const mpreal random(unsigned int seed); + + // Splits mpreal value into fractional and integer parts. + // Returns fractional part and stores integer part in n. + friend const mpreal modf(const mpreal& v, mpreal& n); + + // Constants + // don't forget to call mpfr_free_cache() for every thread where you are using const-functions + friend const mpreal const_log2 (mp_prec_t prec, mp_rnd_t rnd_mode); + friend const mpreal const_pi (mp_prec_t prec, mp_rnd_t rnd_mode); + friend const mpreal const_euler (mp_prec_t prec, mp_rnd_t rnd_mode); + friend const mpreal const_catalan (mp_prec_t prec, mp_rnd_t rnd_mode); + + // returns +inf iff sign>=0 otherwise -inf + friend const mpreal const_infinity(int sign, mp_prec_t prec); + + // Output/ Input + friend std::ostream& operator<<(std::ostream& os, const mpreal& v); + friend std::istream& operator>>(std::istream& is, mpreal& v); + + // Integer Related Functions + friend const mpreal rint (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal ceil (const mpreal& v); + friend const mpreal floor(const mpreal& v); + friend const mpreal round(const mpreal& v); + friend long lround(const mpreal& v); + friend long long llround(const mpreal& v); + friend const mpreal trunc(const mpreal& v); + friend const mpreal rint_ceil (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal rint_floor (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal rint_round (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal rint_trunc (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal frac (const mpreal& v, mp_rnd_t rnd_mode); + friend const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); + friend const mpreal remquo (const mpreal& x, const mpreal& y, int* q, mp_rnd_t rnd_mode); + + // Miscellaneous Functions + friend const mpreal nexttoward (const mpreal& x, const mpreal& y); + friend const mpreal nextabove (const mpreal& x); + friend const mpreal nextbelow (const mpreal& x); + + // use gmp_randinit_default() to init state, gmp_randclear() to clear + friend const mpreal urandomb (gmp_randstate_t& state); + +// MPFR < 2.4.2 Specifics +#if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2)) + friend const mpreal random2 (mp_size_t size, mp_exp_t exp); +#endif + + // Instance Checkers + friend bool isnan (const mpreal& v); + friend bool isinf (const mpreal& v); + friend bool isfinite (const mpreal& v); + + friend bool isnum (const mpreal& v); + friend bool iszero (const mpreal& v); + friend bool isint (const mpreal& v); + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) + friend bool isregular(const mpreal& v); +#endif + + // Set/Get instance properties + inline mp_prec_t get_prec() const; + inline void set_prec(mp_prec_t prec, mp_rnd_t rnd_mode = get_default_rnd()); // Change precision with rounding mode + + // Aliases for get_prec(), set_prec() - needed for compatibility with std::complex interface + inline mpreal& setPrecision(int Precision, mp_rnd_t RoundingMode = get_default_rnd()); + inline int getPrecision() const; + + // Set mpreal to +/- inf, NaN, +/-0 + mpreal& setInf (int Sign = +1); + mpreal& setNan (); + mpreal& setZero (int Sign = +1); + mpreal& setSign (int Sign, mp_rnd_t RoundingMode = get_default_rnd()); + + //Exponent + mp_exp_t get_exp() const; + int set_exp(mp_exp_t e); + int check_range (int t, mp_rnd_t rnd_mode = get_default_rnd()); + int subnormalize (int t, mp_rnd_t rnd_mode = get_default_rnd()); + + // Inexact conversion from float + inline bool fits_in_bits(double x, int n); + + // Set/Get global properties + static void set_default_prec(mp_prec_t prec); + static void set_default_rnd(mp_rnd_t rnd_mode); + + static mp_exp_t get_emin (void); + static mp_exp_t get_emax (void); + static mp_exp_t get_emin_min (void); + static mp_exp_t get_emin_max (void); + static mp_exp_t get_emax_min (void); + static mp_exp_t get_emax_max (void); + static int set_emin (mp_exp_t exp); + static int set_emax (mp_exp_t exp); + + // Efficient swapping of two mpreal values - needed for std algorithms + friend void swap(mpreal& x, mpreal& y); + + friend const mpreal fmax(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); + friend const mpreal fmin(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode); + +private: + // Human friendly Debug Preview in Visual Studio. + // Put one of these lines: + // + // mpfr::mpreal= ; Show value only + // mpfr::mpreal=, bits ; Show value & precision + // + // at the beginning of + // [Visual Studio Installation Folder]\Common7\Packages\Debugger\autoexp.dat + MPREAL_MSVC_DEBUGVIEW_DATA + + // "Smart" resources deallocation. Checks if instance initialized before deletion. + void clear(::mpfr_ptr); +}; + +////////////////////////////////////////////////////////////////////////// +// Exceptions +class conversion_overflow : public std::exception { +public: + std::string why() { return "inexact conversion from floating point"; } +}; + +////////////////////////////////////////////////////////////////////////// +// Constructors & converters +// Default constructor: creates mp number and initializes it to 0. +inline mpreal::mpreal() +{ + mpfr_init2(mpfr_ptr(), mpreal::get_default_prec()); + mpfr_set_zero_fast(mpfr_ptr()); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const mpreal& u) +{ + mpfr_init2(mpfr_ptr(),mpfr_get_prec(u.mpfr_srcptr())); + mpfr_set (mpfr_ptr(),u.mpfr_srcptr(),mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +#ifdef MPREAL_HAVE_MOVE_SUPPORT +inline mpreal::mpreal(mpreal&& other) +{ + mpfr_set_uninitialized(mpfr_ptr()); // make sure "other" holds null-pointer (in uninitialized state) + mpfr_swap(mpfr_ptr(), other.mpfr_ptr()); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal& mpreal::operator=(mpreal&& other) +{ + if (this != &other) + { + mpfr_swap(mpfr_ptr(), other.mpfr_ptr()); // destructor for "other" will be called just afterwards + MPREAL_MSVC_DEBUGVIEW_CODE; + } + return *this; +} +#endif + +inline mpreal::mpreal(const mpfr_t u, bool shared) +{ + if(shared) + { + std::memcpy(mpfr_ptr(), u, sizeof(mpfr_t)); + } + else + { + mpfr_init2(mpfr_ptr(), mpfr_get_prec(u)); + mpfr_set (mpfr_ptr(), u, mpreal::get_default_rnd()); + } + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const mpf_t u) +{ + mpfr_init2(mpfr_ptr(),(mp_prec_t) mpf_get_prec(u)); // (gmp: mp_bitcnt_t) unsigned long -> long (mpfr: mp_prec_t) + mpfr_set_f(mpfr_ptr(),u,mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mpfr_ptr(), prec); + mpfr_set_z(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mpfr_ptr(), prec); + mpfr_set_q(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mpfr_ptr(), prec); + +#if (MPREAL_DOUBLE_BITS_OVERFLOW > -1) + if(fits_in_bits(u, MPREAL_DOUBLE_BITS_OVERFLOW)) + { + mpfr_set_d(mpfr_ptr(), u, mode); + }else + throw conversion_overflow(); +#else + mpfr_set_d(mpfr_ptr(), u, mode); +#endif + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_ld(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const unsigned long long int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_uj(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const long long int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_sj(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_ui(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_ui(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_si(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_si(mpfr_ptr(), u, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_str(mpfr_ptr(), s, base, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mpreal::mpreal(const std::string& s, mp_prec_t prec, int base, mp_rnd_t mode) +{ + mpfr_init2 (mpfr_ptr(), prec); + mpfr_set_str(mpfr_ptr(), s.c_str(), base, mode); + + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline void mpreal::clear(::mpfr_ptr x) +{ +#ifdef MPREAL_HAVE_MOVE_SUPPORT + if(mpfr_is_initialized(x)) +#endif + mpfr_clear(x); +} + +inline mpreal::~mpreal() +{ + clear(mpfr_ptr()); +} + +// internal namespace needed for template magic +namespace internal{ + + // Use SFINAE to restrict arithmetic operations instantiation only for numeric types + // This is needed for smooth integration with libraries based on expression templates, like Eigen. + // TODO: Do the same for boolean operators. + template struct result_type {}; + + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; + template <> struct result_type {typedef mpreal type;}; +} + +// + Addition +template +inline const typename internal::result_type::type + operator+(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) += rhs; } + +template +inline const typename internal::result_type::type + operator+(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) += lhs; } + +// - Subtraction +template +inline const typename internal::result_type::type + operator-(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) -= rhs; } + +template +inline const typename internal::result_type::type + operator-(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) -= rhs; } + +// * Multiplication +template +inline const typename internal::result_type::type + operator*(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) *= rhs; } + +template +inline const typename internal::result_type::type + operator*(const Lhs& lhs, const mpreal& rhs){ return mpreal(rhs) *= lhs; } + +// / Division +template +inline const typename internal::result_type::type + operator/(const mpreal& lhs, const Rhs& rhs){ return mpreal(lhs) /= rhs; } + +template +inline const typename internal::result_type::type + operator/(const Lhs& lhs, const mpreal& rhs){ return mpreal(lhs) /= rhs; } + +////////////////////////////////////////////////////////////////////////// +// sqrt +const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal sqrt(const long int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal sqrt(const int v, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal sqrt(const long double v, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal sqrt(const double v, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +// abs +inline const mpreal abs(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()); + +////////////////////////////////////////////////////////////////////////// +// pow +const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); +inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::get_default_rnd()); + +////////////////////////////////////////////////////////////////////////// +// Estimate machine epsilon for the given precision +// Returns smallest eps such that 1.0 + eps != 1.0 +inline mpreal machine_epsilon(mp_prec_t prec = mpreal::get_default_prec()); + +// Returns smallest eps such that x + eps != x (relative machine epsilon) +inline mpreal machine_epsilon(const mpreal& x); + +// Gives max & min values for the required precision, +// minval is 'safe' meaning 1 / minval does not overflow +// maxval is 'safe' meaning 1 / maxval does not underflow +inline mpreal minval(mp_prec_t prec = mpreal::get_default_prec()); +inline mpreal maxval(mp_prec_t prec = mpreal::get_default_prec()); + +// 'Dirty' equality check 1: |a-b| < min{|a|,|b|} * eps +inline bool isEqualFuzzy(const mpreal& a, const mpreal& b, const mpreal& eps); + +// 'Dirty' equality check 2: |a-b| < min{|a|,|b|} * eps( min{|a|,|b|} ) +inline bool isEqualFuzzy(const mpreal& a, const mpreal& b); + +// 'Bitwise' equality check +// maxUlps - a and b can be apart by maxUlps binary numbers. +inline bool isEqualUlps(const mpreal& a, const mpreal& b, int maxUlps); + +////////////////////////////////////////////////////////////////////////// +// Convert precision in 'bits' to decimal digits and vice versa. +// bits = ceil(digits*log[2](10)) +// digits = floor(bits*log[10](2)) + +inline mp_prec_t digits2bits(int d); +inline int bits2digits(mp_prec_t b); + +////////////////////////////////////////////////////////////////////////// +// min, max +const mpreal (max)(const mpreal& x, const mpreal& y); +const mpreal (min)(const mpreal& x, const mpreal& y); + +////////////////////////////////////////////////////////////////////////// +// Implementation +////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////// +// Operators - Assignment +inline mpreal& mpreal::operator=(const mpreal& v) +{ + if (this != &v) + { + mp_prec_t tp = mpfr_get_prec( mpfr_srcptr()); + mp_prec_t vp = mpfr_get_prec(v.mpfr_srcptr()); + + if(tp != vp){ + clear(mpfr_ptr()); + mpfr_init2(mpfr_ptr(), vp); + } + + mpfr_set(mpfr_ptr(), v.mpfr_srcptr(), mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + } + return *this; +} + +inline mpreal& mpreal::operator=(const mpf_t v) +{ + mpfr_set_f(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const mpz_t v) +{ + mpfr_set_z(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const mpq_t v) +{ + mpfr_set_q(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const long double v) +{ + mpfr_set_ld(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const double v) +{ +#if (MPREAL_DOUBLE_BITS_OVERFLOW > -1) + if(fits_in_bits(v, MPREAL_DOUBLE_BITS_OVERFLOW)) + { + mpfr_set_d(mpfr_ptr(),v,mpreal::get_default_rnd()); + }else + throw conversion_overflow(); +#else + mpfr_set_d(mpfr_ptr(),v,mpreal::get_default_rnd()); +#endif + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const unsigned long int v) +{ + mpfr_set_ui(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const unsigned int v) +{ + mpfr_set_ui(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const unsigned long long int v) +{ + mpfr_set_uj(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const long long int v) +{ + mpfr_set_sj(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const long int v) +{ + mpfr_set_si(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const int v) +{ + mpfr_set_si(mpfr_ptr(), v, mpreal::get_default_rnd()); + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator=(const char* s) +{ + // Use other converters for more precise control on base & precision & rounding: + // + // mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode) + // mpreal(const std::string& s,mp_prec_t prec, int base, mp_rnd_t mode) + // + // Here we assume base = 10 and we use precision of target variable. + + mpfr_t t; + + mpfr_init2(t, mpfr_get_prec(mpfr_srcptr())); + + if(0 == mpfr_set_str(t, s, 10, mpreal::get_default_rnd())) + { + mpfr_set(mpfr_ptr(), t, mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + } + + clear(t); + return *this; +} + +inline mpreal& mpreal::operator=(const std::string& s) +{ + // Use other converters for more precise control on base & precision & rounding: + // + // mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode) + // mpreal(const std::string& s,mp_prec_t prec, int base, mp_rnd_t mode) + // + // Here we assume base = 10 and we use precision of target variable. + + mpfr_t t; + + mpfr_init2(t, mpfr_get_prec(mpfr_srcptr())); + + if(0 == mpfr_set_str(t, s.c_str(), 10, mpreal::get_default_rnd())) + { + mpfr_set(mpfr_ptr(), t, mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + } + + clear(t); + return *this; +} + +template +inline mpreal& mpreal::operator= (const std::complex& z) +{ + return *this = z.real(); +} + +////////////////////////////////////////////////////////////////////////// +// + Addition +inline mpreal& mpreal::operator+=(const mpreal& v) +{ + mpfr_add(mpfr_ptr(), mpfr_srcptr(), v.mpfr_srcptr(), mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+=(const mpf_t u) +{ + *this += mpreal(u); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+=(const mpz_t u) +{ + mpfr_add_z(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+=(const mpq_t u) +{ + mpfr_add_q(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+= (const long double u) +{ + *this += mpreal(u); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+= (const double u) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpfr_add_d(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); +#else + *this += mpreal(u); +#endif + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+=(const unsigned long int u) +{ + mpfr_add_ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+=(const unsigned int u) +{ + mpfr_add_ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+=(const long int u) +{ + mpfr_add_si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+=(const int u) +{ + mpfr_add_si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator+=(const long long int u) { *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; } +inline mpreal& mpreal::operator+=(const unsigned long long int u){ *this += mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; } +inline mpreal& mpreal::operator-=(const long long int u) { *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; } +inline mpreal& mpreal::operator-=(const unsigned long long int u){ *this -= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; } +inline mpreal& mpreal::operator*=(const long long int u) { *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; } +inline mpreal& mpreal::operator*=(const unsigned long long int u){ *this *= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; } +inline mpreal& mpreal::operator/=(const long long int u) { *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; } +inline mpreal& mpreal::operator/=(const unsigned long long int u){ *this /= mpreal(u); MPREAL_MSVC_DEBUGVIEW_CODE; return *this; } + +inline const mpreal mpreal::operator+()const { return mpreal(*this); } + +inline const mpreal operator+(const mpreal& a, const mpreal& b) +{ + mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr()))); + mpfr_add(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd()); + return c; +} + +inline mpreal& mpreal::operator++() +{ + return *this += 1; +} + +inline const mpreal mpreal::operator++ (int) +{ + mpreal x(*this); + *this += 1; + return x; +} + +inline mpreal& mpreal::operator--() +{ + return *this -= 1; +} + +inline const mpreal mpreal::operator-- (int) +{ + mpreal x(*this); + *this -= 1; + return x; +} + +////////////////////////////////////////////////////////////////////////// +// - Subtraction +inline mpreal& mpreal::operator-=(const mpreal& v) +{ + mpfr_sub(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator-=(const mpz_t v) +{ + mpfr_sub_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator-=(const mpq_t v) +{ + mpfr_sub_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator-=(const long double v) +{ + *this -= mpreal(v); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator-=(const double v) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpfr_sub_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); +#else + *this -= mpreal(v); +#endif + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator-=(const unsigned long int v) +{ + mpfr_sub_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator-=(const unsigned int v) +{ + mpfr_sub_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator-=(const long int v) +{ + mpfr_sub_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator-=(const int v) +{ + mpfr_sub_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline const mpreal mpreal::operator-()const +{ + mpreal u(*this); + mpfr_neg(u.mpfr_ptr(),u.mpfr_srcptr(),mpreal::get_default_rnd()); + return u; +} + +inline const mpreal operator-(const mpreal& a, const mpreal& b) +{ + mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr()))); + mpfr_sub(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd()); + return c; +} + +inline const mpreal operator-(const double b, const mpreal& a) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpreal x(0, mpfr_get_prec(a.mpfr_ptr())); + mpfr_d_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +#else + mpreal x(b, mpfr_get_prec(a.mpfr_ptr())); + x -= a; + return x; +#endif +} + +inline const mpreal operator-(const unsigned long int b, const mpreal& a) +{ + mpreal x(0, mpfr_get_prec(a.mpfr_ptr())); + mpfr_ui_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +} + +inline const mpreal operator-(const unsigned int b, const mpreal& a) +{ + mpreal x(0, mpfr_get_prec(a.mpfr_ptr())); + mpfr_ui_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +} + +inline const mpreal operator-(const long int b, const mpreal& a) +{ + mpreal x(0, mpfr_get_prec(a.mpfr_ptr())); + mpfr_si_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +} + +inline const mpreal operator-(const int b, const mpreal& a) +{ + mpreal x(0, mpfr_get_prec(a.mpfr_ptr())); + mpfr_si_sub(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +} + +////////////////////////////////////////////////////////////////////////// +// * Multiplication +inline mpreal& mpreal::operator*= (const mpreal& v) +{ + mpfr_mul(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator*=(const mpz_t v) +{ + mpfr_mul_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator*=(const mpq_t v) +{ + mpfr_mul_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator*=(const long double v) +{ + *this *= mpreal(v); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator*=(const double v) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpfr_mul_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); +#else + *this *= mpreal(v); +#endif + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator*=(const unsigned long int v) +{ + mpfr_mul_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator*=(const unsigned int v) +{ + mpfr_mul_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator*=(const long int v) +{ + mpfr_mul_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator*=(const int v) +{ + mpfr_mul_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline const mpreal operator*(const mpreal& a, const mpreal& b) +{ + mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_ptr()), mpfr_get_prec(b.mpfr_ptr()))); + mpfr_mul(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd()); + return c; +} + +////////////////////////////////////////////////////////////////////////// +// / Division +inline mpreal& mpreal::operator/=(const mpreal& v) +{ + mpfr_div(mpfr_ptr(),mpfr_srcptr(),v.mpfr_srcptr(),mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator/=(const mpz_t v) +{ + mpfr_div_z(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator/=(const mpq_t v) +{ + mpfr_div_q(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator/=(const long double v) +{ + *this /= mpreal(v); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator/=(const double v) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpfr_div_d(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); +#else + *this /= mpreal(v); +#endif + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator/=(const unsigned long int v) +{ + mpfr_div_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator/=(const unsigned int v) +{ + mpfr_div_ui(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator/=(const long int v) +{ + mpfr_div_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator/=(const int v) +{ + mpfr_div_si(mpfr_ptr(),mpfr_srcptr(),v,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline const mpreal operator/(const mpreal& a, const mpreal& b) +{ + mpreal c(0, (std::max)(mpfr_get_prec(a.mpfr_srcptr()), mpfr_get_prec(b.mpfr_srcptr()))); + mpfr_div(c.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), mpreal::get_default_rnd()); + return c; +} + +inline const mpreal operator/(const unsigned long int b, const mpreal& a) +{ + mpreal x(0, mpfr_get_prec(a.mpfr_srcptr())); + mpfr_ui_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +} + +inline const mpreal operator/(const unsigned int b, const mpreal& a) +{ + mpreal x(0, mpfr_get_prec(a.mpfr_srcptr())); + mpfr_ui_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +} + +inline const mpreal operator/(const long int b, const mpreal& a) +{ + mpreal x(0, mpfr_get_prec(a.mpfr_srcptr())); + mpfr_si_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +} + +inline const mpreal operator/(const int b, const mpreal& a) +{ + mpreal x(0, mpfr_get_prec(a.mpfr_srcptr())); + mpfr_si_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +} + +inline const mpreal operator/(const double b, const mpreal& a) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpreal x(0, mpfr_get_prec(a.mpfr_srcptr())); + mpfr_d_div(x.mpfr_ptr(), b, a.mpfr_srcptr(), mpreal::get_default_rnd()); + return x; +#else + mpreal x(b, mpfr_get_prec(a.mpfr_ptr())); + x /= a; + return x; +#endif +} + +////////////////////////////////////////////////////////////////////////// +// Shifts operators - Multiplication/Division by power of 2 +inline mpreal& mpreal::operator<<=(const unsigned long int u) +{ + mpfr_mul_2ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator<<=(const unsigned int u) +{ + mpfr_mul_2ui(mpfr_ptr(),mpfr_srcptr(),static_cast(u),mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator<<=(const long int u) +{ + mpfr_mul_2si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator<<=(const int u) +{ + mpfr_mul_2si(mpfr_ptr(),mpfr_srcptr(),static_cast(u),mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator>>=(const unsigned long int u) +{ + mpfr_div_2ui(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator>>=(const unsigned int u) +{ + mpfr_div_2ui(mpfr_ptr(),mpfr_srcptr(),static_cast(u),mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator>>=(const long int u) +{ + mpfr_div_2si(mpfr_ptr(),mpfr_srcptr(),u,mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::operator>>=(const int u) +{ + mpfr_div_2si(mpfr_ptr(),mpfr_srcptr(),static_cast(u),mpreal::get_default_rnd()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline const mpreal operator<<(const mpreal& v, const unsigned long int k) +{ + return mul_2ui(v,k); +} + +inline const mpreal operator<<(const mpreal& v, const unsigned int k) +{ + return mul_2ui(v,static_cast(k)); +} + +inline const mpreal operator<<(const mpreal& v, const long int k) +{ + return mul_2si(v,k); +} + +inline const mpreal operator<<(const mpreal& v, const int k) +{ + return mul_2si(v,static_cast(k)); +} + +inline const mpreal operator>>(const mpreal& v, const unsigned long int k) +{ + return div_2ui(v,k); +} + +inline const mpreal operator>>(const mpreal& v, const long int k) +{ + return div_2si(v,k); +} + +inline const mpreal operator>>(const mpreal& v, const unsigned int k) +{ + return div_2ui(v,static_cast(k)); +} + +inline const mpreal operator>>(const mpreal& v, const int k) +{ + return div_2si(v,static_cast(k)); +} + +// mul_2ui +inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_mul_2ui(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode); + return x; +} + +// mul_2si +inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_mul_2si(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode); + return x; +} + +inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_div_2ui(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode); + return x; +} + +inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_div_2si(x.mpfr_ptr(),v.mpfr_srcptr(),k,rnd_mode); + return x; +} + +////////////////////////////////////////////////////////////////////////// +//Relational operators + +// WARNING: +// +// Please note that following checks for double-NaN are guaranteed to work only in IEEE math mode: +// +// isnan(b) = (b != b) +// isnan(b) = !(b == b) (we use in code below) +// +// Be cautions if you use compiler options which break strict IEEE compliance (e.g. -ffast-math in GCC). +// Use std::isnan instead (C++11). + +inline bool operator > (const mpreal& a, const mpreal& b ){ return (mpfr_greater_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 ); } +inline bool operator > (const mpreal& a, const unsigned long int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) > 0 ); } +inline bool operator > (const mpreal& a, const unsigned int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) > 0 ); } +inline bool operator > (const mpreal& a, const long int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) > 0 ); } +inline bool operator > (const mpreal& a, const int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) > 0 ); } +inline bool operator > (const mpreal& a, const long double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) > 0 ); } +inline bool operator > (const mpreal& a, const double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) > 0 ); } + +inline bool operator >= (const mpreal& a, const mpreal& b ){ return (mpfr_greaterequal_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 ); } +inline bool operator >= (const mpreal& a, const unsigned long int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) >= 0 ); } +inline bool operator >= (const mpreal& a, const unsigned int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) >= 0 ); } +inline bool operator >= (const mpreal& a, const long int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) >= 0 ); } +inline bool operator >= (const mpreal& a, const int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) >= 0 ); } +inline bool operator >= (const mpreal& a, const long double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) >= 0 ); } +inline bool operator >= (const mpreal& a, const double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) >= 0 ); } + +inline bool operator < (const mpreal& a, const mpreal& b ){ return (mpfr_less_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 ); } +inline bool operator < (const mpreal& a, const unsigned long int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) < 0 ); } +inline bool operator < (const mpreal& a, const unsigned int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) < 0 ); } +inline bool operator < (const mpreal& a, const long int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) < 0 ); } +inline bool operator < (const mpreal& a, const int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) < 0 ); } +inline bool operator < (const mpreal& a, const long double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) < 0 ); } +inline bool operator < (const mpreal& a, const double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) < 0 ); } + +inline bool operator <= (const mpreal& a, const mpreal& b ){ return (mpfr_lessequal_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 ); } +inline bool operator <= (const mpreal& a, const unsigned long int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) <= 0 ); } +inline bool operator <= (const mpreal& a, const unsigned int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) <= 0 ); } +inline bool operator <= (const mpreal& a, const long int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) <= 0 ); } +inline bool operator <= (const mpreal& a, const int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) <= 0 ); } +inline bool operator <= (const mpreal& a, const long double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) <= 0 ); } +inline bool operator <= (const mpreal& a, const double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) <= 0 ); } + +inline bool operator == (const mpreal& a, const mpreal& b ){ return (mpfr_equal_p(a.mpfr_srcptr(),b.mpfr_srcptr()) != 0 ); } +inline bool operator == (const mpreal& a, const unsigned long int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) == 0 ); } +inline bool operator == (const mpreal& a, const unsigned int b ){ return !isnan(a) && (mpfr_cmp_ui(a.mpfr_srcptr(),b) == 0 ); } +inline bool operator == (const mpreal& a, const long int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) == 0 ); } +inline bool operator == (const mpreal& a, const int b ){ return !isnan(a) && (mpfr_cmp_si(a.mpfr_srcptr(),b) == 0 ); } +inline bool operator == (const mpreal& a, const long double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_ld(a.mpfr_srcptr(),b) == 0 ); } +inline bool operator == (const mpreal& a, const double b ){ return !isnan(a) && (b == b) && (mpfr_cmp_d (a.mpfr_srcptr(),b) == 0 ); } + +inline bool operator != (const mpreal& a, const mpreal& b ){ return !(a == b); } +inline bool operator != (const mpreal& a, const unsigned long int b ){ return !(a == b); } +inline bool operator != (const mpreal& a, const unsigned int b ){ return !(a == b); } +inline bool operator != (const mpreal& a, const long int b ){ return !(a == b); } +inline bool operator != (const mpreal& a, const int b ){ return !(a == b); } +inline bool operator != (const mpreal& a, const long double b ){ return !(a == b); } +inline bool operator != (const mpreal& a, const double b ){ return !(a == b); } + +inline bool isnan (const mpreal& op){ return (mpfr_nan_p (op.mpfr_srcptr()) != 0 ); } +inline bool isinf (const mpreal& op){ return (mpfr_inf_p (op.mpfr_srcptr()) != 0 ); } +inline bool isfinite (const mpreal& op){ return (mpfr_number_p (op.mpfr_srcptr()) != 0 ); } +inline bool iszero (const mpreal& op){ return (mpfr_zero_p (op.mpfr_srcptr()) != 0 ); } +inline bool isint (const mpreal& op){ return (mpfr_integer_p(op.mpfr_srcptr()) != 0 ); } + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) +inline bool isregular(const mpreal& op){ return (mpfr_regular_p(op.mpfr_srcptr()));} +#endif + +////////////////////////////////////////////////////////////////////////// +// Type Converters +inline bool mpreal::toBool ( ) const { return mpfr_zero_p (mpfr_srcptr()) == 0; } +inline long mpreal::toLong (mp_rnd_t mode) const { return mpfr_get_si (mpfr_srcptr(), mode); } +inline unsigned long mpreal::toULong (mp_rnd_t mode) const { return mpfr_get_ui (mpfr_srcptr(), mode); } +inline float mpreal::toFloat (mp_rnd_t mode) const { return mpfr_get_flt(mpfr_srcptr(), mode); } +inline double mpreal::toDouble (mp_rnd_t mode) const { return mpfr_get_d (mpfr_srcptr(), mode); } +inline long double mpreal::toLDouble(mp_rnd_t mode) const { return mpfr_get_ld (mpfr_srcptr(), mode); } +inline long long mpreal::toLLong (mp_rnd_t mode) const { return mpfr_get_sj (mpfr_srcptr(), mode); } +inline unsigned long long mpreal::toULLong (mp_rnd_t mode) const { return mpfr_get_uj (mpfr_srcptr(), mode); } + +inline ::mpfr_ptr mpreal::mpfr_ptr() { return mp; } +inline ::mpfr_srcptr mpreal::mpfr_ptr() const { return mp; } +inline ::mpfr_srcptr mpreal::mpfr_srcptr() const { return mp; } + +template +inline std::string toString(T t, std::ios_base & (*f)(std::ios_base&)) +{ + std::ostringstream oss; + oss << f << t; + return oss.str(); +} + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + +inline std::string mpreal::toString(const std::string& format) const +{ + char *s = NULL; + std::string out; + + if( !format.empty() ) + { + if(!(mpfr_asprintf(&s, format.c_str(), mpfr_srcptr()) < 0)) + { + out = std::string(s); + + mpfr_free_str(s); + } + } + + return out; +} + +#endif + +inline std::string mpreal::toString(int n, int b, mp_rnd_t mode) const +{ + // TODO: Add extended format specification (f, e, rounding mode) as it done in output operator + (void)b; + (void)mode; + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + + std::ostringstream format; + + int digits = (n >= 0) ? n : 2 + bits2digits(mpfr_get_prec(mpfr_srcptr())); + + format << "%." << digits << "RNg"; + + return toString(format.str()); + +#else + + char *s, *ns = NULL; + size_t slen, nslen; + mp_exp_t exp; + std::string out; + + if(mpfr_inf_p(mp)) + { + if(mpfr_sgn(mp)>0) return "+Inf"; + else return "-Inf"; + } + + if(mpfr_zero_p(mp)) return "0"; + if(mpfr_nan_p(mp)) return "NaN"; + + s = mpfr_get_str(NULL, &exp, b, 0, mp, mode); + ns = mpfr_get_str(NULL, &exp, b, (std::max)(0,n), mp, mode); + + if(s!=NULL && ns!=NULL) + { + slen = strlen(s); + nslen = strlen(ns); + if(nslen<=slen) + { + mpfr_free_str(s); + s = ns; + slen = nslen; + } + else { + mpfr_free_str(ns); + } + + // Make human eye-friendly formatting if possible + if (exp>0 && static_cast(exp)s+exp) ptr--; + + if(ptr==s+exp) out = std::string(s,exp+1); + else out = std::string(s,exp+1)+'.'+std::string(s+exp+1,ptr-(s+exp+1)+1); + + //out = string(s,exp+1)+'.'+string(s+exp+1); + } + else + { + // Remove zeros starting from right end + char* ptr = s+slen-1; + while (*ptr=='0' && ptr>s+exp-1) ptr--; + + if(ptr==s+exp-1) out = std::string(s,exp); + else out = std::string(s,exp)+'.'+std::string(s+exp,ptr-(s+exp)+1); + + //out = string(s,exp)+'.'+string(s+exp); + } + + }else{ // exp<0 || exp>slen + if(s[0]=='-') + { + // Remove zeros starting from right end + char* ptr = s+slen-1; + while (*ptr=='0' && ptr>s+1) ptr--; + + if(ptr==s+1) out = std::string(s,2); + else out = std::string(s,2)+'.'+std::string(s+2,ptr-(s+2)+1); + + //out = string(s,2)+'.'+string(s+2); + } + else + { + // Remove zeros starting from right end + char* ptr = s+slen-1; + while (*ptr=='0' && ptr>s) ptr--; + + if(ptr==s) out = std::string(s,1); + else out = std::string(s,1)+'.'+std::string(s+1,ptr-(s+1)+1); + + //out = string(s,1)+'.'+string(s+1); + } + + // Make final string + if(--exp) + { + if(exp>0) out += "e+"+mpfr::toString(exp,std::dec); + else out += "e"+mpfr::toString(exp,std::dec); + } + } + + mpfr_free_str(s); + return out; + }else{ + return "conversion error!"; + } +#endif +} + + +////////////////////////////////////////////////////////////////////////// +// I/O +inline std::ostream& mpreal::output(std::ostream& os) const +{ + std::ostringstream format; + const std::ios::fmtflags flags = os.flags(); + + format << ((flags & std::ios::showpos) ? "%+" : "%"); + if (os.precision() >= 0) + format << '.' << os.precision() << "R*" + << ((flags & std::ios::floatfield) == std::ios::fixed ? 'f' : + (flags & std::ios::floatfield) == std::ios::scientific ? 'e' : + 'g'); + else + format << "R*e"; + + char *s = NULL; + if(!(mpfr_asprintf(&s, format.str().c_str(), + mpfr::mpreal::get_default_rnd(), + mpfr_srcptr()) + < 0)) + { + os << std::string(s); + mpfr_free_str(s); + } + return os; +} + +inline std::ostream& operator<<(std::ostream& os, const mpreal& v) +{ + return v.output(os); +} + +inline std::istream& operator>>(std::istream &is, mpreal& v) +{ + // TODO: use cout::hexfloat and other flags to setup base + std::string tmp; + is >> tmp; + mpfr_set_str(v.mpfr_ptr(), tmp.c_str(), 10, mpreal::get_default_rnd()); + return is; +} + +////////////////////////////////////////////////////////////////////////// +// Bits - decimal digits relation +// bits = ceil(digits*log[2](10)) +// digits = floor(bits*log[10](2)) + +inline mp_prec_t digits2bits(int d) +{ + const double LOG2_10 = 3.3219280948873624; + + return mp_prec_t(std::ceil( d * LOG2_10 )); +} + +inline int bits2digits(mp_prec_t b) +{ + const double LOG10_2 = 0.30102999566398119; + + return int(std::floor( b * LOG10_2 )); +} + +////////////////////////////////////////////////////////////////////////// +// Set/Get number properties +inline mpreal& mpreal::setSign(int sign, mp_rnd_t RoundingMode) +{ + mpfr_setsign(mpfr_ptr(), mpfr_srcptr(), sign < 0, RoundingMode); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline int mpreal::getPrecision() const +{ + return int(mpfr_get_prec(mpfr_srcptr())); +} + +inline mpreal& mpreal::setPrecision(int Precision, mp_rnd_t RoundingMode) +{ + mpfr_prec_round(mpfr_ptr(), Precision, RoundingMode); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::setInf(int sign) +{ + mpfr_set_inf(mpfr_ptr(), sign); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::setNan() +{ + mpfr_set_nan(mpfr_ptr()); + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mpreal& mpreal::setZero(int sign) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) + mpfr_set_zero(mpfr_ptr(), sign); +#else + mpfr_set_si(mpfr_ptr(), 0, (mpfr_get_default_rounding_mode)()); + setSign(sign); +#endif + + MPREAL_MSVC_DEBUGVIEW_CODE; + return *this; +} + +inline mp_prec_t mpreal::get_prec() const +{ + return mpfr_get_prec(mpfr_srcptr()); +} + +inline void mpreal::set_prec(mp_prec_t prec, mp_rnd_t rnd_mode) +{ + mpfr_prec_round(mpfr_ptr(),prec,rnd_mode); + MPREAL_MSVC_DEBUGVIEW_CODE; +} + +inline mp_exp_t mpreal::get_exp () const +{ + return mpfr_get_exp(mpfr_srcptr()); +} + +inline int mpreal::set_exp (mp_exp_t e) +{ + int x = mpfr_set_exp(mpfr_ptr(), e); + MPREAL_MSVC_DEBUGVIEW_CODE; + return x; +} + +inline mpreal& negate(mpreal& x) // -x in place +{ + mpfr_neg(x.mpfr_ptr(),x.mpfr_srcptr(),mpreal::get_default_rnd()); + return x; +} + +inline const mpreal frexp(const mpreal& x, mp_exp_t* exp, mp_rnd_t mode = mpreal::get_default_rnd()) +{ + mpreal y(x); +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,1,0)) + mpfr_frexp(exp,y.mpfr_ptr(),x.mpfr_srcptr(),mode); +#else + *exp = mpfr_get_exp(y.mpfr_srcptr()); + mpfr_set_exp(y.mpfr_ptr(),0); +#endif + return y; +} + +inline const mpreal frexp(const mpreal& x, int* exp, mp_rnd_t mode = mpreal::get_default_rnd()) +{ + mp_exp_t expl; + mpreal y = frexp(x, &expl, mode); + *exp = int(expl); + return y; +} + +inline const mpreal ldexp(const mpreal& v, mp_exp_t exp) +{ + mpreal x(v); + + // rounding is not important since we are just increasing the exponent (= exact operation) + mpfr_mul_2si(x.mpfr_ptr(), x.mpfr_srcptr(), exp, mpreal::get_default_rnd()); + return x; +} + +inline const mpreal scalbn(const mpreal& v, mp_exp_t exp) +{ + return ldexp(v, exp); +} + +inline mpreal machine_epsilon(mp_prec_t prec) +{ + /* the smallest eps such that 1 + eps != 1 */ + return machine_epsilon(mpreal(1, prec)); +} + +inline mpreal machine_epsilon(const mpreal& x) +{ + /* the smallest eps such that x + eps != x */ + if( x < 0) + { + return nextabove(-x) + x; + }else{ + return nextabove( x) - x; + } +} + +// minval is 'safe' meaning 1 / minval does not overflow +inline mpreal minval(mp_prec_t prec) +{ + /* min = 1/2 * 2^emin = 2^(emin - 1) */ + return mpreal(1, prec) << mpreal::get_emin()-1; +} + +// maxval is 'safe' meaning 1 / maxval does not underflow +inline mpreal maxval(mp_prec_t prec) +{ + /* max = (1 - eps) * 2^emax, eps is machine epsilon */ + return (mpreal(1, prec) - machine_epsilon(prec)) << mpreal::get_emax(); +} + +inline bool isEqualUlps(const mpreal& a, const mpreal& b, int maxUlps) +{ + return abs(a - b) <= machine_epsilon((max)(abs(a), abs(b))) * maxUlps; +} + +inline bool isEqualFuzzy(const mpreal& a, const mpreal& b, const mpreal& eps) +{ + return abs(a - b) <= eps; +} + +inline bool isEqualFuzzy(const mpreal& a, const mpreal& b) +{ + return isEqualFuzzy(a, b, machine_epsilon((max)(1, (min)(abs(a), abs(b))))); +} + +////////////////////////////////////////////////////////////////////////// +// C++11 sign functions. +inline mpreal copysign(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal rop(0, mpfr_get_prec(x.mpfr_ptr())); + mpfr_setsign(rop.mpfr_ptr(), x.mpfr_srcptr(), mpfr_signbit(y.mpfr_srcptr()), rnd_mode); + return rop; +} + +inline bool signbit(const mpreal& x) +{ + return mpfr_signbit(x.mpfr_srcptr()); +} + +inline mpreal& setsignbit(mpreal& x, bool minus, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpfr_setsign(x.mpfr_ptr(), x.mpfr_srcptr(), minus, rnd_mode); + return x; +} + +inline const mpreal modf(const mpreal& v, mpreal& n) +{ + mpreal f(v); + + // rounding is not important since we are using the same number + mpfr_frac (f.mpfr_ptr(),f.mpfr_srcptr(),mpreal::get_default_rnd()); + mpfr_trunc(n.mpfr_ptr(),v.mpfr_srcptr()); + return f; +} + +inline int mpreal::check_range (int t, mp_rnd_t rnd_mode) +{ + return mpfr_check_range(mpfr_ptr(),t,rnd_mode); +} + +inline int mpreal::subnormalize (int t,mp_rnd_t rnd_mode) +{ + int r = mpfr_subnormalize(mpfr_ptr(),t,rnd_mode); + MPREAL_MSVC_DEBUGVIEW_CODE; + return r; +} + +inline mp_exp_t mpreal::get_emin (void) +{ + return mpfr_get_emin(); +} + +inline int mpreal::set_emin (mp_exp_t exp) +{ + return mpfr_set_emin(exp); +} + +inline mp_exp_t mpreal::get_emax (void) +{ + return mpfr_get_emax(); +} + +inline int mpreal::set_emax (mp_exp_t exp) +{ + return mpfr_set_emax(exp); +} + +inline mp_exp_t mpreal::get_emin_min (void) +{ + return mpfr_get_emin_min(); +} + +inline mp_exp_t mpreal::get_emin_max (void) +{ + return mpfr_get_emin_max(); +} + +inline mp_exp_t mpreal::get_emax_min (void) +{ + return mpfr_get_emax_min(); +} + +inline mp_exp_t mpreal::get_emax_max (void) +{ + return mpfr_get_emax_max(); +} + +////////////////////////////////////////////////////////////////////////// +// Mathematical Functions +////////////////////////////////////////////////////////////////////////// + +// Unary function template with single 'mpreal' argument +#define MPREAL_UNARY_MATH_FUNCTION_BODY(f) \ + mpreal y(0, mpfr_get_prec(x.mpfr_srcptr())); \ + mpfr_##f(y.mpfr_ptr(), x.mpfr_srcptr(), r); \ + return y; + +// Binary function template with 'mpreal' and 'unsigned long' arguments +#define MPREAL_BINARY_MATH_FUNCTION_UI_BODY(f, u) \ + mpreal y(0, mpfr_get_prec(x.mpfr_srcptr())); \ + mpfr_##f(y.mpfr_ptr(), x.mpfr_srcptr(), u, r); \ + return y; + +inline const mpreal sqr (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) +{ MPREAL_UNARY_MATH_FUNCTION_BODY(sqr ); } + +inline const mpreal sqrt (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) +{ MPREAL_UNARY_MATH_FUNCTION_BODY(sqrt); } + +inline const mpreal sqrt(const unsigned long int x, mp_rnd_t r) +{ + mpreal y; + mpfr_sqrt_ui(y.mpfr_ptr(), x, r); + return y; +} + +inline const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode) +{ + return sqrt(static_cast(v),rnd_mode); +} + +inline const mpreal sqrt(const long int v, mp_rnd_t rnd_mode) +{ + if (v>=0) return sqrt(static_cast(v),rnd_mode); + else return mpreal().setNan(); // NaN +} + +inline const mpreal sqrt(const int v, mp_rnd_t rnd_mode) +{ + if (v>=0) return sqrt(static_cast(v),rnd_mode); + else return mpreal().setNan(); // NaN +} + +inline const mpreal root(const mpreal& x, unsigned long int k, mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal y(0, mpfr_get_prec(x.mpfr_srcptr())); +#if (MPFR_VERSION >= MPFR_VERSION_NUM(4,0,0)) + mpfr_rootn_ui(y.mpfr_ptr(), x.mpfr_srcptr(), k, r); +#else + mpfr_root(y.mpfr_ptr(), x.mpfr_srcptr(), k, r); +#endif + return y; +} + +inline const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal y(0, mpfr_get_prec(a.mpfr_srcptr())); + mpfr_dim(y.mpfr_ptr(), a.mpfr_srcptr(), b.mpfr_srcptr(), r); + return y; +} + +inline int cmpabs(const mpreal& a,const mpreal& b) +{ + return mpfr_cmpabs(a.mpfr_ptr(), b.mpfr_srcptr()); +} + +inline int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + return mpfr_sin_cos(s.mpfr_ptr(), c.mpfr_ptr(), v.mpfr_srcptr(), rnd_mode); +} + +inline const mpreal sqrt (const long double v, mp_rnd_t rnd_mode) { return sqrt(mpreal(v),rnd_mode); } +inline const mpreal sqrt (const double v, mp_rnd_t rnd_mode) { return sqrt(mpreal(v),rnd_mode); } + +inline const mpreal cbrt (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(cbrt ); } +inline const mpreal fabs (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(abs ); } +inline const mpreal abs (const mpreal& x, mp_rnd_t r) { MPREAL_UNARY_MATH_FUNCTION_BODY(abs ); } +inline const mpreal log (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(log ); } +inline const mpreal log2 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(log2 ); } +inline const mpreal log10 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(log10); } +inline const mpreal exp (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(exp ); } +inline const mpreal exp2 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(exp2 ); } +inline const mpreal exp10 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(exp10); } +inline const mpreal cos (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(cos ); } +inline const mpreal sin (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(sin ); } +inline const mpreal tan (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(tan ); } +inline const mpreal sec (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(sec ); } +inline const mpreal csc (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(csc ); } +inline const mpreal cot (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(cot ); } +inline const mpreal acos (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(acos ); } +inline const mpreal asin (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(asin ); } +inline const mpreal atan (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(atan ); } + +inline const mpreal logb (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { return log2 (abs(x),r); } +inline mp_exp_t ilogb (const mpreal& x) { return x.get_exp(); } + +inline const mpreal acot (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) { return atan (1/v, r); } +inline const mpreal asec (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) { return acos (1/v, r); } +inline const mpreal acsc (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) { return asin (1/v, r); } +inline const mpreal acoth (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) { return atanh(1/v, r); } +inline const mpreal asech (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) { return acosh(1/v, r); } +inline const mpreal acsch (const mpreal& v, mp_rnd_t r = mpreal::get_default_rnd()) { return asinh(1/v, r); } + +inline const mpreal cosh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(cosh ); } +inline const mpreal sinh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(sinh ); } +inline const mpreal tanh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(tanh ); } +inline const mpreal sech (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(sech ); } +inline const mpreal csch (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(csch ); } +inline const mpreal coth (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(coth ); } +inline const mpreal acosh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(acosh); } +inline const mpreal asinh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(asinh); } +inline const mpreal atanh (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(atanh); } + +inline const mpreal log1p (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(log1p ); } +inline const mpreal expm1 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(expm1 ); } +inline const mpreal eint (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(eint ); } +inline const mpreal gamma (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(gamma ); } +inline const mpreal tgamma (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(gamma ); } +inline const mpreal lngamma (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(lngamma); } +inline const mpreal zeta (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(zeta ); } +inline const mpreal erf (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(erf ); } +inline const mpreal erfc (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(erfc ); } +inline const mpreal besselj0(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(j0 ); } +inline const mpreal besselj1(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(j1 ); } +inline const mpreal bessely0(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(y0 ); } +inline const mpreal bessely1(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(y1 ); } + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(4,0,0)) +inline const mpreal gammainc (const mpreal& a, const mpreal& x, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + /* + The non-normalized (upper) incomplete gamma function of a and x: + gammainc(a,x) := Gamma(a,x) = int(t^(a-1) * exp(-t), t=x..infinity) + */ + mpreal y(0,(std::max)(a.getPrecision(), x.getPrecision())); + mpfr_gamma_inc(y.mpfr_ptr(), a.mpfr_srcptr(), x.mpfr_srcptr(), rnd_mode); + return y; +} + +inline const mpreal beta (const mpreal& z, const mpreal& w, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + /* + Beta function, uses formula (6.2.2) from Abramowitz & Stegun: + beta(z,w) = gamma(z)*gamma(w)/gamma(z+w) + */ + mpreal y(0,(std::max)(z.getPrecision(), w.getPrecision())); + mpfr_beta(y.mpfr_ptr(), z.mpfr_srcptr(), w.mpfr_srcptr(), rnd_mode); + return y; +} + +inline const mpreal log_ui (unsigned long int n, mp_prec_t prec = mpreal::get_default_prec(), mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + /* Computes natural logarithm of an unsigned long */ + mpreal y(0, prec); + mpfr_log_ui(y.mpfr_ptr(),n,rnd_mode); + return y; +} +#endif + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)) + +/* f(x,u) = f(2*pi*x/u) */ +inline const mpreal cosu (const mpreal& x, unsigned long u, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_BINARY_MATH_FUNCTION_UI_BODY(cosu, u); } +inline const mpreal sinu (const mpreal& x, unsigned long u, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_BINARY_MATH_FUNCTION_UI_BODY(sinu, u); } +inline const mpreal tanu (const mpreal& x, unsigned long u, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_BINARY_MATH_FUNCTION_UI_BODY(tanu, u); } +inline const mpreal acosu (const mpreal& x, unsigned long u, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_BINARY_MATH_FUNCTION_UI_BODY(acosu, u); } +inline const mpreal asinu (const mpreal& x, unsigned long u, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_BINARY_MATH_FUNCTION_UI_BODY(asinu, u); } +inline const mpreal atanu (const mpreal& x, unsigned long u, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_BINARY_MATH_FUNCTION_UI_BODY(atanu, u); } + +/* f(x) = f(pi*x) */ +inline const mpreal cospi (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(cospi ); } +inline const mpreal sinpi (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(sinpi ); } +inline const mpreal tanpi (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(tanpi ); } +inline const mpreal acospi (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(acospi); } +inline const mpreal asinpi (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(asinpi); } +inline const mpreal atanpi (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(atanpi); } + +inline const mpreal log2p1 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(log2p1 ); } /* log2 (1+x) */ +inline const mpreal log10p1(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(log10p1); } /* log10(1+x) */ +inline const mpreal exp2m1 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(exp2m1 ); } /* 2^x-1 */ +inline const mpreal exp10m1(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(exp10m1); } /* 10^x-1 */ + +inline const mpreal atan2u(const mpreal& y, const mpreal& x, unsigned long u, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + /* + atan2u(y,x,u) = atan(|y/x|)*u/(2*pi) for x > 0 + atan2u(y,x,u) = 1-atan(|y/x|)*u/(2*pi) for x < 0 + */ + mpreal a(0, (std::max)(y.getPrecision(), x.getPrecision())); + mpfr_atan2u(a.mpfr_ptr(), y.mpfr_srcptr(), x.mpfr_srcptr(), u, rnd_mode); + return a; +} + +inline const mpreal atan2pi(const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + /* atan2pi(x) = atan2u(u=2) */ + mpreal a(0, (std::max)(y.getPrecision(), x.getPrecision())); + mpfr_atan2pi(a.mpfr_ptr(), y.mpfr_srcptr(), x.mpfr_srcptr(), rnd_mode); + return a; +} + +inline const mpreal powr(const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + /* powr(x,y) = exp(y*log(x)) */ + mpreal a(0, (std::max)(x.getPrecision(), y.getPrecision())); + mpfr_powr(a.mpfr_ptr(), x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode); + return a; +} + +inline const mpreal compound(const mpreal& x, long n, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + /* compound(x,n) = (1+x)^n */ + mpreal y(0, x.getPrecision()); + mpfr_compound_si(y.mpfr_ptr(),x.mpfr_srcptr(),n,rnd_mode); + return y; +} + +inline const mpreal fmod(const mpreal& x, unsigned long u, mp_rnd_t r = mpreal::get_default_rnd()) +{ + /* x modulo a machine integer u */ + MPREAL_BINARY_MATH_FUNCTION_UI_BODY(fmod_ui, u); +} +#endif + +inline const mpreal nextpow2(const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal y(0, x.getPrecision()); + + if(!iszero(x)) + y = ceil(log2(abs(x,r),r)); + + return y; +} + +inline const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal a(0,(std::max)(y.getPrecision(), x.getPrecision())); + mpfr_atan2(a.mpfr_ptr(), y.mpfr_srcptr(), x.mpfr_srcptr(), rnd_mode); + return a; +} + +inline const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal a(0,(std::max)(y.getPrecision(), x.getPrecision())); + mpfr_hypot(a.mpfr_ptr(), x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode); + return a; +} + +inline const mpreal hypot(const mpreal& a, const mpreal& b, const mpreal& c) +{ + if(isnan(a) || isnan(b) || isnan(c)) return mpreal().setNan(); + else + { + mpreal absa = abs(a), absb = abs(b), absc = abs(c); + mpreal w = (std::max)(absa, (std::max)(absb, absc)); + mpreal r; + + if (!iszero(w)) + { + mpreal iw = 1/w; + r = w * sqrt(sqr(absa*iw) + sqr(absb*iw) + sqr(absc*iw)); + } + + return r; + } +} + +inline const mpreal hypot(const mpreal& a, const mpreal& b, const mpreal& c, const mpreal& d) +{ + if(isnan(a) || isnan(b) || isnan(c) || isnan(d)) return mpreal().setNan(); + else + { + mpreal absa = abs(a), absb = abs(b), absc = abs(c), absd = abs(d); + mpreal w = (std::max)(absa, (std::max)(absb, (std::max)(absc, absd))); + mpreal r; + + if (!iszero(w)) + { + mpreal iw = 1/w; + r = w * sqrt(sqr(absa*iw) + sqr(absb*iw) + sqr(absc*iw) + sqr(absd*iw)); + } + + return r; + } +} + +inline const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal a(0,(std::max)(y.getPrecision(), x.getPrecision())); + mpfr_remainder(a.mpfr_ptr(), x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode); + return a; +} + +inline const mpreal remquo (const mpreal& x, const mpreal& y, int* q, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + long lq; + mpreal a(0,(std::max)(y.getPrecision(), x.getPrecision())); + mpfr_remquo(a.mpfr_ptr(), &lq, x.mpfr_srcptr(), y.mpfr_srcptr(), rnd_mode); + if (q) *q = int(lq); + return a; +} + +inline const mpreal fac_ui (unsigned long int v, mp_prec_t prec = mpreal::get_default_prec(), + mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x(0, prec); + mpfr_fac_ui(x.mpfr_ptr(),v,rnd_mode); + return x; +} + + +inline const mpreal lgamma (const mpreal& v, int *signp = 0, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x(v); + int tsignp; + + if(signp) mpfr_lgamma(x.mpfr_ptr(), signp,v.mpfr_srcptr(),rnd_mode); + else mpfr_lgamma(x.mpfr_ptr(),&tsignp,v.mpfr_srcptr(),rnd_mode); + + return x; +} + + +inline const mpreal besseljn (long n, const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal y(0, x.getPrecision()); + mpfr_jn(y.mpfr_ptr(), n, x.mpfr_srcptr(), r); + return y; +} + +inline const mpreal besselyn (long n, const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal y(0, x.getPrecision()); + mpfr_yn(y.mpfr_ptr(), n, x.mpfr_srcptr(), r); + return y; +} + +inline const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal a; + mp_prec_t p1, p2, p3; + + p1 = v1.get_prec(); + p2 = v2.get_prec(); + p3 = v3.get_prec(); + + a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1)); + + mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode); + return a; +} + +inline const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal a; + mp_prec_t p1, p2, p3; + + p1 = v1.get_prec(); + p2 = v2.get_prec(); + p3 = v3.get_prec(); + + a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1)); + + mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode); + return a; +} + +inline const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal a; + mp_prec_t p1, p2; + + p1 = v1.get_prec(); + p2 = v2.get_prec(); + + a.set_prec(p1>p2?p1:p2); + + mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode); + + return a; +} + +inline const mpreal sum (const mpreal tab[], const unsigned long int n, int& status, mp_rnd_t mode = mpreal::get_default_rnd()) +{ + mpfr_srcptr *p = new mpfr_srcptr[n]; + + for (unsigned long int i = 0; i < n; i++) + p[i] = tab[i].mpfr_srcptr(); + + mpreal x; + status = mpfr_sum(x.mpfr_ptr(), (mpfr_ptr*)p, n, mode); + + delete [] p; + return x; +} + +////////////////////////////////////////////////////////////////////////// +// MPFR 2.4.0 Specifics +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + +inline int sinh_cosh(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + return mpfr_sinh_cosh(s.mp,c.mp,v.mp,rnd_mode); +} + +inline const mpreal li2 (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) +{ + MPREAL_UNARY_MATH_FUNCTION_BODY(li2); +} + +inline const mpreal rem (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + /* R = rem(X,Y) if Y != 0, returns X - n * Y where n = trunc(X/Y). */ + return fmod(x, y, rnd_mode); +} + +inline const mpreal mod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + (void)rnd_mode; + + /* + + m = mod(x,y) if y != 0, returns x - n*y where n = floor(x/y) + + The following are true by convention: + - mod(x,0) is x + - mod(x,x) is 0 + - mod(x,y) for x != y and y != 0 has the same sign as y. + + */ + + if(iszero(y)) return x; + if(x == y) return 0; + + mpreal m = x - floor(x / y) * y; + + return copysign(abs(m),y); // make sure result has the same sign as Y +} + +inline const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal a; + mp_prec_t yp, xp; + + yp = y.get_prec(); + xp = x.get_prec(); + + a.set_prec(yp>xp?yp:xp); + + mpfr_fmod(a.mp, x.mp, y.mp, rnd_mode); + + return a; +} + +inline const mpreal rec_sqrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x(v); + mpfr_rec_sqrt(x.mp,v.mp,rnd_mode); + return x; +} +#endif // MPFR 2.4.0 Specifics + +////////////////////////////////////////////////////////////////////////// +// MPFR 3.0.0 Specifics +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) +inline const mpreal digamma (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(digamma); } +inline const mpreal ai (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(ai); } +#endif // MPFR 3.0.0 Specifics + +////////////////////////////////////////////////////////////////////////// +// Constants +inline const mpreal const_log2 (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal x(0, p); + mpfr_const_log2(x.mpfr_ptr(), r); + return x; +} + +inline const mpreal const_pi (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal x(0, p); + mpfr_const_pi(x.mpfr_ptr(), r); + return x; +} + +inline const mpreal const_euler (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal x(0, p); + mpfr_const_euler(x.mpfr_ptr(), r); + return x; +} + +inline const mpreal const_catalan (mp_prec_t p = mpreal::get_default_prec(), mp_rnd_t r = mpreal::get_default_rnd()) +{ + mpreal x(0, p); + mpfr_const_catalan(x.mpfr_ptr(), r); + return x; +} + +inline const mpreal const_infinity (int sign = 1, mp_prec_t p = mpreal::get_default_prec()) +{ + mpreal x(0, p); + mpfr_set_inf(x.mpfr_ptr(), sign); + return x; +} + +////////////////////////////////////////////////////////////////////////// +// Integer Related Functions +inline const mpreal ceil(const mpreal& v) +{ + mpreal x(v); + mpfr_ceil(x.mp,v.mp); + return x; +} + +inline const mpreal floor(const mpreal& v) +{ + mpreal x(v); + mpfr_floor(x.mp,v.mp); + return x; +} + +inline const mpreal round(const mpreal& v) +{ + mpreal x(v); + mpfr_round(x.mp,v.mp); + return x; +} + +inline long lround(const mpreal& v) +{ + long r = std::numeric_limits::min(); + mpreal x = round(v); + if (abs(x) < -mpreal(r)) // Assume mpreal(LONG_MIN) is exact + r = x.toLong(); + return r; +} + +inline long long llround(const mpreal& v) +{ + long long r = std::numeric_limits::min(); + mpreal x = round(v); + if (abs(x) < -mpreal(r)) // Assume mpreal(LLONG_MIN) is exact + r = x.toLLong(); + return r; +} + +inline const mpreal trunc(const mpreal& v) +{ + mpreal x(v); + mpfr_trunc(x.mp,v.mp); + return x; +} + +inline const mpreal rint (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint ); } +inline const mpreal rint_ceil (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint_ceil ); } +inline const mpreal rint_floor (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint_floor); } +inline const mpreal rint_round (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint_round); } +inline const mpreal rint_trunc (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(rint_trunc); } +inline const mpreal frac (const mpreal& x, mp_rnd_t r = mpreal::get_default_rnd()) { MPREAL_UNARY_MATH_FUNCTION_BODY(frac ); } + +////////////////////////////////////////////////////////////////////////// +// Miscellaneous Functions +inline int sgn(const mpreal& op) +{ + // Please note, this is classic signum function which ignores sign of zero. + // Use signbit if you need sign of zero. + return mpfr_sgn(op.mpfr_srcptr()); +} + +////////////////////////////////////////////////////////////////////////// +// Miscellaneous Functions +inline void swap (mpreal& a, mpreal& b) { mpfr_swap(a.mpfr_ptr(),b.mpfr_ptr()); } +inline const mpreal (max)(const mpreal& x, const mpreal& y){ return (x= MPFR_VERSION_NUM(3,0,0)) +inline const mpreal urandom (gmp_randstate_t& state, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x; + mpfr_urandom(x.mpfr_ptr(), state, rnd_mode); + return x; +} +#endif + +#if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2)) +inline const mpreal random2 (mp_size_t size, mp_exp_t exp) +{ + mpreal x; + mpfr_random2(x.mpfr_ptr(),size,exp); + return x; +} +#endif + +// Uniformly distributed random number generation +// a = random(seed); <- initialization & first random number generation +// a = random(); <- next random numbers generation +// seed != 0 +inline const mpreal random(unsigned int seed = 0) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) + static gmp_randstate_t state; + static bool initialize = true; + + if(initialize) + { + gmp_randinit_default(state); + gmp_randseed_ui(state,0); + initialize = false; + } + + if(seed != 0) gmp_randseed_ui(state,seed); + + return mpfr::urandom(state); +#else + if(seed != 0) std::srand(seed); + return mpfr::mpreal(std::rand()/(double)RAND_MAX); +#endif +} + +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,1,0)) +inline const mpreal grandom (gmp_randstate_t& state, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x; +#if (MPFR_VERSION >= MPFR_VERSION_NUM(4,0,0)) + mpfr_nrandom(x.mpfr_ptr(), state, rnd_mode); +#else + mpfr_grandom(x.mpfr_ptr(), NULL, state, rnd_mode); +#endif + return x; +} + +inline const mpreal grandom(unsigned int seed = 0) +{ + static gmp_randstate_t state; + static bool initialize = true; + + if(initialize) + { + gmp_randinit_default(state); + gmp_randseed_ui(state,0); + initialize = false; + } + + if(seed != 0) gmp_randseed_ui(state,seed); + + return mpfr::grandom(state); +} +#endif + +////////////////////////////////////////////////////////////////////////// +// Set/Get global properties +inline void mpreal::set_default_prec(mp_prec_t prec) +{ + mpfr_set_default_prec(prec); +} + +inline void mpreal::set_default_rnd(mp_rnd_t rnd_mode) +{ + mpfr_set_default_rounding_mode(rnd_mode); +} + +inline bool mpreal::fits_in_bits(double x, int n) +{ + int i; + double t; + return IsInf(x) || (std::modf ( std::ldexp ( std::frexp ( x, &i ), n ), &t ) == 0.0); +} + +inline const mpreal pow(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x(a); + mpfr_pow(x.mp,x.mp,b.mp,rnd_mode); + return x; +} + +inline const mpreal pow(const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x(a); + mpfr_pow_z(x.mp,x.mp,b,rnd_mode); + return x; +} + +inline const mpreal pow(const mpreal& a, const long long b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + (void)rnd_mode; + return pow(a,mpreal(b)); +} + +inline const mpreal pow(const mpreal& a, const unsigned long long b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + (void)rnd_mode; + return pow(a,mpreal(b)); +} + +inline const mpreal pow(const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x(a); + mpfr_pow_ui(x.mp,x.mp,b,rnd_mode); + return x; +} + +inline const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(a,static_cast(b),rnd_mode); +} + +inline const mpreal pow(const mpreal& a, const long int b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x(a); + mpfr_pow_si(x.mp,x.mp,b,rnd_mode); + return x; +} + +inline const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode) +{ + return pow(a,static_cast(b),rnd_mode); +} + +inline const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode) +{ + return pow(a,mpreal(b),rnd_mode); +} + +inline const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode) +{ + return pow(a,mpreal(b),rnd_mode); +} + +inline const mpreal pow(const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::get_default_rnd()) +{ + mpreal x(a); + mpfr_ui_pow(x.mp,a,b.mp,rnd_mode); + return x; +} + +inline const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),b,rnd_mode); +} + +inline const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),b,rnd_mode); + else return pow(mpreal(a),b,rnd_mode); +} + +inline const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),b,rnd_mode); + else return pow(mpreal(a),b,rnd_mode); +} + +inline const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); +} + +inline const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); +} + +// pow unsigned long int +inline const mpreal pow(const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + mpreal x(a); + mpfr_ui_pow_ui(x.mp,a,b,rnd_mode); + return x; +} + +inline const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(a,static_cast(b),rnd_mode); //mpfr_ui_pow_ui +} + +inline const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode) +{ + if(b>0) return pow(a,static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode) +{ + if(b>0) return pow(a,static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode) +{ + return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode) +{ + return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow +} + +// pow unsigned int +inline const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),b,rnd_mode); //mpfr_ui_pow_ui +} + +inline const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui +} + +inline const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode) +{ + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode) +{ + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow +} + +// pow long int +inline const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + if (a>0) return pow(static_cast(a),b,rnd_mode); //mpfr_ui_pow_ui + else return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode) +{ + if (a>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(mpreal(a),static_cast(b),rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode) +{ + if (a>0) + { + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + }else{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si + } +} + +inline const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode) +{ + if (a>0) + { + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + }else{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_si + } +} + +inline const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow +} + +inline const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow +} + +// pow int +inline const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + if (a>0) return pow(static_cast(a),b,rnd_mode); //mpfr_ui_pow_ui + else return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode) +{ + if (a>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(mpreal(a),static_cast(b),rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode) +{ + if (a>0) + { + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + }else{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si + } +} + +inline const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode) +{ + if (a>0) + { + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + }else{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_si + } +} + +inline const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow +} + +inline const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow +} + +// pow long double +inline const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),mpreal(b),rnd_mode); +} + +inline const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),static_cast(b),rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si +} + +inline const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_si +} + +inline const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),mpreal(b),rnd_mode); +} + +inline const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_ui +} + +inline const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_ui +} + +inline const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si +} + +inline const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_si +} +} // End of mpfr namespace + +// Explicit specialization of std::swap for mpreal numbers +// Thus standard algorithms will use efficient version of swap (due to Koenig lookup) +// Non-throwing swap C++ idiom: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-throwing_swap +namespace std +{ + + template <> + inline void swap(mpfr::mpreal& x, mpfr::mpreal& y) + { + return mpfr::swap(x, y); + } + + template<> + class numeric_limits + { + public: + static const bool is_specialized = true; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = false; + static const int radix = 2; + + static const bool has_infinity = true; + static const bool has_quiet_NaN = true; + static const bool has_signaling_NaN = true; + + static const bool is_iec559 = true; // = IEEE 754 + static const bool is_bounded = true; + static const bool is_modulo = false; + static const bool traps = true; + static const bool tinyness_before = true; + + static const float_denorm_style has_denorm = denorm_absent; + + inline static mpfr::mpreal (min) (mp_prec_t precision = mpfr::mpreal::get_default_prec()) { return mpfr::minval(precision); } + inline static mpfr::mpreal (max) (mp_prec_t precision = mpfr::mpreal::get_default_prec()) { return mpfr::maxval(precision); } + inline static mpfr::mpreal lowest (mp_prec_t precision = mpfr::mpreal::get_default_prec()) { return -mpfr::maxval(precision); } + + // Returns smallest eps such that 1 + eps != 1 (classic machine epsilon) + inline static mpfr::mpreal epsilon(mp_prec_t precision = mpfr::mpreal::get_default_prec()) { return mpfr::machine_epsilon(precision); } + + // Returns smallest eps such that x + eps != x (relative machine epsilon) + inline static mpfr::mpreal epsilon(const mpfr::mpreal& x) { return mpfr::machine_epsilon(x); } + + inline static mpfr::mpreal round_error(mp_prec_t precision = mpfr::mpreal::get_default_prec()) + { + mp_rnd_t r = mpfr::mpreal::get_default_rnd(); + + if(r == GMP_RNDN) return mpfr::mpreal(0.5, precision); + else return mpfr::mpreal(1.0, precision); + } + + inline static const mpfr::mpreal infinity() { return mpfr::const_infinity(); } + inline static const mpfr::mpreal quiet_NaN() { return mpfr::mpreal().setNan(); } + inline static const mpfr::mpreal signaling_NaN() { return mpfr::mpreal().setNan(); } + inline static const mpfr::mpreal denorm_min() { return (min)(); } + + // Please note, exponent range is not fixed in MPFR + static const int min_exponent = MPFR_EMIN_DEFAULT; + static const int max_exponent = MPFR_EMAX_DEFAULT; + MPREAL_PERMISSIVE_EXPR static const int min_exponent10 = (int) (MPFR_EMIN_DEFAULT * 0.3010299956639811); + MPREAL_PERMISSIVE_EXPR static const int max_exponent10 = (int) (MPFR_EMAX_DEFAULT * 0.3010299956639811); + +#ifdef MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS + + // Following members should be constant according to standard, but they can be variable in MPFR + // So we define them as functions here. + // + // This is preferable way for std::numeric_limits specialization. + // But it is incompatible with standard std::numeric_limits and might not work with other libraries, e.g. boost. + // See below for compatible implementation. + inline static float_round_style round_style() + { + mp_rnd_t r = mpfr::mpreal::get_default_rnd(); + + switch (r) + { + case GMP_RNDN: return round_to_nearest; + case GMP_RNDZ: return round_toward_zero; + case GMP_RNDU: return round_toward_infinity; + case GMP_RNDD: return round_toward_neg_infinity; + default: return round_indeterminate; + } + } + + inline static int digits() { return int(mpfr::mpreal::get_default_prec()); } + inline static int digits(const mpfr::mpreal& x) { return x.getPrecision(); } + + inline static int digits10(mp_prec_t precision = mpfr::mpreal::get_default_prec()) + { + return mpfr::bits2digits(precision); + } + + inline static int digits10(const mpfr::mpreal& x) + { + return mpfr::bits2digits(x.getPrecision()); + } + + inline static int max_digits10(mp_prec_t precision = mpfr::mpreal::get_default_prec()) + { + return digits10(precision); + } +#else + // Digits and round_style are NOT constants when it comes to mpreal. + // If possible, please use functions digits() and round_style() defined above. + // + // These (default) values are preserved for compatibility with existing libraries, e.g. boost. + // Change them accordingly to your application. + // + // For example, if you use 256 bits of precision uniformly in your program, then: + // digits = 256 + // digits10 = 77 + // max_digits10 = 78 + // + // Approximate formula for decimal digits is: digits10 = floor(log10(2) * digits). See bits2digits() for more details. + + static const std::float_round_style round_style = round_to_nearest; + static const int digits = 53; + static const int digits10 = 15; + static const int max_digits10 = 16; +#endif + }; + +} + +#endif /* __MPREAL_H__ */ diff --git a/include/shadowValue.hpp b/include/shadowValue.hpp new file mode 100644 index 0000000..63eed38 --- /dev/null +++ b/include/shadowValue.hpp @@ -0,0 +1,10 @@ +#ifndef _SHADOWVALUE +#define _SHADOWVALUE + +#include "basic.hpp" + +void shadowValue(ast_ptr &expr, double input); + +void shadowValue(const ast_ptr &expr, const std::map &varsValue); + +#endif \ No newline at end of file diff --git a/src/basic.cpp b/src/basic.cpp index 9483ebc..9202b38 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -18,6 +18,41 @@ using std::endl; using std::to_string; using std::ofstream; using std::ios; + +std::map singleCall_map = { + {"sin", minesin}, + {"cos", minecos}, + {"tan", minetan}, + {"exp", mineexp}, + {"log", minelog}, + {"asin", mineasin}, + {"acos", mineacos}, + {"atan", mineatan}, +}; + +std::map doubleCall_map = { + {"+", mineadd}, + {"-", minesub}, + {"*", minemul}, + {"/", minediv}, +}; + +std::map commonCall_map = { + {"sin", common_sin}, + {"cos", common_cos}, + {"tan", common_tan}, +}; + +std::map doubleRealCall_map = { + {"+", realadd}, + {"-", realsub}, + {"*", realmul}, + {"/", realdiv}, +}; + +std::map commonRealCall_map = { + {"tan", real_tan}, +}; //===----------------------------------------------------------------------===// // basic operation //===----------------------------------------------------------------------===// @@ -836,3 +871,20 @@ void write_to_file_wrapper(string uniqueLabel, string exprOriginBest, int dimens summaryData.push_back(matlabKernelTime); write_to_file(uniqueLabel, exprOriginBest, numIntervalsSoloBefore, numIntervalsSoloAfter, thresholds, summaryData, "runlog.csv"); } + +std::map setVarsValue(const vector &vars, const vector &values) +{ + if (values.size() != vars.size()) + { + fprintf(stderr, "values.size() != vars.size(), which are %ld and %ld\n", values.size(), vars.size()); + exit(EXIT_FAILURE); + } + std::map results; + for(size_t i = 0; i < vars.size(); i++) + { + auto &var = vars.at(i); + auto &value = values.at(i); + results[var] = value; + } + return results; +} \ No newline at end of file diff --git a/src/funclist.cpp b/src/funclist.cpp new file mode 100644 index 0000000..3bd4e7c --- /dev/null +++ b/src/funclist.cpp @@ -0,0 +1,87 @@ +#include "basic.hpp" +#include "funclist.hpp" + + +double mineadd(double x, double y) { + return x + y; +} + +double minesub(double x, double y) { + return x - y; +} + +double minemul(double x, double y) { + return x * y; +} + +double minediv(double x, double y) { + return x / y; +} + +double minesin(double x) { + return sin(x); +} + +double minecos(double x) { + return cos(x); +} + +double minetan(double x) { + return tan(x); +} + +double mineexp(double x) { + return exp(x); +} + +double minelog(double x) { + return log(x); +} + +double mineasin(double x) { + return asin(x); +} + +double mineacos(double x) { + return acos(x); +} + +double mineatan(double x) { + return atan(x); +} + +double common_sin(vector args) { + return sin(args.at(0)); +} + +double common_cos(vector args) { + return cos(args.at(0)); +} + +double common_tan(vector args) { + return tan(args.at(0)); +} + +mpfr::mpreal realadd(mpfr::mpreal x, mpfr::mpreal y) +{ + return x + y; +} + +mpfr::mpreal realsub(mpfr::mpreal x, mpfr::mpreal y) +{ + return x - y; +} + +mpfr::mpreal realmul(mpfr::mpreal x, mpfr::mpreal y) +{ + return x * y; +} + +mpfr::mpreal realdiv(mpfr::mpreal x, mpfr::mpreal y) +{ + return x / y; +} + +mpfr::mpreal real_tan(vector args) { + return tan(args.at(0)); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index de01ce1..40b61be 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include "geneCode.hpp" #include "tools.hpp" #include "benchMark.hpp" +#include "shadowValue.hpp" #include #include @@ -293,6 +294,27 @@ int main() double step = width / (double)scales.at(i); steps.push_back(step); } + // auto tmpType = originExpr->type(); + // if(tmpType == "Binary") + // { + // BinaryExprAST *tmpBinaryExpr = dynamic_cast(originExpr.get()); + // auto tmpCall = tmpBinaryExpr->getCallback(); + // auto tmpResult = tmpCall(1.3, 2.4); + // cout << "op = " << tmpBinaryExpr->getOp() << " tmpResult = " << tmpResult << endl; + // } + // else if (tmpType == "Call") + // { + // CallExprAST *tmpCallExpr = dynamic_cast(originExpr.get()); + // auto tmpCall = tmpCallExpr->getCallback(); + // vector args{1.3}; + // auto tmpResult = tmpCall(args); + // cout << "callee = " << tmpCallExpr->getCallee() << " tmpResult = " << tmpResult << endl; + // } + vector values(vars.size(), 1.4); + auto varsValue = setVarsValue(vars, values); + fmt::print("varsValue = {}\n", varsValue); + shadowValue(originExpr, varsValue); + testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); fprintf(stderr, GREEN "ready> " RESET); continue; diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp new file mode 100644 index 0000000..a567a9a --- /dev/null +++ b/src/shadowValue.cpp @@ -0,0 +1,213 @@ +#include +#include +#include "mpreal.h" +#include "shadowValue.hpp" +#include "funclist.hpp" + + +using std::string; +using std::vector; +using std::ofstream; + +struct valueTwo { + double funcValue; + mpfr::mpreal realValue; +}; + +// demo +double shadowValueKernel(ast_ptr &expr, double &input, vector &middleValues) +{ + auto type = expr->type(); + double result; + if(type == "Number") + { + NumberExprAST *numberExpr = dynamic_cast(expr.get()); + result = (numberExpr->getNumber()); + middleValues.push_back(result); + return result; + } + else if(type == "Variable") + { + middleValues.push_back(input); + return input; + } + else if(type == "Call") + { + CallExprAST *callPtr = dynamic_cast(expr.get()); + auto &args = callPtr->getArgs(); + vector paramResults; + for(auto& arg : args) + { + auto tmp = shadowValueKernel(arg, input, middleValues); + paramResults.push_back(tmp); + } + auto tmpCall = callPtr->getCallback(); + result = tmpCall(paramResults); + std::cout << "callee = " << callPtr->getCallee() << " result = " << result << std::endl; + middleValues.push_back(result); + + return result; + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + auto lhsValue = shadowValueKernel(lhs, input, middleValues); + auto rhsValue = shadowValueKernel(rhs, input, middleValues); + auto tmpCall = binPtr->getCallback(); + result = tmpCall(lhsValue, rhsValue); + std::cout << "op = " << binPtr->getOp() << " result = " << result << std::endl; + middleValues.push_back(result); + + return result; + } + else + { + fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); + exit(EXIT_FAILURE); + } +} + +// demo +void shadowValue(ast_ptr &expr, double input) +{ + vector middleValues; + shadowValueKernel(expr, input, middleValues); + fmt::print("middleValues := {}\n", middleValues); +} + +valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector &funcValues, vector &funcRealValues, vector &mathRealValues, vector &errorValues) +{ + auto type = expr->type(); + valueTwo result; + if(type == "Number") + { + NumberExprAST *numberExpr = dynamic_cast(expr.get()); + result.funcValue = (numberExpr->getNumber()); + result.realValue = result.funcValue; + funcValues.push_back(result.funcValue); + funcRealValues.push_back(result.realValue); + mathRealValues.push_back(result.realValue); + errorValues.push_back(0); + return result; + } + else if(type == "Variable") + { + VariableExprAST *variableExpr = dynamic_cast(expr.get()); + string variable = (variableExpr->getVariable()); + result.funcValue = varsValue.find(variable)->second; + result.realValue = result.funcValue; + funcValues.push_back(result.funcValue); + funcRealValues.push_back(result.realValue); + mathRealValues.push_back(result.realValue); + errorValues.push_back(0); + + return result; + } + else if(type == "Call") + { + CallExprAST *callPtr = dynamic_cast(expr.get()); + auto &args = callPtr->getArgs(); + vector paramResults; + vector paramRealResults; + vector parammathRealResults; + + for(auto& arg : args) + { + auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues); + paramResults.push_back(tmp.funcValue); + mpfr::mpreal tmpRealValue = tmp.funcValue; + paramRealResults.push_back(tmpRealValue); + parammathRealResults.push_back(tmp.realValue); + } + + // func + auto tmpCall = callPtr->getCallback(); + + // func value + result.funcValue = tmpCall(paramResults); + std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; + funcValues.push_back(result.funcValue); + + // real func + auto tmpRealCall = callPtr->getRealCallback(); + + // func real value + mpfr::mpreal funcRealValue = tmpRealCall(paramRealResults); + std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; + funcRealValues.push_back(funcRealValue); + + // math real value + result.realValue = tmpRealCall(parammathRealResults); + std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; + mathRealValues.push_back(result.realValue); + + // absolute error + double errorValue = fabs((funcRealValue - result.funcValue).toDouble()); + errorValues.push_back(errorValue); + + return result; + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues); + auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues); + + // func + auto tmpCall = binPtr->getCallback(); + + // func value + result.funcValue = tmpCall(lhsValue.funcValue, rhsValue.funcValue); + std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; + funcValues.push_back(result.funcValue); + + // real func + auto tmpRealCall = binPtr->getRealCallback(); + + // func real value + mpfr::mpreal funcRealValue = tmpRealCall(lhsValue.funcValue, rhsValue.funcValue); + std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; + funcRealValues.push_back(funcRealValue); + + // math real value + result.realValue = tmpRealCall(lhsValue.realValue, rhsValue.realValue); + std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << result.realValue.toString() << std::endl; + mathRealValues.push_back(result.realValue); + + // absolute error + double errorValue = fabs((funcRealValue - result.funcValue).toDouble()); + errorValues.push_back(errorValue); + + return result; + } + else + { + fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); + exit(EXIT_FAILURE); + } +} + +void shadowValue(const ast_ptr &expr, const std::map &varsValue) +{ + mpfr::mpreal::set_default_prec(128); + std::vector funcRealValues; + std::vector mathRealValues; + + vector funcValues; + vector errorValues; // this error is f(x+\delta x) between F(x + \delta x) + shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues); + fmt::print("funcValues := {}\n", funcValues); + for(auto &funRealValue : funcRealValues) + { + std::cout << "func real value: " << funRealValue.toString() << std::endl; + } + for(auto &mathRealValue : mathRealValues) + { + std::cout << "math real value: " << mathRealValue.toString() << std::endl; + } + fmt::print("errorValues := {}\n", errorValues); +} \ No newline at end of file -- Gitee From 887105754f89262e181d3ca6da811898435a0f48 Mon Sep 17 00:00:00 2001 From: hjwLab Date: Wed, 26 Apr 2023 22:37:27 +0800 Subject: [PATCH 06/54] Enhance shadowValue: the use of templates and support for arrays as input --- include/basic.hpp | 3 +- include/shadowValue.hpp | 5 +- src/basic.cpp | 12 +- src/main.cpp | 18 +- src/shadowValue.cpp | 378 +++++++++++++++++++++++++++++++++------- 5 files changed, 342 insertions(+), 74 deletions(-) diff --git a/include/basic.hpp b/include/basic.hpp index a6d20a2..e044bb7 100644 --- a/include/basic.hpp +++ b/include/basic.hpp @@ -300,6 +300,7 @@ void write_to_file(const string &uniqueLabel, const string &exprOriginBest, cons void write_to_file_wrapper(string uniqueLabel, string exprOriginBest, int dimension, int numIntervalsBefore, double numOfIntervals, const vector &numIntervalsSoloBefore, const vector &numIntervalsSoloAfter, int numOfExprs, vector thresholds, const exprInfo &originExprInfo, const exprInfo &herbieExprInfo, const exprInfo &finalInfo, double originPerformance, double elapsed_seconds, double init_seconds, double matlab_seconds, double regime_seconds, double rewrite_seconds, double final_seconds, double matlabKernelTime); // } // end anonymous namespace -std::map setVarsValue(const vector &vars, const vector &values); +template +std::map setVarsValue(const vector &vars, const vector &values); #endif \ No newline at end of file diff --git a/include/shadowValue.hpp b/include/shadowValue.hpp index 63eed38..775e39a 100644 --- a/include/shadowValue.hpp +++ b/include/shadowValue.hpp @@ -2,9 +2,12 @@ #define _SHADOWVALUE #include "basic.hpp" +namespace Shadow { void shadowValue(ast_ptr &expr, double input); -void shadowValue(const ast_ptr &expr, const std::map &varsValue); +template +void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length = 1); +} #endif \ No newline at end of file diff --git a/src/basic.cpp b/src/basic.cpp index 9202b38..f82e6ba 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -872,19 +872,23 @@ void write_to_file_wrapper(string uniqueLabel, string exprOriginBest, int dimens write_to_file(uniqueLabel, exprOriginBest, numIntervalsSoloBefore, numIntervalsSoloAfter, thresholds, summaryData, "runlog.csv"); } -std::map setVarsValue(const vector &vars, const vector &values) +template +std::map setVarsValue(const vector &vars, const vector &values) { if (values.size() != vars.size()) { fprintf(stderr, "values.size() != vars.size(), which are %ld and %ld\n", values.size(), vars.size()); exit(EXIT_FAILURE); } - std::map results; - for(size_t i = 0; i < vars.size(); i++) + std::map results; + for (size_t i = 0; i < vars.size(); i++) { auto &var = vars.at(i); auto &value = values.at(i); results[var] = value; } return results; -} \ No newline at end of file +} + +template std::map setVarsValue(const vector &vars, const vector &values); +template std::map setVarsValue(const vector &vars, const vector &values); diff --git a/src/main.cpp b/src/main.cpp index 40b61be..93795ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -311,9 +311,23 @@ int main() // cout << "callee = " << tmpCallExpr->getCallee() << " tmpResult = " << tmpResult << endl; // } vector values(vars.size(), 1.4); - auto varsValue = setVarsValue(vars, values); + auto varsValue = setVarsValue(vars, values); fmt::print("varsValue = {}\n", varsValue); - shadowValue(originExpr, varsValue); + Shadow::shadowValue(originExpr, varsValue); + + vector values1; + size_t inputNum = 5; + for(size_t i = 0; i < vars.size(); i++) + { + double *tmp = new double[inputNum]; + for(size_t j = 0; j < inputNum; j++) + { + tmp[j] = i * inputNum + j; + } + values1.push_back(tmp); + } + auto varsValue1 = setVarsValue(vars, values1); + Shadow::shadowValue(originExpr, varsValue1, inputNum); testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); fprintf(stderr, GREEN "ready> " RESET); diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index a567a9a..9a6b7c9 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "mpreal.h" #include "shadowValue.hpp" #include "funclist.hpp" @@ -8,11 +9,7 @@ using std::string; using std::vector; using std::ofstream; - -struct valueTwo { - double funcValue; - mpfr::mpreal realValue; -}; +namespace Shadow { // demo double shadowValueKernel(ast_ptr &expr, double &input, vector &middleValues) @@ -77,31 +74,115 @@ void shadowValue(ast_ptr &expr, double input) fmt::print("middleValues := {}\n", middleValues); } -valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector &funcValues, vector &funcRealValues, vector &mathRealValues, vector &errorValues) +template +struct ParamTypeMapper +{ + using ParamType = T; +}; + +template <> +struct ParamTypeMapper +{ + using ParamType = mpfr::mpreal; +}; + +template <> +struct ParamTypeMapper +{ + using ParamType = mpfr::mpreal *; +}; + +template +using ParamType = typename ParamTypeMapper::ParamType; + +template +struct valueTwo { + T funcValue; + ParamType realValue; +}; + +template +valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, int length = 1) { auto type = expr->type(); - valueTwo result; + constexpr bool TisDouble = (std::is_same::value); + constexpr bool TisDoublePointer = (std::is_same::value); + valueTwo result; if(type == "Number") { NumberExprAST *numberExpr = dynamic_cast(expr.get()); - result.funcValue = (numberExpr->getNumber()); - result.realValue = result.funcValue; - funcValues.push_back(result.funcValue); - funcRealValues.push_back(result.realValue); - mathRealValues.push_back(result.realValue); - errorValues.push_back(0); + auto funcValue = (numberExpr->getNumber()); + if constexpr (TisDouble) + { + result.funcValue = funcValue; + result.realValue = result.funcValue; + funcValues.push_back(result.funcValue); + funcRealValues.push_back(result.realValue); + mathRealValues.push_back(result.realValue); + errorValues.push_back(0); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncValues = new double[length]; + auto tmpRealValues = new mpfr::mpreal[length]; + auto tmperrorValues = new double[length](); + for(int i = 0; i < length; i++) + { + tmpfuncValues[i] = funcValue; + tmpRealValues[i] = funcValue; + } + result.funcValue = tmpfuncValues; + result.realValue = tmpRealValues; + funcValues.push_back(tmpfuncValues); + funcRealValues.push_back(tmpRealValues); + mathRealValues.push_back(tmpRealValues); + errorValues.push_back(tmperrorValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } return result; } else if(type == "Variable") { VariableExprAST *variableExpr = dynamic_cast(expr.get()); string variable = (variableExpr->getVariable()); - result.funcValue = varsValue.find(variable)->second; - result.realValue = result.funcValue; - funcValues.push_back(result.funcValue); - funcRealValues.push_back(result.realValue); - mathRealValues.push_back(result.realValue); - errorValues.push_back(0); + auto varValue = varsValue.find(variable)->second; + // if(std::is_same::type, T>::value) + if constexpr (TisDouble) + { + result.funcValue = varValue; + result.realValue = result.funcValue; + funcValues.push_back(result.funcValue); + funcRealValues.push_back(result.realValue); + mathRealValues.push_back(result.realValue); + errorValues.push_back(0); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncValues = new double[length]; + auto tmpRealValues = new mpfr::mpreal[length]; + auto tmperrorValues = new double[length](); + for(int i = 0; i < length; i++) + { + auto &tmpfuncValue = varValue[i]; + tmpfuncValues[i] = tmpfuncValue; + tmpRealValues[i] = tmpfuncValue; + } + result.funcValue = tmpfuncValues; + result.realValue = tmpRealValues; + funcValues.push_back(tmpfuncValues); + funcRealValues.push_back(tmpRealValues); + mathRealValues.push_back(tmpRealValues); + errorValues.push_back(tmperrorValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } return result; } @@ -109,16 +190,18 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map & { CallExprAST *callPtr = dynamic_cast(expr.get()); auto &args = callPtr->getArgs(); - vector paramResults; - vector paramRealResults; - vector parammathRealResults; + vector paramResults; + vector> paramFuncRealResults; + vector> parammathRealResults; for(auto& arg : args) { - auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues); + auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); paramResults.push_back(tmp.funcValue); - mpfr::mpreal tmpRealValue = tmp.funcValue; - paramRealResults.push_back(tmpRealValue); + if constexpr (TisDouble) + { + paramFuncRealResults.push_back(tmp.funcValue); + } parammathRealResults.push_back(tmp.realValue); } @@ -126,26 +209,101 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map & auto tmpCall = callPtr->getCallback(); // func value - result.funcValue = tmpCall(paramResults); - std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; - funcValues.push_back(result.funcValue); + if constexpr (TisDouble) + { + result.funcValue = tmpCall(paramResults); + std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; + funcValues.push_back(result.funcValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncValues = new double[length]; + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : paramResults) + { + tmpParam.push_back(param[i]); + } + auto funcValue = tmpCall(tmpParam); + tmpfuncValues[i] = funcValue; + } + result.funcValue = tmpfuncValues; + funcValues.push_back(tmpfuncValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } // real func auto tmpRealCall = callPtr->getRealCallback(); // func real value - mpfr::mpreal funcRealValue = tmpRealCall(paramRealResults); - std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; - funcRealValues.push_back(funcRealValue); + if constexpr (TisDouble) + { + mpfr::mpreal funcRealValue = tmpRealCall(paramFuncRealResults); + std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; + funcRealValues.push_back(funcRealValue); + + // absolute error + double errorValue = fabs((funcRealValue - result.funcValue).toDouble()); + errorValues.push_back(errorValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncRealValues = new mpfr::mpreal[length]; + auto tmpErrorValues = new double[length]; + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : paramResults) + { + tmpParam.push_back(param[i]); + } + auto funcRealValue = tmpRealCall(tmpParam); + tmpfuncRealValues[i] = funcRealValue; + + tmpErrorValues[i] = fabs((funcRealValue - (result.funcValue)[i]).toDouble()); + } + funcRealValues.push_back(tmpfuncRealValues); + errorValues.push_back(tmpErrorValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } // math real value - result.realValue = tmpRealCall(parammathRealResults); - std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; - mathRealValues.push_back(result.realValue); - - // absolute error - double errorValue = fabs((funcRealValue - result.funcValue).toDouble()); - errorValues.push_back(errorValue); + if constexpr (TisDouble) + { + result.realValue = tmpRealCall(parammathRealResults); + std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; + mathRealValues.push_back(result.realValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpmathRealValues = new mpfr::mpreal[length]; + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : parammathRealResults) + { + tmpParam.push_back(param[i]); + } + auto mathRealValue = tmpRealCall(tmpParam); + tmpmathRealValues[i] = mathRealValue; + } + mathRealValues.push_back(tmpmathRealValues); + result.realValue = tmpmathRealValues; + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } return result; } @@ -154,33 +312,100 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map & BinaryExprAST *binPtr = dynamic_cast(expr.get()); ast_ptr &lhs = binPtr->getLHS(); ast_ptr &rhs = binPtr->getRHS(); - auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues); - auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues); + auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); + auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); // func auto tmpCall = binPtr->getCallback(); // func value - result.funcValue = tmpCall(lhsValue.funcValue, rhsValue.funcValue); - std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; - funcValues.push_back(result.funcValue); + if constexpr (TisDouble) + { + result.funcValue = tmpCall(lhsValue.funcValue, rhsValue.funcValue); + std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; + funcValues.push_back(result.funcValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncValues = new double[length]; + for(int i = 0; i < length; i++) + { + double &tmpLhsValue = (lhsValue.funcValue)[i]; + double &tmpRhsValue = (rhsValue.funcValue)[i]; + + auto funcValue = tmpCall(tmpLhsValue, tmpRhsValue); + tmpfuncValues[i] = funcValue; + } + result.funcValue = tmpfuncValues; + funcValues.push_back(tmpfuncValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } // real func auto tmpRealCall = binPtr->getRealCallback(); // func real value - mpfr::mpreal funcRealValue = tmpRealCall(lhsValue.funcValue, rhsValue.funcValue); - std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; - funcRealValues.push_back(funcRealValue); + if constexpr (TisDouble) + { + mpfr::mpreal funcRealValue = tmpRealCall(lhsValue.funcValue, rhsValue.funcValue); + std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; + funcRealValues.push_back(funcRealValue); - // math real value - result.realValue = tmpRealCall(lhsValue.realValue, rhsValue.realValue); - std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << result.realValue.toString() << std::endl; - mathRealValues.push_back(result.realValue); + // absolute error + double errorValue = fabs((funcRealValue - result.funcValue).toDouble()); + errorValues.push_back(errorValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncRealValues = new mpfr::mpreal[length]; + auto tmpErrorValues = new double[length]; + for(int i = 0; i < length; i++) + { + mpfr::mpreal tmpLhsValue = (lhsValue.funcValue)[i]; + mpfr::mpreal tmpRhsValue = (rhsValue.funcValue)[i]; + auto funcRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); + tmpfuncRealValues[i] = funcRealValue; + + tmpErrorValues[i] = fabs((funcRealValue - (result.funcValue)[i]).toDouble()); + } + funcRealValues.push_back(tmpfuncRealValues); + errorValues.push_back(tmpErrorValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } - // absolute error - double errorValue = fabs((funcRealValue - result.funcValue).toDouble()); - errorValues.push_back(errorValue); + // math real value + if constexpr (TisDouble) + { + result.realValue = tmpRealCall(lhsValue.realValue, rhsValue.realValue); + std::cout << "op = " << binPtr->getOp() << " mathRealValue = " << result.realValue.toString() << std::endl; + mathRealValues.push_back(result.realValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpmathRealValues = new mpfr::mpreal[length]; + for(int i = 0; i < length; i++) + { + mpfr::mpreal tmpLhsValue = (lhsValue.realValue)[i]; + mpfr::mpreal tmpRhsValue = (rhsValue.realValue)[i]; + auto mathRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); + tmpmathRealValues[i] = mathRealValue; + } + mathRealValues.push_back(tmpmathRealValues); + result.realValue = tmpmathRealValues; + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } return result; } @@ -191,23 +416,44 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map & } } -void shadowValue(const ast_ptr &expr, const std::map &varsValue) +template +void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length) { mpfr::mpreal::set_default_prec(128); - std::vector funcRealValues; - std::vector mathRealValues; - - vector funcValues; - vector errorValues; // this error is f(x+\delta x) between F(x + \delta x) - shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues); - fmt::print("funcValues := {}\n", funcValues); - for(auto &funRealValue : funcRealValues) + vector funcValues; + vector errorValues; // this error is f(x+\delta x) between F(x + \delta x) + if constexpr (std::is_same::value) { - std::cout << "func real value: " << funRealValue.toString() << std::endl; + std::vector funcRealValues; + std::vector mathRealValues; + shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); + fmt::print("funcValues := {}\n", funcValues); + for(auto &funRealValue : funcRealValues) + { + std::cout << "func real value: " << funRealValue.toString() << std::endl; + } + for(auto &mathRealValue : mathRealValues) + { + std::cout << "math real value: " << mathRealValue.toString() << std::endl; + } + fmt::print("errorValues := {}\n", errorValues); } - for(auto &mathRealValue : mathRealValues) + else if constexpr (std::is_same::value) { - std::cout << "math real value: " << mathRealValue.toString() << std::endl; + std::vector funcRealValues; + std::vector mathRealValues; + shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); + for(int i = 0; i < length; i++) + { + for(size_t j = 0; j < funcValues.size(); j++) + { + fprintf(stderr, "i = %d j = %ld: funcValue = %f\n", i, j, (funcValues.at(j))[i]); + } + } } - fmt::print("errorValues := {}\n", errorValues); +} + +template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length); +template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length); + } \ No newline at end of file -- Gitee From a4aa0cdf4b571b29156b4a8a9de2d372f5222166 Mon Sep 17 00:00:00 2001 From: hjwLab Date: Sat, 6 May 2023 21:48:11 +0800 Subject: [PATCH 07/54] support pow function --- include/funclist.hpp | 4 ++++ src/basic.cpp | 2 ++ src/funclist.cpp | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/include/funclist.hpp b/include/funclist.hpp index 20bb690..36a17ea 100644 --- a/include/funclist.hpp +++ b/include/funclist.hpp @@ -35,6 +35,8 @@ double common_cos(vector args); double common_tan(vector args); +double common_pow(vector args); + mpfr::mpreal realadd(mpfr::mpreal x, mpfr::mpreal y); mpfr::mpreal realsub(mpfr::mpreal x, mpfr::mpreal y); @@ -45,4 +47,6 @@ mpfr::mpreal realdiv(mpfr::mpreal x, mpfr::mpreal y); mpfr::mpreal real_tan(vector args); +mpfr::mpreal real_pow(vector args); + #endif \ No newline at end of file diff --git a/src/basic.cpp b/src/basic.cpp index f82e6ba..0d3ba87 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -41,6 +41,7 @@ std::map commonCall_map = { {"sin", common_sin}, {"cos", common_cos}, {"tan", common_tan}, + {"pow", common_pow}, }; std::map doubleRealCall_map = { @@ -52,6 +53,7 @@ std::map doubleRealCall_map = { std::map commonRealCall_map = { {"tan", real_tan}, + {"pow", real_pow}, }; //===----------------------------------------------------------------------===// // basic operation diff --git a/src/funclist.cpp b/src/funclist.cpp index 3bd4e7c..93dad0a 100644 --- a/src/funclist.cpp +++ b/src/funclist.cpp @@ -62,6 +62,10 @@ double common_tan(vector args) { return tan(args.at(0)); } +double common_pow(vector args) { + return pow(args.at(0), args.at(1)); +} + mpfr::mpreal realadd(mpfr::mpreal x, mpfr::mpreal y) { return x + y; @@ -84,4 +88,8 @@ mpfr::mpreal realdiv(mpfr::mpreal x, mpfr::mpreal y) mpfr::mpreal real_tan(vector args) { return tan(args.at(0)); +} + +mpfr::mpreal real_pow(vector args) { + return pow(args.at(0), args.at(1)); } \ No newline at end of file -- Gitee From b3de1c429e14f0e1e7e76b8dc12777c6447788af Mon Sep 17 00:00:00 2001 From: hjwLab Date: Sat, 6 May 2023 21:52:15 +0800 Subject: [PATCH 08/54] support different error criterion and improve output style and some improvement --- include/errorDetect.hpp | 20 +++++++++ src/errorDetect.cpp | 40 ++++++++++++++++++ src/main.cpp | 23 +++++++---- src/shadowValue.cpp | 89 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 154 insertions(+), 18 deletions(-) create mode 100644 include/errorDetect.hpp create mode 100644 src/errorDetect.cpp diff --git a/include/errorDetect.hpp b/include/errorDetect.hpp new file mode 100644 index 0000000..82935b4 --- /dev/null +++ b/include/errorDetect.hpp @@ -0,0 +1,20 @@ +#ifndef _ERRORDETECT +#define _ERRORDETECT + +#include "mpreal.h" + +typedef union { + double d; + unsigned long int l; +} DL; + +typedef union { + float f; + unsigned int l; +} FS; + +double computeUlpUnit(double x); + +double computeError(mpfr::mpreal oracle, double x); + +#endif \ No newline at end of file diff --git a/src/errorDetect.cpp b/src/errorDetect.cpp new file mode 100644 index 0000000..83e3bd0 --- /dev/null +++ b/src/errorDetect.cpp @@ -0,0 +1,40 @@ +#include +#include "errorDetect.hpp" + +double computeUlpUnit(double x) { + DL x0; + x0.d = fabs(x); + // printf("x0 = %le\n", x0.d); + // printf("x0 = %016lx\n", x0.l); + if(x0.d < pow(2, -1021)) { + x0.d = pow(2, -1074); + } else if(x0.d > (1 - pow(2, -53)) * pow(2, 1024)) { + x0.d = pow(2,971); + } else { + x0.l = x0.l >> 52; + // printf("1x0 = %016lx\n", x0.l); + // x0.l = x0.l - 52; // for these FP numbers whose exponent is lower than 52, the result will be zero wrongly. + // printf("2x0 = %016lx\n", x0.l); + x0.l = x0.l << 52; + // printf("3x0 = %016lx\n", x0.l); + x0.d = x0.d * pow(2, -52); + // printf("4x0 = %016lx\n", x0.l); + // printf("else: x0 = %le\n", x0.d); + } + return x0.d; +} + +double computeError(mpfr::mpreal oracle, double x) +{ + // absolute error + // double errorValue = fabs((oracle - x).toDouble()); + + // relative error + // double errorValue = fabs(((oracle - x) / oracle).toDouble()); + + // ulp error + auto unitUlp = computeUlpUnit(oracle.toDouble()); + auto errorValue = fabs((oracle - x).toDouble() / unitUlp); + + return errorValue; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 93795ba..d7357d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -310,25 +310,32 @@ int main() // auto tmpResult = tmpCall(args); // cout << "callee = " << tmpCallExpr->getCallee() << " tmpResult = " << tmpResult << endl; // } - vector values(vars.size(), 1.4); - auto varsValue = setVarsValue(vars, values); - fmt::print("varsValue = {}\n", varsValue); - Shadow::shadowValue(originExpr, varsValue); + // vector values(dimension, 1.4); + // auto varsValue = setVarsValue(vars, values); + // fmt::print("varsValue = {}\n", varsValue); + // Shadow::shadowValue(originExpr, varsValue); + // generate input data vector values1; - size_t inputNum = 5; - for(size_t i = 0; i < vars.size(); i++) + size_t inputNum = 1000; + for(int i = 0; i < dimension; i++) { + auto &startOriginInterval = intervals.at(i * 2); + auto &endOriginInterval = intervals.at(i * 2 + 1); + double width = endOriginInterval - startOriginInterval; + double step = width / inputNum; + double *tmp = new double[inputNum]; for(size_t j = 0; j < inputNum; j++) { - tmp[j] = i * inputNum + j; + tmp[j] = startOriginInterval + j * step; } values1.push_back(tmp); } auto varsValue1 = setVarsValue(vars, values1); + // call the shadowValue function to generate the shadow values of the expression. Shadow::shadowValue(originExpr, varsValue1, inputNum); - + // TODO: free values1 testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); fprintf(stderr, GREEN "ready> " RESET); continue; diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 9a6b7c9..32278fa 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -1,14 +1,19 @@ #include #include #include +#include +#include +#include #include "mpreal.h" #include "shadowValue.hpp" #include "funclist.hpp" +#include "errorDetect.hpp" using std::string; using std::vector; using std::ofstream; +using std::ios; namespace Shadow { // demo @@ -247,8 +252,7 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; funcRealValues.push_back(funcRealValue); - // absolute error - double errorValue = fabs((funcRealValue - result.funcValue).toDouble()); + auto errorValue = computeError(funcRealValue, result.funcValue); errorValues.push_back(errorValue); } else if constexpr (TisDoublePointer) @@ -265,7 +269,7 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va auto funcRealValue = tmpRealCall(tmpParam); tmpfuncRealValues[i] = funcRealValue; - tmpErrorValues[i] = fabs((funcRealValue - (result.funcValue)[i]).toDouble()); + tmpErrorValues[i] = computeError(funcRealValue, (result.funcValue)[i]); } funcRealValues.push_back(tmpfuncRealValues); errorValues.push_back(tmpErrorValues); @@ -355,9 +359,19 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; funcRealValues.push_back(funcRealValue); - // absolute error - double errorValue = fabs((funcRealValue - result.funcValue).toDouble()); + auto errorValue = computeError(funcRealValue, result.funcValue); errorValues.push_back(errorValue); + + // absolute error + // double absErrorValue = fabs((funcRealValue - result.funcValue).toDouble()); + // errorValues.push_back(absErrorValue); + // relative error + // double relErrorValue = fabs(((funcRealValue - result.funcValue) / funcRealValue).toDouble()); + // errorValues.push_back(relErrorValue); + // ulp error + // auto unitUlp = computeUlpUnit(funcRealValue.toDouble()); + // auto ulpErrorValue = fabs((funcRealValue - result.funcValue).toDouble() / unitUlp); + // errorValues.push_back(ulpErrorValue); } else if constexpr (TisDoublePointer) { @@ -369,8 +383,11 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va mpfr::mpreal tmpRhsValue = (rhsValue.funcValue)[i]; auto funcRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); tmpfuncRealValues[i] = funcRealValue; - - tmpErrorValues[i] = fabs((funcRealValue - (result.funcValue)[i]).toDouble()); + + tmpErrorValues[i] = computeError(funcRealValue, (result.funcValue)[i]); + + // absolute error + // tmpErrorValues[i] = fabs((funcRealValue - (result.funcValue)[i]).toDouble()); } funcRealValues.push_back(tmpfuncRealValues); errorValues.push_back(tmpErrorValues); @@ -443,13 +460,65 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int std::vector funcRealValues; std::vector mathRealValues; shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); - for(int i = 0; i < length; i++) + // TODO: free funcValues, funcRealValues, mathRealValues, errorValues + // print to the screen + // for(int i = 0; i < length; i++) + // { + // for(size_t j = 0; j < funcValues.size(); j++) + // { + // fprintf(stderr, "input NO.%d step NO.%ld: funcValue = %g\n", i, j, (funcValues.at(j))[i]); + // fprintf(stderr, "input NO.%d step NO.%ld: funcRealValue = %s\n", i, j, (funcRealValues.at(j))[i].toString().c_str()); + // fprintf(stderr, "input NO.%d step NO.%ld: mathRealValue = %s\n", i, j, (mathRealValues.at(j))[i].toString().c_str()); + // fprintf(stderr, "input NO.%d step NO.%ld: errorValue = %g\n\n", i, j, (errorValues.at(j))[i]); + // } + // fprintf(stderr, "================================\n\n"); + // } + // print to the file + double **inputsPtr = new double *[varsValue.size()]; + int ptrIdx = 0; + for(auto &value : varsValue){ + inputsPtr[ptrIdx] = value.second; + ptrIdx++; + } + for(size_t i = 0; i < funcValues.size(); i++) { - for(size_t j = 0; j < funcValues.size(); j++) + std::ofstream fout; + string filename = "./errorFunc_" + std::to_string(i) + ".txt"; + fout.open(filename, ios::out); + if (!fout.is_open()) + { + std::cout << "open " << filename << " failed"; + exit(EXIT_FAILURE); + } + for(int j = 0; j < length; j++) { - fprintf(stderr, "i = %d j = %ld: funcValue = %f\n", i, j, (funcValues.at(j))[i]); + for(size_t ptrIdx = 0; ptrIdx < varsValue.size(); ptrIdx++) // print all the input variables' value + { + fout << inputsPtr[ptrIdx][j] << " "; + } + fout << (errorValues.at(i))[j] << "\n"; } } + // std::ofstream fout; + // fout.open("./shadowValueResult.txt", ios::out); + // if (!fout.is_open()) + // { + // std::cout << "open shadowValueResult.txt failed"; + // exit(EXIT_FAILURE); + // } + // fout << "inputIdx stepIdx funcValue funcRealValue mathRealValue errorValue\n"; + // for(int i = 0; i < length; i++) + // { + // for(size_t j = 0; j < funcValues.size(); j++) + // { + // fout << i << " " << j << " " << (funcValues.at(j))[i] << " " << (funcRealValues.at(j))[i].toString() << " " << (mathRealValues.at(j))[i].toString() << " " << (errorValues.at(j))[i] << "\n"; + // } + // } + // fout << "input NO." << i << " step NO." << j << ": funcValue = " << (funcValues.at(j))[i] << "\n"; + // fout << "input NO." << i << " step NO." << j << ": funcRealValue = " << (funcRealValues.at(j))[i].toString() << "\n"; + // fout << "input NO." << i << " step NO." << j << ": mathRealValue = " << (mathRealValues.at(j))[i].toString() << "\n"; + // fout << "input NO." << i << " step NO." << j << ": errorValue = " << (errorValues.at(j))[i] << "\n"; + // fout << "================================\n\n"; } } -- Gitee From 238e3fbcaa0c6c3ee6f322a3e8568982dd07fd64 Mon Sep 17 00:00:00 2001 From: hjwLab Date: Mon, 8 May 2023 11:14:29 +0800 Subject: [PATCH 09/54] imporve dd.h --- includeDD/dd.h | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/includeDD/dd.h b/includeDD/dd.h index 91a1c94..72427f6 100644 --- a/includeDD/dd.h +++ b/includeDD/dd.h @@ -3,13 +3,19 @@ #define xTmp(x) x##Tmp +// TODO: 操作的实现精度取决于操作结果的类型以及变量类型。如果结果是dd类型,那实现必须按照dd的方法来。如果结果是double,那要看变量类型有无dd。如果有的话,就得使用dd算法,只不过最后要将结果舍入到double。 +// 解释:这么做的原因在于,避免上一步的精度优化白做。如果上步采用的是dd,那其精度提升效果主要体现在新增的精度位。如果当前步骤舍去新增的精度位,那就相当于舍弃了上一步的精度优化效果。 +// 解释:虽然这么做,感觉是存在一些性能上的牵连,但如果不这么做的话,那精度优化的意义就不大了。而且从优化的角度,也鼓励一条龙式的优化,这样可以尽量避免精度、性能浪费。 +// 我的疑问就是:dd+double的话,究竟算是dd实现,还是double实现?dd+dd和ld+dd的精度实现有差异吗 + // =========================================== ADD ======================================= +// 先只改dd、double #define add_d_d_d(a, b, c) double c = (a) + (b); #define add_ld_d_d(a, b, c) long double xTmp(c) = (a) + (b); double c = xTmp(c); -#define add_dd_d_d(a, b, c) double xTmp(c)[2]; c_dd_add_dd_d(a, b, xTmp(c)); double c = xTmp(c)[0]; -#define add_d_dd_d(a, b, c) double xTmp(c)[2]; c_dd_add_d_dd(a, b, xTmp(c)); double c = xTmp(c)[0]; +#define add_dd_d_d(a, b, c) double xTmp(c)[2]; c_dd_add_dd_d(a, b, xTmp(c)); double c = xTmp(c)[0] + xTmp(c)[1]; +#define add_d_dd_d(a, b, c) double xTmp(c)[2]; c_dd_add_d_dd(a, b, xTmp(c)); double c = xTmp(c)[0] + xTmp(c)[1]; #define add_ld_dd_d(a, b, c) double xTmp(a)[2]; xTmp(a)[0] = a; xTmp(a)[1] = a - xTmp(a)[0]; double xTmp(c)[2]; c_dd_add(xTmp(a), b, xTmp(c)); c = xTmp(c)[0]; // check c = ((a) + (b[0])) + b[1]; -#define add_dd_dd_d(a, b, c) double xTmp(c)[2]; c_dd_add(a, b, xTmp(c)); double c; c = xTmp(c)[0]; +#define add_dd_dd_d(a, b, c) double xTmp(c)[2]; c_dd_add(a, b, xTmp(c)); double c; c = xTmp(c)[0] + xTmp(c)[1]; #define add_d_ld_d(a, b, c) double c = (a) + (b); #define add_ld_ld_d(a, b, c) double c = (a) + (b); #define add_dd_ld_d(a, b, c) double xTmp(b)[2]; xTmp(b)[0] = b; xTmp(b)[1] = b - xTmp(b)[0]; double xTmp(c)[2]; c_dd_add(a, xTmp(b), xTmp(c)); c = xTmp(c)[0]; // check double c = ((a[0]) + (b[0])) + a[1]; @@ -37,10 +43,10 @@ // =========================================== SUB ======================================= #define sub_d_d_d(a, b, c) double c = (a) - (b); #define sub_ld_d_d(a, b, c) long double xTmp(c) = (a) - (b); double c = xTmp(c); -#define sub_dd_d_d(a, b, c) double xTmp(c)[2]; c_dd_sub_dd_d(a, b, xTmp(c)); double c = xTmp(c)[0]; -#define sub_d_dd_d(a, b, c) double xTmp(c)[2]; c_dd_sub_d_dd(a, b, xTmp(c)); double c = xTmp(c)[0]; +#define sub_dd_d_d(a, b, c) double xTmp(c)[2]; c_dd_sub_dd_d(a, b, xTmp(c)); double c = xTmp(c)[0] + xTmp(c)[1]; +#define sub_d_dd_d(a, b, c) double xTmp(c)[2]; c_dd_sub_d_dd(a, b, xTmp(c)); double c = xTmp(c)[0] + xTmp(c)[1]; #define sub_ld_dd_d(a, b, c) double xTmp(a)[2]; xTmp(a)[0] = a; xTmp(a)[1] = a - xTmp(a)[0]; double xTmp(c)[2]; c_dd_sub(xTmp(a), b, xTmp(c)); c = xTmp(c)[0]; // check c = ((a) - (b[0])) - b[1]; -#define sub_dd_dd_d(a, b, c) double xTmp(c)[2]; c_dd_sub(a, b, xTmp(c)); double c; c = xTmp(c)[0]; +#define sub_dd_dd_d(a, b, c) double xTmp(c)[2]; c_dd_sub(a, b, xTmp(c)); double c; c = xTmp(c)[0] + xTmp(c)[1]; #define sub_d_ld_d(a, b, c) double c = (a) - (b); #define sub_ld_ld_d(a, b, c) double c = (a) - (b); #define sub_dd_ld_d(a, b, c) double xTmp(b)[2]; xTmp(b)[0] = b; xTmp(b)[1] = b - xTmp(b)[0]; double xTmp(c)[2]; c_dd_sub(a, xTmp(b), xTmp(c)); c = xTmp(c)[0]; // check double c = ((a[0]) - (b[0])) - a[1]; @@ -68,10 +74,10 @@ // =========================================== MUL ======================================= #define mul_d_d_d(a, b, c) double c = (a) * (b); #define mul_ld_d_d(a, b, c) long double xTmp(c) = (a) * (b); double c = xTmp(c); -#define mul_dd_d_d(a, b, c) double xTmp(c)[2]; c_dd_mul_dd_d(a, b, xTmp(c)); double c = xTmp(c)[0]; -#define mul_d_dd_d(a, b, c) double xTmp(c)[2]; c_dd_mul_d_dd(a, b, xTmp(c)); double c = xTmp(c)[0]; +#define mul_dd_d_d(a, b, c) double xTmp(c)[2]; c_dd_mul_dd_d(a, b, xTmp(c)); double c = xTmp(c)[0] + xTmp(c)[1]; +#define mul_d_dd_d(a, b, c) double xTmp(c)[2]; c_dd_mul_d_dd(a, b, xTmp(c)); double c = xTmp(c)[0] + xTmp(c)[1]; #define mul_ld_dd_d(a, b, c) double xTmp(a)[2]; xTmp(a)[0] = a; xTmp(a)[1] = a - xTmp(a)[0]; double xTmp(c)[2]; c_dd_mul(xTmp(a), b, xTmp(c)); c = xTmp(c)[0]; // TODO: check c = ((a) + (b[0])) + b[1]; -#define mul_dd_dd_d(a, b, c) double xTmp(c)[2]; c_dd_mul(a, b, xTmp(c)); double c; c = xTmp(c)[0]; +#define mul_dd_dd_d(a, b, c) double xTmp(c)[2]; c_dd_mul(a, b, xTmp(c)); double c; c = xTmp(c)[0] + xTmp(c)[1]; #define mul_d_ld_d(a, b, c) double c = (a) * (b); #define mul_ld_ld_d(a, b, c) double c = (a) * (b); #define mul_dd_ld_d(a, b, c) double xTmp(b)[2]; xTmp(b)[0] = b; xTmp(b)[1] = b - xTmp(b)[0]; double xTmp(c)[2]; c_dd_mul(a, xTmp(b), xTmp(c)); c = xTmp(c)[0]; // TODO: check double c = ((a[0]) + (b)) + a[1]; @@ -99,10 +105,10 @@ // =========================================== DIV ======================================= #define div_d_d_d(a, b, c) double c = (a) / (b); #define div_ld_d_d(a, b, c) long double xTmp(c) = (a) / (b); double c = xTmp(c); -#define div_dd_d_d(a, b, c) double xTmp(c)[2]; c_dd_div_dd_d(a, b, xTmp(c)); double c = xTmp(c)[0]; -#define div_d_dd_d(a, b, c) double xTmp(c)[2]; c_dd_div_d_dd(a, b, xTmp(c)); double c = xTmp(c)[0]; +#define div_dd_d_d(a, b, c) double xTmp(c)[2]; c_dd_div_dd_d(a, b, xTmp(c)); double c = xTmp(c)[0] + xTmp(c)[1]; +#define div_d_dd_d(a, b, c) double xTmp(c)[2]; c_dd_div_d_dd(a, b, xTmp(c)); double c = xTmp(c)[0] + xTmp(c)[1]; #define div_ld_dd_d(a, b, c) double xTmp(a)[2]; xTmp(a)[0] = a; xTmp(a)[1] = a - xTmp(a)[0]; double xTmp(c)[2]; c_dd_div(xTmp(a), b, xTmp(c)); c = xTmp(c)[0]; // TODO: check c = ((a) + (b[0])) + b[1]; -#define div_dd_dd_d(a, b, c) double xTmp(c)[2]; c_dd_div(a, b, xTmp(c)); double c; c = xTmp(c)[0]; +#define div_dd_dd_d(a, b, c) double xTmp(c)[2]; c_dd_div(a, b, xTmp(c)); double c; c = xTmp(c)[0] + xTmp(c)[1]; #define div_d_ld_d(a, b, c) double c = (a) / (b); #define div_ld_ld_d(a, b, c) double c = (a) / (b); #define div_dd_ld_d(a, b, c) double xTmp(b)[2]; xTmp(b)[0] = b; xTmp(b)[1] = b - xTmp(b)[0]; double xTmp(c)[2]; c_dd_div(a, xTmp(b), xTmp(c)); c = xTmp(c)[0]; // TODO: check double c = ((a[0]) + (b)) + a[1]; -- Gitee From d2db433e5922e87d4836d89d9055c62beabbf307 Mon Sep 17 00:00:00 2001 From: hjwLab Date: Tue, 9 May 2023 22:27:30 +0800 Subject: [PATCH 10/54] Support the calculation of shadowValue for dd mixed precision type --- Makefile | 2 +- detectErrorOneFPEDParallel.sh | 2 +- include/basic.hpp | 9 ++ include/errorDetect.hpp | 2 + include/funclist.hpp | 42 +++++++ include/geneCode.hpp | 2 +- include/shadowValue.hpp | 2 +- src/basic.cpp | 42 +++++++ src/errorDetect.cpp | 15 +++ src/funclist.cpp | 210 +++++++++++++++++++++++++++++++++- src/geneCode.cpp | 9 +- src/main.cpp | 81 ++++++------- src/shadowValue.cpp | 210 ++++++++++++++++++++++++++++------ 13 files changed, 541 insertions(+), 87 deletions(-) diff --git a/Makefile b/Makefile index 4cba888..70ee34c 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CC = gcc CPP = g++ INCLUDE = -Iinclude -I/usr/include/python3.8 # LIBS= -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -lpython3.8 # may need -L to assign the Python lobrary path -LIBS = -lm -lpython3.8 -lfmt -lmpfr +LIBS = -lm -lpython3.8 -lfmt -lmpfr -lqd ECHO = printf # $(info $(CFLAGS) ) diff --git a/detectErrorOneFPEDParallel.sh b/detectErrorOneFPEDParallel.sh index 9a336c3..0a8449e 100755 --- a/detectErrorOneFPEDParallel.sh +++ b/detectErrorOneFPEDParallel.sh @@ -4,7 +4,7 @@ path=`pwd` cd ${path} CC=mpicc -ERRORMODEL=ABSOLUTE +ERRORMODEL=ULP uniqueLabel=${1} # unique number x0Start=${2} diff --git a/include/basic.hpp b/include/basic.hpp index e044bb7..ac21f92 100644 --- a/include/basic.hpp +++ b/include/basic.hpp @@ -60,6 +60,15 @@ extern std::map commonCall_map; extern std::map doubleRealCall_map; extern std::map commonRealCall_map; +typedef std::function singleCall_dd; +typedef std::function doubleCall_d_dd; +typedef std::function doubleCall_dd_d; +typedef std::function doubleCall_dd_dd; +extern std::map singleCall_dd_map; +extern std::map doubleCall_d_dd_map; +extern std::map doubleCall_dd_d_map; +extern std::map doubleCall_dd_dd_map; + //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// diff --git a/include/errorDetect.hpp b/include/errorDetect.hpp index 82935b4..076de3d 100644 --- a/include/errorDetect.hpp +++ b/include/errorDetect.hpp @@ -17,4 +17,6 @@ double computeUlpUnit(double x); double computeError(mpfr::mpreal oracle, double x); +double computeError(mpfr::mpreal oracle, mpfr::mpreal x); + #endif \ No newline at end of file diff --git a/include/funclist.hpp b/include/funclist.hpp index 36a17ea..b8f7326 100644 --- a/include/funclist.hpp +++ b/include/funclist.hpp @@ -49,4 +49,46 @@ mpfr::mpreal real_tan(vector args); mpfr::mpreal real_pow(vector args); +template +mpfr::mpreal mineadd_d_dd(double x, double *y); + +template +mpfr::mpreal mineadd_dd_d(double *x, double y); + +template +mpfr::mpreal mineadd_dd_dd(double *x, double *y); + +template +mpfr::mpreal minesub_d_dd(double x, double *y); + +template +mpfr::mpreal minesub_dd_d(double *x, double y); + +template +mpfr::mpreal minesub_dd_dd(double *x, double *y); + +template +mpfr::mpreal minemul_d_dd(double x, double *y); + +template +mpfr::mpreal minemul_dd_d(double *x, double y); + +template +mpfr::mpreal minemul_dd_dd(double *x, double *y); + +template +mpfr::mpreal minediv_d_dd(double x, double *y); + +template +mpfr::mpreal minediv_dd_d(double *x, double y); + +template +mpfr::mpreal minediv_dd_dd(double *x, double *y); + +template +mpfr::mpreal minesin_dd(double *x); + +template +mpfr::mpreal minetan_dd(double *x); + #endif \ No newline at end of file diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 3a30611..ddb81fb 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -43,6 +43,6 @@ void getDepth(ast_ptr &expr, int &depth); int showOrder(ast_ptr &expr); -int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail); +int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map values, size_t inputNum); #endif \ No newline at end of file diff --git a/include/shadowValue.hpp b/include/shadowValue.hpp index 775e39a..6102048 100644 --- a/include/shadowValue.hpp +++ b/include/shadowValue.hpp @@ -7,7 +7,7 @@ namespace Shadow { void shadowValue(ast_ptr &expr, double input); template -void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length = 1); +void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length = 1, bool ifUnique = false, string uniqueLabel = "", string funcName = ""); } #endif \ No newline at end of file diff --git a/src/basic.cpp b/src/basic.cpp index 0d3ba87..f612cc9 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "mpreal.h" using std::cerr; using std::cout; @@ -55,6 +56,47 @@ std::map commonRealCall_map = { {"tan", real_tan}, {"pow", real_pow}, }; + +std::map singleCall_dd_map = { + {"sin_d", minesin_dd}, + {"sin_dd", minesin_dd}, + {"tan_d", minetan_dd}, + {"tan_dd", minetan_dd}, +}; + +std::map doubleCall_d_dd_map = { + {"add_d", mineadd_d_dd}, + {"add_dd", mineadd_d_dd}, + {"sub_d", minesub_d_dd}, + {"sub_dd", minesub_d_dd}, + {"mul_d", minemul_d_dd}, + {"mul_dd", minemul_d_dd}, + {"div_d", minediv_d_dd}, + {"div_dd", minediv_d_dd}, +}; + +std::map doubleCall_dd_d_map = { + {"add_d", mineadd_dd_d}, + {"add_dd", mineadd_dd_d}, + {"sub_d", minesub_dd_d}, + {"sub_dd", minesub_dd_d}, + {"mul_d", minemul_dd_d}, + {"mul_dd", minemul_dd_d}, + {"div_d", minediv_dd_d}, + {"div_dd", minediv_dd_d}, +}; + +std::map doubleCall_dd_dd_map = { + {"add_d", mineadd_dd_dd}, + {"add_dd", mineadd_dd_dd}, + {"sub_d", minesub_dd_dd}, + {"sub_dd", minesub_dd_dd}, + {"mul_d", minemul_dd_dd}, + {"mul_dd", minemul_dd_dd}, + {"div_d", minediv_dd_dd}, + {"div_dd", minediv_dd_dd}, +}; + //===----------------------------------------------------------------------===// // basic operation //===----------------------------------------------------------------------===// diff --git a/src/errorDetect.cpp b/src/errorDetect.cpp index 83e3bd0..2c64a48 100644 --- a/src/errorDetect.cpp +++ b/src/errorDetect.cpp @@ -36,5 +36,20 @@ double computeError(mpfr::mpreal oracle, double x) auto unitUlp = computeUlpUnit(oracle.toDouble()); auto errorValue = fabs((oracle - x).toDouble() / unitUlp); + return errorValue; +} + +double computeError(mpfr::mpreal oracle, mpfr::mpreal x) +{ + // absolute error + // double errorValue = fabs((oracle - x).toDouble()); + + // relative error + // double errorValue = fabs(((oracle - x) / oracle).toDouble()); + + // ulp error + auto unitUlp = computeUlpUnit(oracle.toDouble()); + auto errorValue = fabs((oracle - x).toDouble() / unitUlp); + return errorValue; } \ No newline at end of file diff --git a/src/funclist.cpp b/src/funclist.cpp index 93dad0a..6f922ab 100644 --- a/src/funclist.cpp +++ b/src/funclist.cpp @@ -1,7 +1,7 @@ +#include #include "basic.hpp" #include "funclist.hpp" - double mineadd(double x, double y) { return x + y; } @@ -92,4 +92,210 @@ mpfr::mpreal real_tan(vector args) { mpfr::mpreal real_pow(vector args) { return pow(args.at(0), args.at(1)); -} \ No newline at end of file +} + +template +mpfr::mpreal mineadd_d_dd(double x1, double *x2Ptr) +{ + double y[2]; + c_dd_add_d_dd(x1, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal mineadd_dd_d(double *x1Ptr, double x2) +{ + double y[2]; + c_dd_add_dd_d(x1Ptr, x2, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal mineadd_dd_dd(double *x1Ptr, double *x2Ptr) +{ + double y[2]; + c_dd_add(x1Ptr, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minesub_d_dd(double x1, double *x2Ptr) +{ + double y[2]; + c_dd_sub_d_dd(x1, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minesub_dd_d(double *x1Ptr, double x2) +{ + double y[2]; + c_dd_sub_dd_d(x1Ptr, x2, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minesub_dd_dd(double *x1Ptr, double *x2Ptr) +{ + double y[2]; + c_dd_sub(x1Ptr, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minemul_d_dd(double x1, double *x2Ptr) +{ + double y[2]; + c_dd_mul_d_dd(x1, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minemul_dd_d(double *x1Ptr, double x2) +{ + double y[2]; + c_dd_mul_dd_d(x1Ptr, x2, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minemul_dd_dd(double *x1Ptr, double *x2Ptr) +{ + double y[2]; + c_dd_mul(x1Ptr, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minediv_d_dd(double x1, double *x2Ptr) +{ + double y[2]; + c_dd_div_d_dd(x1, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minediv_dd_d(double *x1Ptr, double x2) +{ + double y[2]; + c_dd_div_dd_d(x1Ptr, x2, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minediv_dd_dd(double *x1Ptr, double *x2Ptr) +{ + double y[2]; + c_dd_div(x1Ptr, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minesin_dd(double *x) +{ + double y[2]; + c_dd_sin(x, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minetan_dd(double *x) +{ + double y[2]; + c_dd_tan(x, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +// add +template mpfr::mpreal mineadd_d_dd(double x, double *y); +template mpfr::mpreal mineadd_d_dd(double x, double *y); +template mpfr::mpreal mineadd_dd_d(double *x, double y); +template mpfr::mpreal mineadd_dd_d(double *x, double y); +template mpfr::mpreal mineadd_dd_dd(double *x, double *y); +template mpfr::mpreal mineadd_dd_dd(double *x, double *y); + +// sub +template mpfr::mpreal minesub_d_dd(double x, double *y); +template mpfr::mpreal minesub_d_dd(double x, double *y); +template mpfr::mpreal minesub_dd_d(double *x, double y); +template mpfr::mpreal minesub_dd_d(double *x, double y); +template mpfr::mpreal minesub_dd_dd(double *x, double *y); +template mpfr::mpreal minesub_dd_dd(double *x, double *y); + +// mul +template mpfr::mpreal minemul_d_dd(double x, double *y); +template mpfr::mpreal minemul_d_dd(double x, double *y); +template mpfr::mpreal minemul_dd_d(double *x, double y); +template mpfr::mpreal minemul_dd_d(double *x, double y); +template mpfr::mpreal minemul_dd_dd(double *x, double *y); +template mpfr::mpreal minemul_dd_dd(double *x, double *y); + +// div +template mpfr::mpreal minediv_d_dd(double x, double *y); +template mpfr::mpreal minediv_d_dd(double x, double *y); +template mpfr::mpreal minediv_dd_d(double *x, double y); +template mpfr::mpreal minediv_dd_d(double *x, double y); +template mpfr::mpreal minediv_dd_dd(double *x, double *y); +template mpfr::mpreal minediv_dd_dd(double *x, double *y); + +// single math function +template mpfr::mpreal minesin_dd(double *x); +template mpfr::mpreal minesin_dd(double *x); +template mpfr::mpreal minetan_dd(double *x); +template mpfr::mpreal minetan_dd(double *x); \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index a4bfc63..071babd 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -1,6 +1,7 @@ #include "basic.hpp" #include "geneCode.hpp" #include "parserASTLY.hpp" +#include "shadowValue.hpp" #include #include @@ -1204,7 +1205,7 @@ void codegen(ast_ptr &expr, vector &vars, const string funcName, ofstrea // Note: Each operator node has two states, double or double-double. if there are n node in that expression, there are 2^n states. // Generate double-double implementations in all states and return the number of generated codes -int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail) +int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map varsValue, size_t inputNum) { // AST init auto opOrder = setOrder(expr); @@ -1251,6 +1252,7 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel } setType(expr, opTypes); + // init to generate code string directory = "srcTest/" + uniqueLabel + "/"; string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(num); @@ -1264,6 +1266,11 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel ofstream file_clean(fileName, ios_base::out); ofstream ofs(fileName, ios::app); + /// call shadowValue to generate each step's values of expr. + // varsValue is input values + // inputNum is the number of input data + Shadow::shadowValue(expr, varsValue, inputNum, true, uniqueLabel, funcName); + // call codegen to generate code codegen(expr, vars, funcName, ofs); } diff --git a/src/main.cpp b/src/main.cpp index 02510f4..bba17b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -282,43 +282,16 @@ int main() auto funcNameMpfr = geneMpfrCode(inputStr, uniqueLabel, vars); printExpr(originExpr, "the origin expr: "); showOrder(originExpr); - auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd"); - vector startNowIdxs(dimension, 0); - vector startOriginIntervals; - vector steps; - for (int i = 0; i < dimension; i++) - { - auto &startOriginInterval = intervals.at(i * 2); - auto &endOriginInterval = intervals.at(i * 2 + 1); - startOriginIntervals.push_back(startOriginInterval); - double width = endOriginInterval - startOriginInterval; - double step = width / (double)scales.at(i); - steps.push_back(step); - } - // auto tmpType = originExpr->type(); - // if(tmpType == "Binary") - // { - // BinaryExprAST *tmpBinaryExpr = dynamic_cast(originExpr.get()); - // auto tmpCall = tmpBinaryExpr->getCallback(); - // auto tmpResult = tmpCall(1.3, 2.4); - // cout << "op = " << tmpBinaryExpr->getOp() << " tmpResult = " << tmpResult << endl; - // } - // else if (tmpType == "Call") - // { - // CallExprAST *tmpCallExpr = dynamic_cast(originExpr.get()); - // auto tmpCall = tmpCallExpr->getCallback(); - // vector args{1.3}; - // auto tmpResult = tmpCall(args); - // cout << "callee = " << tmpCallExpr->getCallee() << " tmpResult = " << tmpResult << endl; - // } + + //// a simple try for shadow value // vector values(dimension, 1.4); // auto varsValue = setVarsValue(vars, values); // fmt::print("varsValue = {}\n", varsValue); // Shadow::shadowValue(originExpr, varsValue); - // generate input data + //// generate input data for shadow value vector values1; - size_t inputNum = 1000; + size_t inputNum = 10; for(int i = 0; i < dimension; i++) { auto &startOriginInterval = intervals.at(i * 2); @@ -334,25 +307,43 @@ int main() values1.push_back(tmp); } auto varsValue1 = setVarsValue(vars, values1); - // call the shadowValue function to generate the shadow values of the expression. - Shadow::shadowValue(originExpr, varsValue1, inputNum); - // TODO: free values1 - testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); - vector infos; - for(int i = 0; i < maxNum; i++) { - string tmp = "dd_" + std::to_string(i); - auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); - infos.push_back(infoTmp); - } - cout << "No\taverage Err\tmax Err\n"; - for(size_t i = 0; i < infos.size(); i++) + //// call the shadowValue function to generate the shadow values of the expression. The shadow values are stored into files partly. + // Shadow::shadowValue(originExpr, varsValue1, inputNum); + //// TODO: free values1 + + //// support DD + auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum); + //// test DD's error + vector startNowIdxs(dimension, 0); + vector startOriginIntervals; + vector steps; + for (int i = 0; i < dimension; i++) { - auto &info = infos.at(i); - cout << i << "\t" << info.aveError << "\t" << info.maxError << "\n"; + auto &startOriginInterval = intervals.at(i * 2); + auto &endOriginInterval = intervals.at(i * 2 + 1); + startOriginIntervals.push_back(startOriginInterval); + double width = endOriginInterval - startOriginInterval; + double step = width / (double)scales.at(i); + steps.push_back(step); } + // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); + // vector infos; + // for(int i = 0; i < maxNum; i++) { + // string tmp = "dd_" + std::to_string(i); + // auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + // infos.push_back(infoTmp); + // } + // cout << "No\taverage Err\tmax Err\n"; + // for(size_t i = 0; i < infos.size(); i++) + // { + // auto &info = infos.at(i); + // cout << i << "\t" << info.aveError << "\t" << info.maxError << "\n"; + // } + // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); fprintf(stderr, GREEN "ready> " RESET); continue; + // if(exprOrigin != "") // { // originPerformance = testPerformance(uniqueLabel, "origin", intervals); diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 32278fa..8bde56c 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "mpreal.h" #include "shadowValue.hpp" #include "funclist.hpp" @@ -79,6 +80,19 @@ void shadowValue(ast_ptr &expr, double input) fmt::print("middleValues := {}\n", middleValues); } +std::map binaryOp = { + {'+', "add"}, + {'-', "sub"}, + {'*', "mul"}, + {'/', "div"}, +}; + +std::map opTypeMap = { + {"double", "d"}, + {"DD", "dd"}, + {"ld", "ld"}, +}; + template struct ParamTypeMapper { @@ -102,16 +116,16 @@ using ParamType = typename ParamTypeMapper::ParamType; template struct valueTwo { - T funcValue; + ParamType funcValue; ParamType realValue; }; template -valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, int length = 1) +valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector> &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, int length = 1) { auto type = expr->type(); - constexpr bool TisDouble = (std::is_same::value); - constexpr bool TisDoublePointer = (std::is_same::value); + constexpr bool TisDouble = (std::is_same::value); + constexpr bool TisDoublePointer = (std::is_same::value); valueTwo result; if(type == "Number") { @@ -128,7 +142,7 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va } else if constexpr (TisDoublePointer) { - auto tmpfuncValues = new double[length]; + auto tmpfuncValues = new mpfr::mpreal[length]; auto tmpRealValues = new mpfr::mpreal[length]; auto tmperrorValues = new double[length](); for(int i = 0; i < length; i++) @@ -167,7 +181,7 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va } else if constexpr (TisDoublePointer) { - auto tmpfuncValues = new double[length]; + auto tmpfuncValues = new mpfr::mpreal[length]; auto tmpRealValues = new mpfr::mpreal[length]; auto tmperrorValues = new double[length](); for(int i = 0; i < length; i++) @@ -195,10 +209,11 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va { CallExprAST *callPtr = dynamic_cast(expr.get()); auto &args = callPtr->getArgs(); - vector paramResults; + vector> paramResults; + vector paramResultsDouble; vector> paramFuncRealResults; vector> parammathRealResults; - + for(auto& arg : args) { auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); @@ -206,33 +221,72 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va if constexpr (TisDouble) { paramFuncRealResults.push_back(tmp.funcValue); + paramResultsDouble.push_back((tmp.funcValue).toDouble()); } parammathRealResults.push_back(tmp.realValue); } // func auto tmpCall = callPtr->getCallback(); - + auto callee = callPtr->getCallee(); + auto calleeType = callPtr->getOpType(); + auto callTypeStr = opTypeMap.find(calleeType)->second; + string mapType; + for(const auto& arg : args) + { + auto opType = arg->getOpType(); + auto opTypeStr = opTypeMap.find(opType)->second; + mapType += "_" + opTypeStr; + } + // func value if constexpr (TisDouble) { - result.funcValue = tmpCall(paramResults); + if(mapType == "_dd") + { + double x1[2]{0}; + x1[0] = paramResults.at(0).toDouble(); + x1[1] = (paramResults.at(0) - x1[0]).toDouble(); + auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; + mpfr::mpreal tmp = tmpSingleCall(x1); + result.funcValue = tmp; + } + else + { + result.funcValue = tmpCall(paramResultsDouble); + } std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; funcValues.push_back(result.funcValue); } else if constexpr (TisDoublePointer) { - auto tmpfuncValues = new double[length]; - for(int i = 0; i < length; i++) + auto tmpfuncValues = new mpfr::mpreal[length]; + if(mapType == "_dd") { - vector tmpParam; - for(auto ¶m : paramResults) + double x1[2]{0}; + mpfr::mpreal tmp; + for(int i = 0; i < length; i++) { - tmpParam.push_back(param[i]); + x1[0] = ((paramResults.at(0))[i]).toDouble(); + x1[1] = ((paramResults.at(0))[i] - x1[0]).toDouble(); + auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; + tmpfuncValues[i] = tmpSingleCall(x1); + } + } + else + { + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : paramResults) + { + tmpParam.push_back((param[i]).toDouble()); + } + auto funcValue = tmpCall(tmpParam); + tmpfuncValues[i] = funcValue; } - auto funcValue = tmpCall(tmpParam); - tmpfuncValues[i] = funcValue; } + result.funcValue = tmpfuncValues; funcValues.push_back(tmpfuncValues); } @@ -269,7 +323,7 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va auto funcRealValue = tmpRealCall(tmpParam); tmpfuncRealValues[i] = funcRealValue; - tmpErrorValues[i] = computeError(funcRealValue, (result.funcValue)[i]); + tmpErrorValues[i] = computeError(funcRealValue, ((result.funcValue)[i])); } funcRealValues.push_back(tmpfuncRealValues); errorValues.push_back(tmpErrorValues); @@ -318,27 +372,100 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va ast_ptr &rhs = binPtr->getRHS(); auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); - + // func auto tmpCall = binPtr->getCallback(); - + auto op = binPtr->getOp(); + auto opType = binPtr->getOpType(); + auto opTypeStr = opTypeMap.find(opType)->second; + auto opTypeLHS = lhs->getOpType(); + auto opTypeRHS = rhs->getOpType(); + auto opStr = binaryOp.find(op)->second; + auto opTypeLhsStr = opTypeMap.find(opTypeLHS)->second; + auto opTypeRhsStr = opTypeMap.find(opTypeRHS)->second; + auto mapType = opTypeLhsStr + "_" + opTypeRhsStr; + // func value if constexpr (TisDouble) { - result.funcValue = tmpCall(lhsValue.funcValue, rhsValue.funcValue); + double x1[2]{0}; + double x2[2]{0}; + x1[0] = lhsValue.funcValue.toDouble(); + x2[0] = rhsValue.funcValue.toDouble(); + if(mapType == "d_dd") + { + auto tmpDoubleCall = doubleCall_d_dd_map.find(opStr + "_" + opTypeStr)->second; + result.funcValue = tmpDoubleCall(x1[0], x2); + } + else if(mapType == "dd_d") + { + auto tmpDoubleCall = doubleCall_dd_d_map.find(opStr + "_" + opTypeStr)->second; + result.funcValue = tmpDoubleCall(x1, x2[0]); + } + else if(mapType == "dd_dd") + { + auto tmpDoubleCall = doubleCall_dd_dd_map.find(opStr + "_" + opTypeStr)->second; + result.funcValue = tmpDoubleCall(x1, x2); + } + else + { + result.funcValue = tmpCall(x1[0], x2[0]); + } std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; funcValues.push_back(result.funcValue); + } else if constexpr (TisDoublePointer) { - auto tmpfuncValues = new double[length]; - for(int i = 0; i < length; i++) + auto tmpfuncValues = new mpfr::mpreal[length]; + double x1[2]{0}; + double x2[2]{0}; + if(mapType == "d_dd") { - double &tmpLhsValue = (lhsValue.funcValue)[i]; - double &tmpRhsValue = (rhsValue.funcValue)[i]; - - auto funcValue = tmpCall(tmpLhsValue, tmpRhsValue); - tmpfuncValues[i] = funcValue; + auto tmpDoubleCall = doubleCall_d_dd_map.find(opStr + "_" + opTypeStr)->second; + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + x2[0] = tmpRhsValue.toDouble(); + x2[1] = (tmpRhsValue - x2[0]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(tmpLhsValue.toDouble(), x2); + } + } + else if(mapType == "dd_d") + { + auto tmpDoubleCall = doubleCall_dd_d_map.find(opStr + "_" + opTypeStr)->second; + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + x1[0] = tmpLhsValue.toDouble(); + x1[1] = (tmpLhsValue - x1[0]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(x1, tmpRhsValue.toDouble()); + } + } + else if(mapType == "dd_dd") + { + auto tmpDoubleCall = doubleCall_dd_dd_map.find(opStr + "_" + opTypeStr)->second; + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + x1[0] = tmpLhsValue.toDouble(); + x1[1] = (tmpLhsValue - x1[0]).toDouble(); + x2[0] = tmpRhsValue.toDouble(); + x2[1] = (tmpRhsValue - x2[0]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(x1, x2); + } + } + else // d_d + { + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + tmpfuncValues[i] = tmpCall(tmpLhsValue.toDouble(), tmpRhsValue.toDouble()); + } } result.funcValue = tmpfuncValues; funcValues.push_back(tmpfuncValues); @@ -434,17 +561,21 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va } template -void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length) +void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, string uniqueLabel, string funcName) { mpfr::mpreal::set_default_prec(128); - vector funcValues; + vector> funcValues; vector errorValues; // this error is f(x+\delta x) between F(x + \delta x) if constexpr (std::is_same::value) { std::vector funcRealValues; std::vector mathRealValues; shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); - fmt::print("funcValues := {}\n", funcValues); + // fmt::print("funcValues := {}\n", funcValues); + for(auto &funcValue : funcValues) + { + std::cout << "func value: " << funcValue.toString() << std::endl; + } for(auto &funRealValue : funcRealValues) { std::cout << "func real value: " << funRealValue.toString() << std::endl; @@ -466,7 +597,7 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int // { // for(size_t j = 0; j < funcValues.size(); j++) // { - // fprintf(stderr, "input NO.%d step NO.%ld: funcValue = %g\n", i, j, (funcValues.at(j))[i]); + // fprintf(stderr, "input NO.%d step NO.%ld: funcValue = %s\n", i, j, (funcValues.at(j))[i].toString().c_str()); // fprintf(stderr, "input NO.%d step NO.%ld: funcRealValue = %s\n", i, j, (funcRealValues.at(j))[i].toString().c_str()); // fprintf(stderr, "input NO.%d step NO.%ld: mathRealValue = %s\n", i, j, (mathRealValues.at(j))[i].toString().c_str()); // fprintf(stderr, "input NO.%d step NO.%ld: errorValue = %g\n\n", i, j, (errorValues.at(j))[i]); @@ -483,7 +614,16 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int for(size_t i = 0; i < funcValues.size(); i++) { std::ofstream fout; - string filename = "./errorFunc_" + std::to_string(i) + ".txt"; + + string filename = "./outputs/"; // i is represent the step of expression + if(ifUnique) + { + filename += uniqueLabel + "/errorFunc_" + funcName + "_" + std::to_string(i) + ".txt"; // i is represent the step of expression + } + else + { + filename += "errorFunc_" + std::to_string(i) + ".txt"; // i is represent the step of expression + } fout.open(filename, ios::out); if (!fout.is_open()) { @@ -522,7 +662,7 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int } } -template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length); -template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length); +template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, std::string uniqueLabel, std::string funcName); +template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, std::string uniqueLabel, std::string funcName); } \ No newline at end of file -- Gitee From bcb44f2a345960460503fa1654ec3d188f1e6083 Mon Sep 17 00:00:00 2001 From: Xia yuanyuan Date: Mon, 22 May 2023 10:44:32 +0800 Subject: [PATCH 11/54] Support the calculation of condition number in shadowValue method --- include/errorDetect.hpp | 2 + src/errorDetect.cpp | 5 + src/shadowValue.cpp | 836 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 806 insertions(+), 37 deletions(-) diff --git a/include/errorDetect.hpp b/include/errorDetect.hpp index 076de3d..1093dc3 100644 --- a/include/errorDetect.hpp +++ b/include/errorDetect.hpp @@ -15,6 +15,8 @@ typedef union { double computeUlpUnit(double x); +double computeUlpUnit(mpfr::mpreal oracle); + double computeError(mpfr::mpreal oracle, double x); double computeError(mpfr::mpreal oracle, mpfr::mpreal x); diff --git a/src/errorDetect.cpp b/src/errorDetect.cpp index 2c64a48..1df89fb 100644 --- a/src/errorDetect.cpp +++ b/src/errorDetect.cpp @@ -24,6 +24,11 @@ double computeUlpUnit(double x) { return x0.d; } +double computeUlpUnit(mpfr::mpreal oracle) { + double x = oracle.toDouble(); + return computeUlpUnit(x); +} + double computeError(mpfr::mpreal oracle, double x) { // absolute error diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 8bde56c..186ce6c 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -15,8 +15,37 @@ using std::string; using std::vector; using std::ofstream; using std::ios; + namespace Shadow { +std::map> fDrvMapOne = { + {"exp", [](double x) { return exp(x); }}, + {"exp2", [](double x) { return exp2(x) * log(2); }}, + {"exp10", [](double x) { return exp10(x) * log(10); }}, + {"log", [](double x) { return (1 / x); }}, + {"log2", [](double x) { return (1 / (x * log(2))); }}, + {"log10", [](double x) { return (1 / (x * log(10))); }}, + {"sin", [](double x) { return cos(x); }}, + {"cos", [](double x) { return -sin(x); }}, + {"tan", [](double x) { return 1 / (cos(x) * cos(x)); }}, + {"arcsin", [](double x) { return 1 / sqrt(1 - x * x); }}, + {"arccos", [](double x) { return -1 / sqrt(1 - x * x); }}, + {"arctan", [](double x) { return 1 / (1 + x * x); }}, +}; + +std::map> fDrvMapTwo = { + {"addL", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return 1; }}, + {"addR", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return 1; }}, + {"subL", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return 1; }}, + {"subR", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return -1; }}, + {"mulL", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return y; }}, + {"mulR", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return x; }}, + {"divL", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return 1 / y; }}, + {"divR", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return -x / (y * y); }}, + {"powL", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return y * pow(x, y - 1); }}, + {"powR", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return log(x) * pow(x, y); }}, +}; + // demo double shadowValueKernel(ast_ptr &expr, double &input, vector &middleValues) { @@ -114,6 +143,7 @@ struct ParamTypeMapper template using ParamType = typename ParamTypeMapper::ParamType; +/* /// old shadowValueKernel method: not consider conditionNumbers. template struct valueTwo { ParamType funcValue; @@ -559,51 +589,781 @@ valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &va exit(EXIT_FAILURE); } } +*/ template -void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, string uniqueLabel, string funcName) +struct valueThree { + ParamType funcValue; + ParamType realValue; + T ulpValue; +}; + +template +void computeConditionNumberKernel(vector &conditionNumbers, vector &conditionNumbersOp, const int IDfather, int &IDnow, const int length = 1) { - mpfr::mpreal::set_default_prec(128); - vector> funcValues; - vector errorValues; // this error is f(x+\delta x) between F(x + \delta x) - if constexpr (std::is_same::value) + constexpr bool TisDouble = (std::is_same::value); + constexpr bool TisDoublePointer = (std::is_same::value); + if constexpr (TisDouble) { - std::vector funcRealValues; - std::vector mathRealValues; - shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); - // fmt::print("funcValues := {}\n", funcValues); - for(auto &funcValue : funcValues) + conditionNumbersOp.at(IDnow) = conditionNumbersOp.at(IDfather) * conditionNumbers.at(IDnow); + } + else if constexpr (TisDoublePointer) + { + for(int i = 0; i < length; i++) { - std::cout << "func value: " << funcValue.toString() << std::endl; + conditionNumbersOp.at(IDnow)[i] = conditionNumbersOp.at(IDfather)[i] * conditionNumbers.at(IDnow)[i]; } - for(auto &funRealValue : funcRealValues) + } + else + { + fprintf(stderr, "ERROR: %s: the type of T %s is not supported\n", __func__, typeid(T).name()); + exit(EXIT_FAILURE); + } +} + +template +void computeConditionNumber(const ast_ptr &expr, vector &conditionNumbers, vector &conditionNumbersOp, const int IDfather, int &IDnow, const int length = 1) +{ + auto type = expr->type(); + if(type == "Number") + { + return ; // do nothing + } + else if (type == "Variable") + { + return ; // do nothing + } + else if (type == "Call") + { + CallExprAST *callPtr = dynamic_cast(expr.get()); + auto &args = callPtr->getArgs(); + auto IDparam = new int[args.size()]; + + for (size_t i = args.size() - 1; i >= 0; i--) { - std::cout << "func real value: " << funRealValue.toString() << std::endl; + computeConditionNumberKernel(conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); + IDparam[i] = IDnow; + IDnow--; } - for(auto &mathRealValue : mathRealValues) + for (size_t i = args.size() - 1; i >= 0; i--) { - std::cout << "math real value: " << mathRealValue.toString() << std::endl; + const auto &arg = args.at(i); + computeConditionNumber(arg, conditionNumbers, conditionNumbersOp, IDparam[i], IDnow, length); } - fmt::print("errorValues := {}\n", errorValues); + delete []IDparam; } - else if constexpr (std::is_same::value) + else if (type == "Binary") { - std::vector funcRealValues; - std::vector mathRealValues; - shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); - // TODO: free funcValues, funcRealValues, mathRealValues, errorValues - // print to the screen - // for(int i = 0; i < length; i++) - // { - // for(size_t j = 0; j < funcValues.size(); j++) - // { - // fprintf(stderr, "input NO.%d step NO.%ld: funcValue = %s\n", i, j, (funcValues.at(j))[i].toString().c_str()); - // fprintf(stderr, "input NO.%d step NO.%ld: funcRealValue = %s\n", i, j, (funcRealValues.at(j))[i].toString().c_str()); - // fprintf(stderr, "input NO.%d step NO.%ld: mathRealValue = %s\n", i, j, (mathRealValues.at(j))[i].toString().c_str()); - // fprintf(stderr, "input NO.%d step NO.%ld: errorValue = %g\n\n", i, j, (errorValues.at(j))[i]); - // } - // fprintf(stderr, "================================\n\n"); - // } + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + + computeConditionNumberKernel(conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); + auto IDrhs = IDnow; + IDnow--; + computeConditionNumberKernel(conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); + auto IDlhs = IDnow; + IDnow--; + + computeConditionNumber(rhs, conditionNumbers, conditionNumbersOp, IDrhs, IDnow, length); + computeConditionNumber(lhs, conditionNumbers, conditionNumbersOp, IDlhs, IDnow, length); + } + else + { + fprintf(stderr, "ERROR : %s : unknowntype %s\n", __func__, type.c_str()); + exit(EXIT_FAILURE); + } +} + +template +valueThree shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector> &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, vector &conditionNumbers, int length = 1) +{ + auto type = expr->type(); + constexpr bool TisDouble = (std::is_same::value); + constexpr bool TisDoublePointer = (std::is_same::value); + valueThree result; + if(type == "Number") + { + NumberExprAST *numberExpr = dynamic_cast(expr.get()); + auto funcValue = (numberExpr->getNumber()); + if constexpr (TisDouble) + { + result.funcValue = funcValue; + result.realValue = result.funcValue; + result.ulpValue = computeUlpUnit(funcValue); // may set to ZERO! + funcValues.push_back(result.funcValue); + funcRealValues.push_back(result.realValue); + mathRealValues.push_back(result.realValue); + errorValues.push_back(0); + // conditionNumber : do nothing + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncValues = new mpfr::mpreal[length]; + auto tmpRealValues = new mpfr::mpreal[length]; + auto tmperrorValues = new double[length](); + auto tmpUlpValues = new double[length](); + for(int i = 0; i < length; i++) + { + tmpfuncValues[i] = funcValue; + tmpRealValues[i] = funcValue; + tmpUlpValues[i] = computeUlpUnit(funcValue); // may set to ZERO! + } + result.funcValue = tmpfuncValues; + result.realValue = tmpRealValues; + result.ulpValue = tmpUlpValues; + funcValues.push_back(tmpfuncValues); + funcRealValues.push_back(tmpRealValues); + mathRealValues.push_back(tmpRealValues); + errorValues.push_back(tmperrorValues); + // conditionNumber : do nothing + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + return result; + } + else if(type == "Variable") + { + VariableExprAST *variableExpr = dynamic_cast(expr.get()); + string variable = (variableExpr->getVariable()); + auto varValue = varsValue.find(variable)->second; + // if(std::is_same::type, T>::value) + if constexpr (TisDouble) + { + result.funcValue = varValue; + result.realValue = result.funcValue; + result.ulpValue = computeUlpUnit(varValue); + funcValues.push_back(result.funcValue); + funcRealValues.push_back(result.realValue); + mathRealValues.push_back(result.realValue); + errorValues.push_back(0); + // conditionNumber : do nothing + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncValues = new mpfr::mpreal[length]; + auto tmpRealValues = new mpfr::mpreal[length]; + auto tmperrorValues = new double[length](); + auto tmpUlpValues = new double[length](); + for(int i = 0; i < length; i++) + { + auto &tmpfuncValue = varValue[i]; + tmpfuncValues[i] = tmpfuncValue; + tmpRealValues[i] = tmpfuncValue; + tmpUlpValues[i] = computeUlpUnit(tmpfuncValue); + } + result.funcValue = tmpfuncValues; + result.realValue = tmpRealValues; + result.ulpValue = tmpUlpValues; + funcValues.push_back(tmpfuncValues); + funcRealValues.push_back(tmpRealValues); + mathRealValues.push_back(tmpRealValues); + errorValues.push_back(tmperrorValues); + // conditionNumber : do nothing + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + return result; + } + else if(type == "Call") + { + CallExprAST *callPtr = dynamic_cast(expr.get()); + auto &args = callPtr->getArgs(); + vector> paramResults; + vector paramResultsDouble; + vector> paramFuncRealResults; + vector> parammathRealResults; + vector paramUlpResults; + + for(auto& arg : args) + { + auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); + paramResults.push_back(tmp.funcValue); + if constexpr (TisDouble) + { + paramFuncRealResults.push_back(tmp.funcValue); + paramResultsDouble.push_back((tmp.funcValue).toDouble()); + } + parammathRealResults.push_back(tmp.realValue); + paramUlpResults.push_back(tmp.ulpValue); + } + + // func + auto tmpCall = callPtr->getCallback(); + auto callee = callPtr->getCallee(); + auto calleeType = callPtr->getOpType(); + auto callTypeStr = opTypeMap.find(calleeType)->second; + string mapType; + for(const auto& arg : args) + { + auto opType = arg->getOpType(); + auto opTypeStr = opTypeMap.find(opType)->second; + mapType += "_" + opTypeStr; + } + + // func value + if constexpr (TisDouble) + { + if(mapType == "_dd") + { + double x1[2]{0}; + x1[0] = paramResults.at(0).toDouble(); + x1[1] = (paramResults.at(0) - x1[0]).toDouble(); + auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; + mpfr::mpreal tmp = tmpSingleCall(x1); + result.funcValue = tmp; + } + else + { + result.funcValue = tmpCall(paramResultsDouble); + } + std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; + funcValues.push_back(result.funcValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncValues = new mpfr::mpreal[length]; + if(mapType == "_dd") + { + double x1[2]{0}; + mpfr::mpreal tmp; + for(int i = 0; i < length; i++) + { + x1[0] = ((paramResults.at(0))[i]).toDouble(); + x1[1] = ((paramResults.at(0))[i] - x1[0]).toDouble(); + auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; + tmpfuncValues[i] = tmpSingleCall(x1); + } + } + else + { + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : paramResults) + { + tmpParam.push_back((param[i]).toDouble()); + } + auto funcValue = tmpCall(tmpParam); + tmpfuncValues[i] = funcValue; + } + } + + result.funcValue = tmpfuncValues; + funcValues.push_back(tmpfuncValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + // real func + auto tmpRealCall = callPtr->getRealCallback(); + + // func real value + if constexpr (TisDouble) + { + mpfr::mpreal funcRealValue = tmpRealCall(paramFuncRealResults); + std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; + funcRealValues.push_back(funcRealValue); + + auto errorValue = computeError(funcRealValue, result.funcValue); + errorValues.push_back(errorValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncRealValues = new mpfr::mpreal[length]; + auto tmpErrorValues = new double[length]; + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : paramResults) + { + tmpParam.push_back(param[i]); + } + auto funcRealValue = tmpRealCall(tmpParam); + tmpfuncRealValues[i] = funcRealValue; + + tmpErrorValues[i] = computeError(funcRealValue, ((result.funcValue)[i])); + } + funcRealValues.push_back(tmpfuncRealValues); + errorValues.push_back(tmpErrorValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + // math real value + if constexpr (TisDouble) + { + result.realValue = tmpRealCall(parammathRealResults); + std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; + result.ulpValue = computeUlpUnit(result.realValue); + mathRealValues.push_back(result.realValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpmathRealValues = new mpfr::mpreal[length]; + auto tmpUlpValues = new double[length]; + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : parammathRealResults) + { + tmpParam.push_back(param[i]); + } + auto mathRealValue = tmpRealCall(tmpParam); + tmpmathRealValues[i] = mathRealValue; + tmpUlpValues[i] = computeUlpUnit(mathRealValue); + } + mathRealValues.push_back(tmpmathRealValues); + result.realValue = tmpmathRealValues; + result.ulpValue = tmpUlpValues; + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + // condition number value + if constexpr (TisDouble) + { + auto &ulpY = result.ulpValue; + // std::function funcDrv = [](double x){ return exp(x); }; + // std::function funcDrv = &exp; // wrong! + // std::function funcDrv = exp; // wrong! + const size_t &lenParam = args.size(); + if (lenParam == 1) + { + std::function funcDrv = fDrvMapOne.find(callee)->second; + auto &ulpX = paramUlpResults.at(0); + auto input = parammathRealResults.at(0).toDouble(); + auto derivativeFuncValue = funcDrv(input); + auto conditionNumber = ulpX * derivativeFuncValue / ulpY; + conditionNumbers.push_back(conditionNumber); + } + else if (lenParam == 2) + { + std::function funcDrv; + auto inputX1 = parammathRealResults.at(0).toDouble(); + auto inputX2 = parammathRealResults.at(1).toDouble(); + + funcDrv = fDrvMapTwo.find(callee + "L")->second; + auto derivativeFuncValue = funcDrv(inputX1, inputX2); + auto &ulpX1 = paramUlpResults.at(0); + auto conditionNumber = ulpX1 * derivativeFuncValue / ulpY; + conditionNumbers.push_back(conditionNumber); + + funcDrv = fDrvMapTwo.find(callee + "R")->second; + derivativeFuncValue = funcDrv(inputX1, inputX2); + auto &ulpX2 = paramUlpResults.at(1); + conditionNumber = ulpX2 * derivativeFuncValue / ulpX2; + conditionNumbers.push_back(conditionNumber); + } + else + { + fprintf(stderr, "shadowValueKernel: we can not support %ld parameters' function call\n", lenParam); + exit(EXIT_FAILURE); + } + // for(size_t i = 0; i < parammathRealResults.size(); i++) + // { + // auto &ulpX = paramUlpResults.at(i); + // auto input = parammathRealResults.at(i).toDouble(); + // auto derivativeFuncValue = funcDrv(input); + // auto conditionNumber = (ulpX * derivativeFuncValue / ulpY).toDouble(); + // conditionNumbers.push_back(conditionNumber); + // } + } + else if constexpr (TisDoublePointer) + { + auto &ulpYs = result.ulpValue; + // std::function funcDrv = [](double x){ return exp(x); }; + // std::function funcDrv = &exp; // wrong! + // std::function funcDrv = exp; // wrong! + const size_t &lenParam = args.size(); + if (lenParam == 1) + { + std::function funcDrv = fDrvMapOne.find(callee)->second; + auto tmpConditionNumbers = new double[length]; + for(int i = 0; i < length; i++) + { + auto ulpX = paramUlpResults.at(0)[i]; + auto input = parammathRealResults.at(0)[i].toDouble(); + auto derivativeFuncValue = funcDrv(input); + tmpConditionNumbers[i] = ulpX * derivativeFuncValue / ulpYs[i]; + } + conditionNumbers.push_back(tmpConditionNumbers); + } + else if (lenParam == 2) + { + std::function funcDrvL, funcDrvR; + auto tmpConditionNumbers1 = new double[length]; + auto tmpConditionNumbers2 = new double[length]; + funcDrvL = fDrvMapTwo.find(callee + "L")->second; + funcDrvR = fDrvMapTwo.find(callee + "R")->second; + for(int i = 0; i < length; i++) + { + auto inputX1 = parammathRealResults.at(0)[i].toDouble(); + auto inputX2 = parammathRealResults.at(1)[i].toDouble(); + + auto derivativeFuncValue = funcDrvL(inputX1, inputX2); + auto &ulpX1 = paramUlpResults.at(0)[i]; + tmpConditionNumbers1[i] = ulpX1 * derivativeFuncValue / ulpYs[i]; + + derivativeFuncValue = funcDrvR(inputX1, inputX2); + auto &ulpX2 = paramUlpResults.at(1)[i]; + tmpConditionNumbers2[i] = ulpX2 * derivativeFuncValue / ulpYs[i]; + } + conditionNumbers.push_back(tmpConditionNumbers1); + conditionNumbers.push_back(tmpConditionNumbers2); + } + else + { + fprintf(stderr, "shadowValueKernel: we can not support %ld parameters' function call\n", lenParam); + exit(EXIT_FAILURE); + } + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + return result; + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); + auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); + + // func + auto tmpCall = binPtr->getCallback(); + auto op = binPtr->getOp(); + auto opType = binPtr->getOpType(); + auto opTypeStr = opTypeMap.find(opType)->second; + auto opTypeLHS = lhs->getOpType(); + auto opTypeRHS = rhs->getOpType(); + auto opStr = binaryOp.find(op)->second; + auto opTypeLhsStr = opTypeMap.find(opTypeLHS)->second; + auto opTypeRhsStr = opTypeMap.find(opTypeRHS)->second; + auto mapType = opTypeLhsStr + "_" + opTypeRhsStr; + + // func value + if constexpr (TisDouble) + { + double x1[2]{0}; + double x2[2]{0}; + x1[0] = lhsValue.funcValue.toDouble(); + x2[0] = rhsValue.funcValue.toDouble(); + if(mapType == "d_dd") + { + auto tmpDoubleCall = doubleCall_d_dd_map.find(opStr + "_" + opTypeStr)->second; + result.funcValue = tmpDoubleCall(x1[0], x2); + } + else if(mapType == "dd_d") + { + auto tmpDoubleCall = doubleCall_dd_d_map.find(opStr + "_" + opTypeStr)->second; + result.funcValue = tmpDoubleCall(x1, x2[0]); + } + else if(mapType == "dd_dd") + { + auto tmpDoubleCall = doubleCall_dd_dd_map.find(opStr + "_" + opTypeStr)->second; + result.funcValue = tmpDoubleCall(x1, x2); + } + else + { + result.funcValue = tmpCall(x1[0], x2[0]); + } + std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; + funcValues.push_back(result.funcValue); + + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncValues = new mpfr::mpreal[length]; + double x1[2]{0}; + double x2[2]{0}; + if(mapType == "d_dd") + { + auto tmpDoubleCall = doubleCall_d_dd_map.find(opStr + "_" + opTypeStr)->second; + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + x2[0] = tmpRhsValue.toDouble(); + x2[1] = (tmpRhsValue - x2[0]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(tmpLhsValue.toDouble(), x2); + } + } + else if(mapType == "dd_d") + { + auto tmpDoubleCall = doubleCall_dd_d_map.find(opStr + "_" + opTypeStr)->second; + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + x1[0] = tmpLhsValue.toDouble(); + x1[1] = (tmpLhsValue - x1[0]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(x1, tmpRhsValue.toDouble()); + } + } + else if(mapType == "dd_dd") + { + auto tmpDoubleCall = doubleCall_dd_dd_map.find(opStr + "_" + opTypeStr)->second; + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + x1[0] = tmpLhsValue.toDouble(); + x1[1] = (tmpLhsValue - x1[0]).toDouble(); + x2[0] = tmpRhsValue.toDouble(); + x2[1] = (tmpRhsValue - x2[0]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(x1, x2); + } + } + else // d_d + { + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + tmpfuncValues[i] = tmpCall(tmpLhsValue.toDouble(), tmpRhsValue.toDouble()); + } + } + result.funcValue = tmpfuncValues; + funcValues.push_back(tmpfuncValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + // real func + auto tmpRealCall = binPtr->getRealCallback(); + + // func real value + if constexpr (TisDouble) + { + mpfr::mpreal funcRealValue = tmpRealCall(lhsValue.funcValue, rhsValue.funcValue); + std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; + funcRealValues.push_back(funcRealValue); + + auto errorValue = computeError(funcRealValue, result.funcValue); + errorValues.push_back(errorValue); + + // absolute error + // double absErrorValue = fabs((funcRealValue - result.funcValue).toDouble()); + // errorValues.push_back(absErrorValue); + // relative error + // double relErrorValue = fabs(((funcRealValue - result.funcValue) / funcRealValue).toDouble()); + // errorValues.push_back(relErrorValue); + // ulp error + // auto unitUlp = computeUlpUnit(funcRealValue.toDouble()); + // auto ulpErrorValue = fabs((funcRealValue - result.funcValue).toDouble() / unitUlp); + // errorValues.push_back(ulpErrorValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpfuncRealValues = new mpfr::mpreal[length]; + auto tmpErrorValues = new double[length]; + for(int i = 0; i < length; i++) + { + mpfr::mpreal tmpLhsValue = (lhsValue.funcValue)[i]; + mpfr::mpreal tmpRhsValue = (rhsValue.funcValue)[i]; + auto funcRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); + tmpfuncRealValues[i] = funcRealValue; + + tmpErrorValues[i] = computeError(funcRealValue, (result.funcValue)[i]); + + // absolute error + // tmpErrorValues[i] = fabs((funcRealValue - (result.funcValue)[i]).toDouble()); + } + funcRealValues.push_back(tmpfuncRealValues); + errorValues.push_back(tmpErrorValues); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + // math real value + if constexpr (TisDouble) + { + result.realValue = tmpRealCall(lhsValue.realValue, rhsValue.realValue); + std::cout << "op = " << binPtr->getOp() << " mathRealValue = " << result.realValue.toString() << std::endl; + mathRealValues.push_back(result.realValue); + result.ulpValue = computeUlpUnit(result.realValue); + } + else if constexpr (TisDoublePointer) + { + auto tmpmathRealValues = new mpfr::mpreal[length]; + auto tmpUlpValues = new double[length]; + for(int i = 0; i < length; i++) + { + mpfr::mpreal tmpLhsValue = (lhsValue.realValue)[i]; + mpfr::mpreal tmpRhsValue = (rhsValue.realValue)[i]; + auto mathRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); + tmpmathRealValues[i] = mathRealValue; + tmpUlpValues[i] = computeUlpUnit(mathRealValue); + } + mathRealValues.push_back(tmpmathRealValues); + result.realValue = tmpmathRealValues; + result.ulpValue = tmpUlpValues; + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + // condition number value + if constexpr (TisDouble) + { + auto &ulpY = result.ulpValue; + std::function funcDrv; + + auto inputLhs = lhsValue.realValue.toDouble(); + auto inputRhs = rhsValue.realValue.toDouble(); + + funcDrv = fDrvMapTwo.find(opStr + "L")->second; + auto derivativeFuncValue = funcDrv(inputLhs, inputRhs); + auto &ulpXLhs = lhsValue.ulpValue; + auto conditionNumber = ulpXLhs * derivativeFuncValue / ulpY; + conditionNumbers.push_back(conditionNumber); + + funcDrv = fDrvMapTwo.find(opStr + "R")->second; + derivativeFuncValue = funcDrv(inputLhs, inputRhs); + auto &ulpXRhs = rhsValue.ulpValue; + conditionNumber = ulpXRhs * derivativeFuncValue / ulpY; + conditionNumbers.push_back(conditionNumber); + } + else if constexpr (TisDoublePointer) + { + auto &ulpYs = result.ulpValue; + + std::function funcDrvL, funcDrvR; + auto tmpConditionNumbers1 = new double[length]; + auto tmpConditionNumbers2 = new double[length]; + funcDrvL = fDrvMapTwo.find(opStr + "L")->second; + funcDrvR = fDrvMapTwo.find(opStr + "R")->second; + for(int i = 0; i < length; i++) + { + auto inputLhs = lhsValue.realValue[i].toDouble(); + auto inputRhs = rhsValue.realValue[i].toDouble(); + + auto derivativeFuncValue = funcDrvL(inputLhs, inputRhs); + auto &ulpX1 = lhsValue.ulpValue[i]; + tmpConditionNumbers1[i] = ulpX1 * derivativeFuncValue / ulpYs[i]; + + derivativeFuncValue = funcDrvR(inputLhs, inputRhs); + auto &ulpX2 = rhsValue.ulpValue[i]; + tmpConditionNumbers2[i] = ulpX2 * derivativeFuncValue / ulpYs[i]; + } + conditionNumbers.push_back(tmpConditionNumbers1); + conditionNumbers.push_back(tmpConditionNumbers2); + } + else + { + fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + exit(EXIT_FAILURE); + } + + return result; + } + else + { + fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); + exit(EXIT_FAILURE); + } +} + +template +void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, string uniqueLabel, string funcName) +{ + mpfr::mpreal::set_default_prec(128); + vector> funcValues; + vector errorValues; // this error is f(x+\delta x) between F(x + \delta x) + vector conditionNumbers; + if constexpr (std::is_same::value) + { + std::vector funcRealValues; + std::vector mathRealValues; + shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); + + vector conditionNumbersOp(conditionNumbers.size() + 1, 1); + int IDfather = conditionNumbersOp.size() - 1; + int IDnow = conditionNumbers.size() - 1; + computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); + + // fmt::print("funcValues := {}\n", funcValues); + for(auto &funcValue : funcValues) + { + std::cout << "func value: " << funcValue.toString() << std::endl; + } + for(auto &funRealValue : funcRealValues) + { + std::cout << "func real value: " << funRealValue.toString() << std::endl; + } + for(auto &mathRealValue : mathRealValues) + { + std::cout << "math real value: " << mathRealValue.toString() << std::endl; + } + fmt::print("errorValues := {}\n", errorValues); + fmt::print("conditionNumbers := {}\n", conditionNumbers); + fmt::print("conditionNumbersOp := {}\n", conditionNumbersOp); + } + else if constexpr (std::is_same::value) + { + std::vector funcRealValues; + std::vector mathRealValues; + shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); + + vector conditionNumbersOp; + for(size_t i = 0; i < conditionNumbers.size() + 1; i++) + { + auto tmp = new double[length]; + conditionNumbersOp.push_back(tmp); + } + for(int i = 0; i < length; i++) + { + conditionNumbersOp.back()[i] = 1; + } + int IDfather = conditionNumbersOp.size() - 1; + int IDnow = conditionNumbers.size() - 1; + computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); + + // TODO: free funcValues, funcRealValues, mathRealValues, errorValues + // print to the screen + for(int i = 0; i < length; i++) + { + for(size_t j = 0; j < funcValues.size(); j++) + { + fprintf(stderr, "input NO.%d step NO.%ld: funcValue = %s\n", i, j, (funcValues.at(j))[i].toString().c_str()); + fprintf(stderr, "input NO.%d step NO.%ld: funcRealValue = %s\n", i, j, (funcRealValues.at(j))[i].toString().c_str()); + fprintf(stderr, "input NO.%d step NO.%ld: mathRealValue = %s\n", i, j, (mathRealValues.at(j))[i].toString().c_str()); + fprintf(stderr, "input NO.%d step NO.%ld: errorValue = %g\n", i, j, (errorValues.at(j))[i]); + if (j != funcValues.size() - 1) + fprintf(stderr, "input NO.%d step NO.%ld: conditionNumbers = %g\n", i, j, (conditionNumbers.at(j))[i]); + fprintf(stderr, "input NO.%d step NO.%ld: conditionNumbersOp = %g\n\n", i, j, (conditionNumbersOp.at(j))[i]); + } + fprintf(stderr, "================================\n\n"); + } // print to the file double **inputsPtr = new double *[varsValue.size()]; int ptrIdx = 0; @@ -611,18 +1371,18 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int inputsPtr[ptrIdx] = value.second; ptrIdx++; } - for(size_t i = 0; i < funcValues.size(); i++) + for(size_t i = 0; i < funcValues.size(); i++) // i is represent the step of expression { std::ofstream fout; - string filename = "./outputs/"; // i is represent the step of expression + string filename = "./outputs/"; if(ifUnique) { - filename += uniqueLabel + "/errorFunc_" + funcName + "_" + std::to_string(i) + ".txt"; // i is represent the step of expression + filename += uniqueLabel + "/errorFunc_" + funcName + "_" + std::to_string(i) + ".txt"; } else { - filename += "errorFunc_" + std::to_string(i) + ".txt"; // i is represent the step of expression + filename += "errorFunc_" + std::to_string(i) + ".txt"; } fout.open(filename, ios::out); if (!fout.is_open()) @@ -637,6 +1397,8 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int fout << inputsPtr[ptrIdx][j] << " "; } fout << (errorValues.at(i))[j] << "\n"; + // if (i != funcValues.size() - 1) + // std::cout << (conditionNumbers.at(i))[j] << "\n"; } } // std::ofstream fout; -- Gitee From c5be21fb0b86e5c25008348b3f13c185b2019cd0 Mon Sep 17 00:00:00 2001 From: Xia yuanyuan Date: Tue, 23 May 2023 09:22:43 +0800 Subject: [PATCH 12/54] support the calculation of epsilon_e in shadowValue method and improve shadowValue code --- include/geneCode.hpp | 2 + src/shadowValue.cpp | 164 +++++++++++++++++++++++++++++++------------ 2 files changed, 121 insertions(+), 45 deletions(-) diff --git a/include/geneCode.hpp b/include/geneCode.hpp index ddb81fb..d75afd9 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -41,6 +41,8 @@ string geneFinalCode(string exprStr, string uniqueLabel, vector exprIn void getDepth(ast_ptr &expr, int &depth); +vector setOrder(ast_ptr &expr); + int showOrder(ast_ptr &expr); int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map values, size_t inputNum); diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 186ce6c..34e9513 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -676,7 +676,40 @@ void computeConditionNumber(const ast_ptr &expr, vector &conditionNumbers, ve } template -valueThree shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector> &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, vector &conditionNumbers, int length = 1) +void computeEpsilonE(vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const int length = 1) +{ + constexpr bool TisDouble = (std::is_same::value); + constexpr bool TisDoublePointer = (std::is_same::value); + if constexpr (TisDouble) + { + for(size_t i = 0; i < errorValues.size(); i++) + { + epsilonE.at(i) = errorValues.at(i) * conditionNumbersOp.at(condNumOrder.at(i)); + } + } + else if constexpr (TisDoublePointer) + { + vector epsilonEAverage(errorValues.size(), 0.0); + for(size_t i = 0; i < errorValues.size(); i++) + { + for(int j = 0; j < length; j++) + { + epsilonE.at(i)[j] = errorValues.at(i)[j] * conditionNumbersOp.at(condNumOrder.at(i))[j]; + epsilonEAverage.at(i) += epsilonE.at(i)[j]; + } + epsilonEAverage.at(i) /= length; + } + fmt::print("the avarage of epsilonE is: {}\n", epsilonEAverage); + } + else + { + fprintf(stderr, "ERROR: %s: the type of T %s is not supported\n", __func__, typeid(T).name()); + exit(EXIT_FAILURE); + } +} + +template +valueThree shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector> &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, vector &conditionNumbers, vector &condNumOrder, int length = 1) { auto type = expr->type(); constexpr bool TisDouble = (std::is_same::value); @@ -784,7 +817,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & for(auto& arg : args) { - auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); + auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, condNumOrder, length); paramResults.push_back(tmp.funcValue); if constexpr (TisDouble) { @@ -793,6 +826,8 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } parammathRealResults.push_back(tmp.realValue); paramUlpResults.push_back(tmp.ulpValue); + // condition number vector's op order + condNumOrder.push_back(arg->getOrder()); } // func @@ -824,7 +859,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & { result.funcValue = tmpCall(paramResultsDouble); } - std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; + // std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; funcValues.push_back(result.funcValue); } else if constexpr (TisDoublePointer) @@ -872,7 +907,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & if constexpr (TisDouble) { mpfr::mpreal funcRealValue = tmpRealCall(paramFuncRealResults); - std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; + // std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; funcRealValues.push_back(funcRealValue); auto errorValue = computeError(funcRealValue, result.funcValue); @@ -907,7 +942,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & if constexpr (TisDouble) { result.realValue = tmpRealCall(parammathRealResults); - std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; + // std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; result.ulpValue = computeUlpUnit(result.realValue); mathRealValues.push_back(result.realValue); } @@ -1047,8 +1082,8 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & BinaryExprAST *binPtr = dynamic_cast(expr.get()); ast_ptr &lhs = binPtr->getLHS(); ast_ptr &rhs = binPtr->getRHS(); - auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); - auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); + auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, condNumOrder, length); + auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, condNumOrder, length); // func auto tmpCall = binPtr->getCallback(); @@ -1062,6 +1097,10 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & auto opTypeRhsStr = opTypeMap.find(opTypeRHS)->second; auto mapType = opTypeLhsStr + "_" + opTypeRhsStr; + // condition number vector's op order + condNumOrder.push_back(lhs->getOrder()); + condNumOrder.push_back(rhs->getOrder()); + // func value if constexpr (TisDouble) { @@ -1088,7 +1127,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & { result.funcValue = tmpCall(x1[0], x2[0]); } - std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; + // std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; funcValues.push_back(result.funcValue); } @@ -1160,7 +1199,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & if constexpr (TisDouble) { mpfr::mpreal funcRealValue = tmpRealCall(lhsValue.funcValue, rhsValue.funcValue); - std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; + // std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; funcRealValues.push_back(funcRealValue); auto errorValue = computeError(funcRealValue, result.funcValue); @@ -1206,7 +1245,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & if constexpr (TisDouble) { result.realValue = tmpRealCall(lhsValue.realValue, rhsValue.realValue); - std::cout << "op = " << binPtr->getOp() << " mathRealValue = " << result.realValue.toString() << std::endl; + // std::cout << "op = " << binPtr->getOp() << " mathRealValue = " << result.realValue.toString() << std::endl; mathRealValues.push_back(result.realValue); result.ulpValue = computeUlpUnit(result.realValue); } @@ -1294,23 +1333,49 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } template -void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, string uniqueLabel, string funcName) +void shadowValueInit(vector &conditionNumbersOp, vector &epsilonE, const size_t condNumOpSize, const int length) { - mpfr::mpreal::set_default_prec(128); - vector> funcValues; - vector errorValues; // this error is f(x+\delta x) between F(x + \delta x) - vector conditionNumbers; - if constexpr (std::is_same::value) + constexpr bool TisDouble = (std::is_same::value); + constexpr bool TisDoublePointer = (std::is_same::value); + if constexpr (TisDouble) { - std::vector funcRealValues; - std::vector mathRealValues; - shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); - - vector conditionNumbersOp(conditionNumbers.size() + 1, 1); - int IDfather = conditionNumbersOp.size() - 1; - int IDnow = conditionNumbers.size() - 1; - computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); + for(size_t i = 0; i < condNumOpSize; i++) + { + conditionNumbersOp.push_back(1); + epsilonE.push_back(0); + } + } + else if constexpr (TisDoublePointer) + { + for(size_t i = 0; i < condNumOpSize; i++) + { + auto tmp = new double[length]; + conditionNumbersOp.push_back(tmp); + } + for(int i = 0; i < length; i++) + { + conditionNumbersOp.back()[i] = 1; + } + for(size_t i = 0; i < condNumOpSize; i++) + { + auto tmp = new double[length]; + epsilonE.push_back(tmp); + } + } + else + { + fprintf(stderr, "ERROR: %s: the type of T %s is not supported\n", __func__, typeid(T).name()); + exit(EXIT_FAILURE); + } +} +template +void shadowValuePrint(const vector> &funcValues, const vector> &funcRealValues, const vector> &mathRealValues, const vector &errorValues, const vector &conditionNumbers, const vector &conditionNumbersOp, [[maybe_unused]] const vector &epsilonE, const std::map &varsValue, const int length, const bool ifUnique, const string uniqueLabel, const string funcName) +{ + constexpr bool TisDouble = (std::is_same::value); + constexpr bool TisDoublePointer = (std::is_same::value); + if constexpr (TisDouble) + { // fmt::print("funcValues := {}\n", funcValues); for(auto &funcValue : funcValues) { @@ -1328,26 +1393,8 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int fmt::print("conditionNumbers := {}\n", conditionNumbers); fmt::print("conditionNumbersOp := {}\n", conditionNumbersOp); } - else if constexpr (std::is_same::value) + else if constexpr (TisDoublePointer) { - std::vector funcRealValues; - std::vector mathRealValues; - shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, length); - - vector conditionNumbersOp; - for(size_t i = 0; i < conditionNumbers.size() + 1; i++) - { - auto tmp = new double[length]; - conditionNumbersOp.push_back(tmp); - } - for(int i = 0; i < length; i++) - { - conditionNumbersOp.back()[i] = 1; - } - int IDfather = conditionNumbersOp.size() - 1; - int IDnow = conditionNumbers.size() - 1; - computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); - // TODO: free funcValues, funcRealValues, mathRealValues, errorValues // print to the screen for(int i = 0; i < length; i++) @@ -1397,8 +1444,6 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int fout << inputsPtr[ptrIdx][j] << " "; } fout << (errorValues.at(i))[j] << "\n"; - // if (i != funcValues.size() - 1) - // std::cout << (conditionNumbers.at(i))[j] << "\n"; } } // std::ofstream fout; @@ -1422,6 +1467,35 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int // fout << "input NO." << i << " step NO." << j << ": errorValue = " << (errorValues.at(j))[i] << "\n"; // fout << "================================\n\n"; } + else + { + fprintf(stderr, "ERROR: %s: the type of T %s is not supported\n", __func__, typeid(T).name()); + exit(EXIT_FAILURE); + } +} + +template +void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, string uniqueLabel, string funcName) +{ + mpfr::mpreal::set_default_prec(128); + vector> funcValues; + vector errorValues; // this error is f(x+\delta x) between F(x + \delta x) + vector conditionNumbers; + std::vector> funcRealValues; + std::vector> mathRealValues; + vector condNumOrder; + shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, condNumOrder, length); + condNumOrder.push_back(conditionNumbers.size()); // 令condNumber最后一个元素指向conditionNumber的最后一个元素,同时保证其长度同errorValues、conditionNumberOp一致 + // fmt::print("condNumOrder: {}\n", condNumOrder); + vector conditionNumbersOp; + vector epsilonE; + shadowValueInit(conditionNumbersOp, epsilonE, conditionNumbers.size() + 1, length); + int IDfather = conditionNumbersOp.size() - 1; + int IDnow = conditionNumbers.size() - 1; + computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); + computeEpsilonE(epsilonE, errorValues, conditionNumbersOp, condNumOrder, length); + + // shadowValuePrint(funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, conditionNumbersOp, epsilonE, varsValue, length, ifUnique, uniqueLabel, funcName); } template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, std::string uniqueLabel, std::string funcName); -- Gitee From 1350e44c054eee12a9790544d5c0bea8567cb6cb Mon Sep 17 00:00:00 2001 From: hjwLab Date: Tue, 23 May 2023 20:47:55 +0800 Subject: [PATCH 13/54] Support more functions and fix a bug that size_t i-- >=0 always is TRUE --- include/funclist.hpp | 52 ++++++++++++++++++++++ src/basic.cpp | 26 +++++++++++ src/funclist.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++ src/shadowValue.cpp | 12 ++--- 4 files changed, 189 insertions(+), 5 deletions(-) diff --git a/include/funclist.hpp b/include/funclist.hpp index b8f7326..3b2fd31 100644 --- a/include/funclist.hpp +++ b/include/funclist.hpp @@ -37,6 +37,30 @@ double common_tan(vector args); double common_pow(vector args); +double common_exp(vector args); + +double common_log(vector args); + +double common_asin(vector args); + +double common_acos(vector args); + +double common_atan(vector args); + +double common_expm1(vector args); + +double common_fma(vector args); + +double common_log1p(vector args); + +double common_sqrt(vector args); + +double common_hypot(vector args); + +double common_cbrt(vector args); + +double common_atan2(vector args); + mpfr::mpreal realadd(mpfr::mpreal x, mpfr::mpreal y); mpfr::mpreal realsub(mpfr::mpreal x, mpfr::mpreal y); @@ -45,10 +69,38 @@ mpfr::mpreal realmul(mpfr::mpreal x, mpfr::mpreal y); mpfr::mpreal realdiv(mpfr::mpreal x, mpfr::mpreal y); +mpfr::mpreal real_sin(vector args); + +mpfr::mpreal real_cos(vector args); + mpfr::mpreal real_tan(vector args); mpfr::mpreal real_pow(vector args); +mpfr::mpreal real_exp(vector args); + +mpfr::mpreal real_log(vector args); + +mpfr::mpreal real_asin(vector args); + +mpfr::mpreal real_acos(vector args); + +mpfr::mpreal real_atan(vector args); + +mpfr::mpreal real_expm1(vector args); + +mpfr::mpreal real_fma(vector args); + +mpfr::mpreal real_log1p(vector args); + +mpfr::mpreal real_sqrt(vector args); + +mpfr::mpreal real_hypot(vector args); + +mpfr::mpreal real_cbrt(vector args); + +mpfr::mpreal real_atan2(vector args); + template mpfr::mpreal mineadd_d_dd(double x, double *y); diff --git a/src/basic.cpp b/src/basic.cpp index f612cc9..e3252c1 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -43,6 +43,18 @@ std::map commonCall_map = { {"cos", common_cos}, {"tan", common_tan}, {"pow", common_pow}, + {"exp", common_exp}, + {"log", common_log}, + {"asin", common_asin}, + {"acos", common_acos}, + {"atan", common_atan}, + {"expm1", common_expm1}, + {"fma", common_fma}, + {"log1p", common_log1p}, + {"sqrt", common_sqrt}, + {"hypot", common_hypot}, + {"cbrt", common_cbrt}, + {"atan2", common_atan2}, }; std::map doubleRealCall_map = { @@ -53,8 +65,22 @@ std::map doubleRealCall_map = { }; std::map commonRealCall_map = { + {"sin", real_sin}, + {"cos", real_cos}, {"tan", real_tan}, {"pow", real_pow}, + {"exp", real_exp}, + {"log", real_log}, + {"asin", real_asin}, + {"acos", real_acos}, + {"atan", real_atan}, + {"expm1", real_expm1}, + {"fma", real_fma}, + {"log1p", real_log1p}, + {"sqrt", real_sqrt}, + {"hypot", real_hypot}, + {"cbrt", real_cbrt}, + {"atan2", real_atan2}, }; std::map singleCall_dd_map = { diff --git a/src/funclist.cpp b/src/funclist.cpp index 6f922ab..a91bfaa 100644 --- a/src/funclist.cpp +++ b/src/funclist.cpp @@ -66,6 +66,54 @@ double common_pow(vector args) { return pow(args.at(0), args.at(1)); } +double common_exp(vector args) { + return exp(args.at(0)); +} + +double common_log(vector args) { + return log(args.at(0)); +} + +double common_asin(vector args) { + return asin(args.at(0)); +} + +double common_acos(vector args) { + return acos(args.at(0)); +} + +double common_atan(vector args) { + return atan(args.at(0)); +} + +double common_expm1(vector args) { + return expm1(args.at(0)); +} + +double common_fma(vector args) { + return fma(args.at(0), args.at(1), args.at(2)); +} + +double common_log1p(vector args) { + return log1p(args.at(0)); +} + +double common_sqrt(vector args) { + return sqrt(args.at(0)); +} + +double common_hypot(vector args) { + return hypot(args.at(0), args.at(1)); +} + +double common_cbrt(vector args) { + return cbrt(args.at(0)); +} + +double common_atan2(vector args) { + return atan2(args.at(0), args.at(1)); +} + mpfr::mpreal realadd(mpfr::mpreal x, mpfr::mpreal y) { return x + y; @@ -86,6 +134,14 @@ mpfr::mpreal realdiv(mpfr::mpreal x, mpfr::mpreal y) return x / y; } +mpfr::mpreal real_sin(vector args) { + return sin(args.at(0)); +} + +mpfr::mpreal real_cos(vector args) { + return cos(args.at(0)); +} + mpfr::mpreal real_tan(vector args) { return tan(args.at(0)); } @@ -94,6 +150,54 @@ mpfr::mpreal real_pow(vector args) { return pow(args.at(0), args.at(1)); } +mpfr::mpreal real_exp(vector args) { + return exp(args.at(0)); +} + +mpfr::mpreal real_log(vector args) { + return log(args.at(0)); +} + +mpfr::mpreal real_asin(vector args) { + return asin(args.at(0)); +} + +mpfr::mpreal real_acos(vector args) { + return acos(args.at(0)); +} + +mpfr::mpreal real_atan(vector args) { + return atan(args.at(0)); +} + +mpfr::mpreal real_expm1(vector args) { + return expm1(args.at(0)); +} + +mpfr::mpreal real_fma(vector args) { + return fma(args.at(0), args.at(1), args.at(2)); +} + +mpfr::mpreal real_log1p(vector args) { + return log1p(args.at(0)); +} + +mpfr::mpreal real_sqrt(vector args) { + return sqrt(args.at(0)); +} + +mpfr::mpreal real_hypot(vector args) { + return hypot(args.at(0), args.at(1)); +} + +mpfr::mpreal real_cbrt(vector args) { + return cbrt(args.at(0)); +} + +mpfr::mpreal real_atan2(vector args) { + return atan2(args.at(0), args.at(1)); +} + template mpfr::mpreal mineadd_d_dd(double x1, double *x2Ptr) { diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 34e9513..f951a22 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -19,6 +19,8 @@ using std::ios; namespace Shadow { std::map> fDrvMapOne = { + {"sqrt", [](double x) { return 0.5 / sqrt(x); }}, + {"cbrt", [](double x) { return 1 / (3.0 * cbrt(x*x)); }}, {"exp", [](double x) { return exp(x); }}, {"exp2", [](double x) { return exp2(x) * log(2); }}, {"exp10", [](double x) { return exp10(x) * log(10); }}, @@ -28,9 +30,9 @@ std::map> fDrvMapOne = { {"sin", [](double x) { return cos(x); }}, {"cos", [](double x) { return -sin(x); }}, {"tan", [](double x) { return 1 / (cos(x) * cos(x)); }}, - {"arcsin", [](double x) { return 1 / sqrt(1 - x * x); }}, - {"arccos", [](double x) { return -1 / sqrt(1 - x * x); }}, - {"arctan", [](double x) { return 1 / (1 + x * x); }}, + {"asin", [](double x) { return 1 / sqrt(1 - x * x); }}, + {"acos", [](double x) { return -1 / sqrt(1 - x * x); }}, + {"atan", [](double x) { return 1 / (1 + x * x); }}, }; std::map> fDrvMapTwo = { @@ -639,13 +641,13 @@ void computeConditionNumber(const ast_ptr &expr, vector &conditionNumbers, ve auto &args = callPtr->getArgs(); auto IDparam = new int[args.size()]; - for (size_t i = args.size() - 1; i >= 0; i--) + for (int i = args.size() - 1; i >= 0; i--) { computeConditionNumberKernel(conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); IDparam[i] = IDnow; IDnow--; } - for (size_t i = args.size() - 1; i >= 0; i--) + for (int i = args.size() - 1; i >= 0; i--) { const auto &arg = args.at(i); computeConditionNumber(arg, conditionNumbers, conditionNumbersOp, IDparam[i], IDnow, length); -- Gitee From 96a67f852cf63826a10304861ca29d3f42fbde70 Mon Sep 17 00:00:00 2001 From: hjw Date: Mon, 29 May 2023 09:44:38 +0800 Subject: [PATCH 14/54] Enhance the print ability --- detectErrorOneFPEDParallel.sh | 4 +-- include/geneCode.hpp | 2 +- src/geneCode.cpp | 25 ++++++++++--------- src/main.cpp | 42 ++++++++++++++++++++------------ src/shadowValue.cpp | 41 ++++++++++++++++++++++++++++--- src/tools.cpp | 2 +- srcTest/test1paramFPEDParallel.c | 6 ++--- 7 files changed, 85 insertions(+), 37 deletions(-) diff --git a/detectErrorOneFPEDParallel.sh b/detectErrorOneFPEDParallel.sh index 0a8449e..e2564b9 100755 --- a/detectErrorOneFPEDParallel.sh +++ b/detectErrorOneFPEDParallel.sh @@ -67,5 +67,5 @@ if [ ${errfile} -eq 1 ]; then cd - > /dev/null fi -echo "end detecting error ${uniqueLabel}" -echo +# echo "end detecting error ${uniqueLabel}" +# echo diff --git a/include/geneCode.hpp b/include/geneCode.hpp index d75afd9..57a02a8 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -45,6 +45,6 @@ vector setOrder(ast_ptr &expr); int showOrder(ast_ptr &expr); -int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map values, size_t inputNum); +int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map values, size_t inputNum, vector &outputStr); #endif \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 071babd..8625da2 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -879,16 +879,17 @@ vector setOrder(ast_ptr &expr) void showOrdersKernel(ast_ptr &expr, int &orderNow) { auto type = expr->type(); + // string prompt = ""; if(type == "Number") { - string tmp = "NO." + std::to_string(orderNow) + ": "; - printExpr(expr, tmp); + // string tmp = prompt + std::to_string(orderNow) + ": "; + printExpr(expr); orderNow++; } else if(type == "Variable") { - string tmp = "NO." + std::to_string(orderNow) + ": "; - printExpr(expr, tmp); + // string tmp = prompt + std::to_string(orderNow) + ": "; + printExpr(expr); orderNow++; } else if(type == "Call") @@ -900,8 +901,8 @@ void showOrdersKernel(ast_ptr &expr, int &orderNow) { showOrdersKernel(arg, orderNow); } - string tmp = "NO." + std::to_string(orderNow) + ": "; - printExpr(expr, tmp); + // string tmp = prompt + std::to_string(orderNow) + ": "; + printExpr(expr); orderNow++; } else if(type == "Binary") @@ -911,8 +912,8 @@ void showOrdersKernel(ast_ptr &expr, int &orderNow) ast_ptr &rhs = binPtr->getRHS(); showOrdersKernel(lhs, orderNow); showOrdersKernel(rhs, orderNow); - string tmp = "NO." + std::to_string(orderNow) + ": "; - printExpr(expr, tmp); + // string tmp = prompt + std::to_string(orderNow) + ": "; + printExpr(expr); orderNow++; } else @@ -1205,7 +1206,7 @@ void codegen(ast_ptr &expr, vector &vars, const string funcName, ofstrea // Note: Each operator node has two states, double or double-double. if there are n node in that expression, there are 2^n states. // Generate double-double implementations in all states and return the number of generated codes -int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map varsValue, size_t inputNum) +int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map varsValue, size_t inputNum, vector &outputStr) { // AST init auto opOrder = setOrder(expr); @@ -1258,11 +1259,13 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(num); string fileName = directory + funcName + ".c"; cout << "fileName: " << fileName << "\topTypes: "; + std::stringstream ss; for(map::iterator it = opTypes.begin(); it != opTypes.end(); it++) { - cout << it->first << " " << it->second << ", "; + // cout << it->first << " " << it->second << ", "; + ss << it->first << " " << it->second << " "; } - cout << "\n"; + outputStr.push_back(ss.str()); ofstream file_clean(fileName, ios_base::out); ofstream ofs(fileName, ios::app); diff --git a/src/main.cpp b/src/main.cpp index bba17b7..8621ee6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -283,6 +283,8 @@ int main() printExpr(originExpr, "the origin expr: "); showOrder(originExpr); + // set calculation order for originExpr + setOrder(originExpr); //// a simple try for shadow value // vector values(dimension, 1.4); // auto varsValue = setVarsValue(vars, values); @@ -291,7 +293,7 @@ int main() //// generate input data for shadow value vector values1; - size_t inputNum = 10; + size_t inputNum = 500000; for(int i = 0; i < dimension; i++) { auto &startOriginInterval = intervals.at(i * 2); @@ -308,11 +310,12 @@ int main() } auto varsValue1 = setVarsValue(vars, values1); //// call the shadowValue function to generate the shadow values of the expression. The shadow values are stored into files partly. - // Shadow::shadowValue(originExpr, varsValue1, inputNum); + Shadow::shadowValue(originExpr, varsValue1, inputNum); //// TODO: free values1 //// support DD - auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum); + vector outputStr; + auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum, outputStr); //// test DD's error vector startNowIdxs(dimension, 0); vector startOriginIntervals; @@ -326,19 +329,26 @@ int main() double step = width / (double)scales.at(i); steps.push_back(step); } - // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); - // vector infos; - // for(int i = 0; i < maxNum; i++) { - // string tmp = "dd_" + std::to_string(i); - // auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); - // infos.push_back(infoTmp); - // } - // cout << "No\taverage Err\tmax Err\n"; - // for(size_t i = 0; i < infos.size(); i++) - // { - // auto &info = infos.at(i); - // cout << i << "\t" << info.aveError << "\t" << info.maxError << "\n"; - // } + // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + vector infos; + for(int i = 0; i < maxNum; i++) { + cout << "-test error-" << i << "\n"; + string tmp = "dd_" + std::to_string(i); + auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + infos.push_back(infoTmp); + } + cout << std::left << setw(4) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; + for(int i = 0; i < log2(maxNum); i++) { + cout << "step Type "; + } + cout << "\n"; + // cout << std::left << setw(4) << "No" << std::left << setw(15) << "average Err" << std::left << setw(15) << "max Err" << "op Type\n"; + for(size_t i = 0; i < infos.size(); i++) + { + auto &info = infos.at(i); + auto &opTypeStr = outputStr.at(i); + cout << std::left << setw(4) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; + } // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); fprintf(stderr, GREEN "ready> " RESET); diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index f951a22..21b023c 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -677,6 +677,23 @@ void computeConditionNumber(const ast_ptr &expr, vector &conditionNumbers, ve } } +// The function takes in vecotor v as input, and returns vecotor res, where res[i] represents the rank of the v[i] by descending order." +vector getRanks(const vector &v) +{ + vector sorted = v; + std::sort(sorted.begin(), sorted.end(), std::greater()); + auto last = std::unique(sorted.begin(), sorted.end()); // Remove duplicates + sorted.erase(last, sorted.end()); // Delete excess elements + vector res(v.size()); + for (size_t i = 0; i < v.size(); i++) + { + auto it = std::find(sorted.begin(), sorted.end(), v[i]); // Find the first occurrence of v[i] in sorted + res[i] = std::distance(sorted.begin(), it) + 1; // Record the position, which is the ranking of v[i] in the sorted order + } + + return res; +} + template void computeEpsilonE(vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const int length = 1) { @@ -692,16 +709,30 @@ void computeEpsilonE(vector &epsilonE, const vector &errorValues, const ve else if constexpr (TisDoublePointer) { vector epsilonEAverage(errorValues.size(), 0.0); + vector errorValuesAverage(errorValues.size(), 0.0); + vector conditionNumbersOpAverage(errorValues.size(), 0.0); for(size_t i = 0; i < errorValues.size(); i++) { for(int j = 0; j < length; j++) { - epsilonE.at(i)[j] = errorValues.at(i)[j] * conditionNumbersOp.at(condNumOrder.at(i))[j]; - epsilonEAverage.at(i) += epsilonE.at(i)[j]; + epsilonE.at(i)[j] = fabs(errorValues.at(i)[j] * conditionNumbersOp.at(condNumOrder.at(i))[j]); + epsilonEAverage.at(i) += epsilonE.at(i)[j]; // TODO: 实际上,这个fabs函数应该在求取条件数的时候就加上。但从结果讲,在最后加的效果是等价的。errorValues根据我的印象,应该是早都加过fabs了。 + errorValuesAverage.at(i) += errorValues.at(i)[j]; + conditionNumbersOpAverage.at(i) += conditionNumbersOp.at(i)[j]; } epsilonEAverage.at(i) /= length; + errorValuesAverage.at(i) /= length; + conditionNumbersOpAverage.at(i) /= length; + } + auto ranks = getRanks(epsilonEAverage); + // fmt::print("the avarage of epsilonE is: {}\n", epsilonEAverage); + std::cout << "epsilonE rank\n"; + for(size_t i = 0; i < epsilonEAverage.size(); i++) + { + // fmt::print("{} {}\n", epsilonEAverage.at(i), ranks.at(i)); + // fmt::print("rank {}: errorValuesAverage = {} conditionNumbersOpAverage = {} epsilonEAverage = {}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); + fmt::print("{}: {:<15e} {:<15e} {:<15e}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); } - fmt::print("the avarage of epsilonE is: {}\n", epsilonEAverage); } else { @@ -1113,16 +1144,20 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & if(mapType == "d_dd") { auto tmpDoubleCall = doubleCall_d_dd_map.find(opStr + "_" + opTypeStr)->second; + x2[1] = (rhsValue.funcValue - x2[0]).toDouble(); result.funcValue = tmpDoubleCall(x1[0], x2); } else if(mapType == "dd_d") { auto tmpDoubleCall = doubleCall_dd_d_map.find(opStr + "_" + opTypeStr)->second; + x1[1] = (lhsValue.funcValue - x1[0]).toDouble(); result.funcValue = tmpDoubleCall(x1, x2[0]); } else if(mapType == "dd_dd") { auto tmpDoubleCall = doubleCall_dd_dd_map.find(opStr + "_" + opTypeStr)->second; + x1[1] = (lhsValue.funcValue - x1[0]).toDouble(); + x2[1] = (rhsValue.funcValue - x2[0]).toDouble(); result.funcValue = tmpDoubleCall(x1, x2); } else diff --git a/src/tools.cpp b/src/tools.cpp index 685d446..4a1ea09 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -421,7 +421,7 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte string commandStr = ss.str(); // cout << "fileNameKernel: " << fileNameKernel << "\n"; - cout << "command: " << commandStr << "\n"; + // cout << "command: " << commandStr << "\n"; // cout << "testName: " << testName << "\n"; char command[512] = {0}; strcat(command, commandStr.c_str()); diff --git a/srcTest/test1paramFPEDParallel.c b/srcTest/test1paramFPEDParallel.c index dde1b65..0574211 100644 --- a/srcTest/test1paramFPEDParallel.c +++ b/srcTest/test1paramFPEDParallel.c @@ -258,9 +258,9 @@ int main(int argc, char **argv) printf("Error opening file %s.\n", fileNameErr); exit(0); } - printf("average ulp\tmax ulp\n"); - printf("%.16le\t%.16le\n", aveError, maxError); - printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); + // printf("average ulp\tmax ulp\n"); + // printf("%.16le\t%.16le\n", aveError, maxError); + // printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); fprintf(fErr, "average ulp\tmax ulp\n"); fprintf(fErr, "%.16le\t%.16le\n", aveError, maxError); fprintf(fErr, "\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); -- Gitee From edb873f17fe8d745f27e0ad25b7d55d84db1fc3f Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 30 May 2023 15:04:57 +0800 Subject: [PATCH 15/54] Add functions like "mpreal add_d_d(double,double)" --- include/basic.hpp | 2 ++ include/funclist.hpp | 12 ++++++++++ src/basic.cpp | 11 +++++++++ src/funclist.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/include/basic.hpp b/include/basic.hpp index ac21f92..812f3a0 100644 --- a/include/basic.hpp +++ b/include/basic.hpp @@ -61,10 +61,12 @@ extern std::map doubleRealCall_map; extern std::map commonRealCall_map; typedef std::function singleCall_dd; +typedef std::function doubleCall_d_d; typedef std::function doubleCall_d_dd; typedef std::function doubleCall_dd_d; typedef std::function doubleCall_dd_dd; extern std::map singleCall_dd_map; +extern std::map doubleCall_d_d_map; extern std::map doubleCall_d_dd_map; extern std::map doubleCall_dd_d_map; extern std::map doubleCall_dd_dd_map; diff --git a/include/funclist.hpp b/include/funclist.hpp index 3b2fd31..602ae0c 100644 --- a/include/funclist.hpp +++ b/include/funclist.hpp @@ -101,6 +101,9 @@ mpfr::mpreal real_cbrt(vector args); mpfr::mpreal real_atan2(vector args); +template +mpfr::mpreal mineadd_d_d(double x, double y); + template mpfr::mpreal mineadd_d_dd(double x, double *y); @@ -110,6 +113,9 @@ mpfr::mpreal mineadd_dd_d(double *x, double y); template mpfr::mpreal mineadd_dd_dd(double *x, double *y); +template +mpfr::mpreal minesub_d_d(double x, double y); + template mpfr::mpreal minesub_d_dd(double x, double *y); @@ -119,6 +125,9 @@ mpfr::mpreal minesub_dd_d(double *x, double y); template mpfr::mpreal minesub_dd_dd(double *x, double *y); +template +mpfr::mpreal minemul_d_d(double x, double y); + template mpfr::mpreal minemul_d_dd(double x, double *y); @@ -128,6 +137,9 @@ mpfr::mpreal minemul_dd_d(double *x, double y); template mpfr::mpreal minemul_dd_dd(double *x, double *y); +template +mpfr::mpreal minediv_d_d(double x, double y); + template mpfr::mpreal minediv_d_dd(double x, double *y); diff --git a/src/basic.cpp b/src/basic.cpp index e3252c1..d08ca11 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -90,6 +90,17 @@ std::map singleCall_dd_map = { {"tan_dd", minetan_dd}, }; +std::map doubleCall_d_d_map = { + {"add_d", mineadd_d_d}, + {"add_dd", mineadd_d_d}, + {"sub_d", minesub_d_d}, + {"sub_dd", minesub_d_d}, + {"mul_d", minemul_d_d}, + {"mul_dd", minemul_d_d}, + {"div_d", minediv_d_d}, + {"div_dd", minediv_d_d}, +}; + std::map doubleCall_d_dd_map = { {"add_d", mineadd_d_dd}, {"add_dd", mineadd_d_dd}, diff --git a/src/funclist.cpp b/src/funclist.cpp index a91bfaa..ec1cd83 100644 --- a/src/funclist.cpp +++ b/src/funclist.cpp @@ -1,6 +1,7 @@ #include #include "basic.hpp" #include "funclist.hpp" +#include "includeDD/inline.h" double mineadd(double x, double y) { return x + y; @@ -198,6 +199,18 @@ mpfr::mpreal real_atan2(vector args) { return atan2(args.at(0), args.at(1)); } +template +mpfr::mpreal mineadd_d_d(double x1, double x2) +{ + double y[2]; + y[0] = two_add_mine(x1, x2, &(y[1])); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + template mpfr::mpreal mineadd_d_dd(double x1, double *x2Ptr) { @@ -234,6 +247,18 @@ mpfr::mpreal mineadd_dd_dd(double *x1Ptr, double *x2Ptr) return result; } +template +mpfr::mpreal minesub_d_d(double x1, double x2) +{ + double y[2]; + y[0] = two_sub_mine(x1, x2, &(y[1])); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + template mpfr::mpreal minesub_d_dd(double x1, double *x2Ptr) { @@ -270,6 +295,18 @@ mpfr::mpreal minesub_dd_dd(double *x1Ptr, double *x2Ptr) return result; } +template +mpfr::mpreal minemul_d_d(double x1, double x2) +{ + double y[2]; + y[0] = two_mul_mine(x1, x2, &(y[1])); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + template mpfr::mpreal minemul_d_dd(double x1, double *x2Ptr) { @@ -306,6 +343,18 @@ mpfr::mpreal minemul_dd_dd(double *x1Ptr, double *x2Ptr) return result; } +template +mpfr::mpreal minediv_d_d(double x1, double x2) +{ + double y[2]; + y[0] = div_mine(x1, x2, &(y[1])); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + template mpfr::mpreal minediv_d_dd(double x1, double *x2Ptr) { @@ -367,6 +416,8 @@ mpfr::mpreal minetan_dd(double *x) } // add +template mpfr::mpreal mineadd_d_d(double x, double y); +template mpfr::mpreal mineadd_d_d(double x, double y); template mpfr::mpreal mineadd_d_dd(double x, double *y); template mpfr::mpreal mineadd_d_dd(double x, double *y); template mpfr::mpreal mineadd_dd_d(double *x, double y); @@ -375,6 +426,8 @@ template mpfr::mpreal mineadd_dd_dd(double *x, double *y); template mpfr::mpreal mineadd_dd_dd(double *x, double *y); // sub +template mpfr::mpreal minesub_d_d(double x, double y); +template mpfr::mpreal minesub_d_d(double x, double y); template mpfr::mpreal minesub_d_dd(double x, double *y); template mpfr::mpreal minesub_d_dd(double x, double *y); template mpfr::mpreal minesub_dd_d(double *x, double y); @@ -383,6 +436,8 @@ template mpfr::mpreal minesub_dd_dd(double *x, double *y); template mpfr::mpreal minesub_dd_dd(double *x, double *y); // mul +template mpfr::mpreal minemul_d_d(double x, double y); +template mpfr::mpreal minemul_d_d(double x, double y); template mpfr::mpreal minemul_d_dd(double x, double *y); template mpfr::mpreal minemul_d_dd(double x, double *y); template mpfr::mpreal minemul_dd_d(double *x, double y); @@ -391,6 +446,8 @@ template mpfr::mpreal minemul_dd_dd(double *x, double *y); template mpfr::mpreal minemul_dd_dd(double *x, double *y); // div +template mpfr::mpreal minediv_d_d(double x, double y); +template mpfr::mpreal minediv_d_d(double x, double y); template mpfr::mpreal minediv_d_dd(double x, double *y); template mpfr::mpreal minediv_d_dd(double x, double *y); template mpfr::mpreal minediv_dd_d(double *x, double y); -- Gitee From ee89642ceb41c686bf4c47005add26a4160f678a Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 30 May 2023 15:19:55 +0800 Subject: [PATCH 16/54] Improve computeEpsilonE & shadowValueKernel & shadowValue Details: Support return type to vector about the average of epsilonE; Support the binary input type "d_d" for shodawValueKernel; Combine the code blocks of computing funcRealValue and mathRealValue; Modify the denominator in the error detection method from the ulp unit value of funcRealValue to the ulp unit value of mathRealValue; --- include/errorDetect.hpp | 2 + include/shadowValue.hpp | 2 +- src/errorDetect.cpp | 8 +++ src/shadowValue.cpp | 126 +++++++++++++++++++++++++--------------- 4 files changed, 89 insertions(+), 49 deletions(-) diff --git a/include/errorDetect.hpp b/include/errorDetect.hpp index 1093dc3..9d0ce56 100644 --- a/include/errorDetect.hpp +++ b/include/errorDetect.hpp @@ -21,4 +21,6 @@ double computeError(mpfr::mpreal oracle, double x); double computeError(mpfr::mpreal oracle, mpfr::mpreal x); +double computeError(mpfr::mpreal funcRealValue, mpfr::mpreal funcValue, double unitUlp); + #endif \ No newline at end of file diff --git a/include/shadowValue.hpp b/include/shadowValue.hpp index 6102048..b2a9ea2 100644 --- a/include/shadowValue.hpp +++ b/include/shadowValue.hpp @@ -7,7 +7,7 @@ namespace Shadow { void shadowValue(ast_ptr &expr, double input); template -void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length = 1, bool ifUnique = false, string uniqueLabel = "", string funcName = ""); +vector shadowValue(const ast_ptr &expr, const std::map &varsValue, int length = 1, bool ifUnique = false, string uniqueLabel = "", string funcName = ""); } #endif \ No newline at end of file diff --git a/src/errorDetect.cpp b/src/errorDetect.cpp index 1df89fb..c9fbe02 100644 --- a/src/errorDetect.cpp +++ b/src/errorDetect.cpp @@ -56,5 +56,13 @@ double computeError(mpfr::mpreal oracle, mpfr::mpreal x) auto unitUlp = computeUlpUnit(oracle.toDouble()); auto errorValue = fabs((oracle - x).toDouble() / unitUlp); + return errorValue; +} + +double computeError(mpfr::mpreal funcRealValue, mpfr::mpreal funcValue, double unitUlp) +{ + // ulp error + auto errorValue = fabs((funcRealValue - funcValue).toDouble() / unitUlp); + return errorValue; } \ No newline at end of file diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 21b023c..3ae415c 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -695,16 +695,19 @@ vector getRanks(const vector &v) } template -void computeEpsilonE(vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const int length = 1) +vector computeEpsilonE(vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const int length = 1) { constexpr bool TisDouble = (std::is_same::value); constexpr bool TisDoublePointer = (std::is_same::value); if constexpr (TisDouble) { + vector epsilonEStr; for(size_t i = 0; i < errorValues.size(); i++) { epsilonE.at(i) = errorValues.at(i) * conditionNumbersOp.at(condNumOrder.at(i)); + epsilonEStr.push_back(std::to_string(epsilonE.at(i))); } + return epsilonEStr; } else if constexpr (TisDoublePointer) { @@ -727,12 +730,16 @@ void computeEpsilonE(vector &epsilonE, const vector &errorValues, const ve auto ranks = getRanks(epsilonEAverage); // fmt::print("the avarage of epsilonE is: {}\n", epsilonEAverage); std::cout << "epsilonE rank\n"; + vector epsilonEStr; for(size_t i = 0; i < epsilonEAverage.size(); i++) { // fmt::print("{} {}\n", epsilonEAverage.at(i), ranks.at(i)); // fmt::print("rank {}: errorValuesAverage = {} conditionNumbersOpAverage = {} epsilonEAverage = {}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); - fmt::print("{}: {:<15e} {:<15e} {:<15e}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); + // fmt::print("{}: {:<15e} {:<15e} {:<15e}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); + auto epsilonEStrNow = fmt::format("{}: {:<15e} {:<15e} {:<15e}", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); + epsilonEStr.push_back(epsilonEStrNow); } + return epsilonEStr; } else { @@ -1160,14 +1167,29 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & x2[1] = (rhsValue.funcValue - x2[0]).toDouble(); result.funcValue = tmpDoubleCall(x1, x2); } + else if(mapType == "d_d") + { + auto tmpDoubleCall = doubleCall_d_d_map.find(opStr + "_" + opTypeStr)->second; + if(opTypeStr == "dd") + { + result.funcValue = tmpDoubleCall(x1[0], x2[0]); + } + else + { + result.funcValue = tmpCall(x1[0], x2[0]); + } + } else { - result.funcValue = tmpCall(x1[0], x2[0]); + fprintf(stderr, "ERROR: %s : Invalid map type: %s\n", __func__, mapType.c_str()); + exit(EXIT_FAILURE); } // std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; funcValues.push_back(result.funcValue); } + // TODO: 按照double的方法,需要考虑输入为d_d的情况。目前这样可以解决模型不唯一的问题。 + // TODO: 下一步就是怎么把代码实现对应到模型上。可能需要重新考虑把当前步骤更改为dd带来的影响。 else if constexpr (TisDoublePointer) { auto tmpfuncValues = new mpfr::mpreal[length]; @@ -1211,15 +1233,33 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & tmpfuncValues[i] = tmpDoubleCall(x1, x2); } } - else // d_d + else if(mapType == "d_d") { - for(int i = 0; i < length; i++) + if(opTypeStr == "dd") { - auto &tmpLhsValue = (lhsValue.funcValue)[i]; - auto &tmpRhsValue = (rhsValue.funcValue)[i]; - tmpfuncValues[i] = tmpCall(tmpLhsValue.toDouble(), tmpRhsValue.toDouble()); + auto tmpDoubleCall = doubleCall_d_d_map.find(opStr + "_" + opTypeStr)->second; + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + tmpfuncValues[i] = tmpDoubleCall(tmpLhsValue.toDouble(), tmpRhsValue.toDouble()); + } + } + else + { + for(int i = 0; i < length; i++) + { + auto &tmpLhsValue = (lhsValue.funcValue)[i]; + auto &tmpRhsValue = (rhsValue.funcValue)[i]; + tmpfuncValues[i] = tmpCall(tmpLhsValue.toDouble(), tmpRhsValue.toDouble()); + } } } + else + { + fprintf(stderr, "ERROR: %s : Invalid map type: %s\n", __func__, mapType.c_str()); + exit(EXIT_FAILURE); + } result.funcValue = tmpfuncValues; funcValues.push_back(tmpfuncValues); } @@ -1232,16 +1272,23 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & // real func auto tmpRealCall = binPtr->getRealCallback(); - // func real value + // func real value & math real value & ulp unit value & error value if constexpr (TisDouble) { + // func Real Value mpfr::mpreal funcRealValue = tmpRealCall(lhsValue.funcValue, rhsValue.funcValue); // std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; funcRealValues.push_back(funcRealValue); - auto errorValue = computeError(funcRealValue, result.funcValue); - errorValues.push_back(errorValue); + // math real value + result.realValue = tmpRealCall(lhsValue.realValue, rhsValue.realValue); + // std::cout << "op = " << binPtr->getOp() << " mathRealValue = " << result.realValue.toString() << std::endl; + mathRealValues.push_back(result.realValue); + // math real value's ulp unit Value + result.ulpValue = computeUlpUnit(result.realValue); + + // error value according funcReal & func & mathReal values // absolute error // double absErrorValue = fabs((funcRealValue - result.funcValue).toDouble()); // errorValues.push_back(absErrorValue); @@ -1249,56 +1296,38 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & // double relErrorValue = fabs(((funcRealValue - result.funcValue) / funcRealValue).toDouble()); // errorValues.push_back(relErrorValue); // ulp error - // auto unitUlp = computeUlpUnit(funcRealValue.toDouble()); - // auto ulpErrorValue = fabs((funcRealValue - result.funcValue).toDouble() / unitUlp); - // errorValues.push_back(ulpErrorValue); + auto errorValue = computeError(funcRealValue, result.funcValue, result.ulpValue); + errorValues.push_back(errorValue); } else if constexpr (TisDoublePointer) { auto tmpfuncRealValues = new mpfr::mpreal[length]; auto tmpErrorValues = new double[length]; + auto tmpmathRealValues = new mpfr::mpreal[length]; + auto tmpUlpValues = new double[length]; for(int i = 0; i < length; i++) { + // func real value mpfr::mpreal tmpLhsValue = (lhsValue.funcValue)[i]; mpfr::mpreal tmpRhsValue = (rhsValue.funcValue)[i]; auto funcRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); tmpfuncRealValues[i] = funcRealValue; - tmpErrorValues[i] = computeError(funcRealValue, (result.funcValue)[i]); - - // absolute error - // tmpErrorValues[i] = fabs((funcRealValue - (result.funcValue)[i]).toDouble()); - } - funcRealValues.push_back(tmpfuncRealValues); - errorValues.push_back(tmpErrorValues); - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - - // math real value - if constexpr (TisDouble) - { - result.realValue = tmpRealCall(lhsValue.realValue, rhsValue.realValue); - // std::cout << "op = " << binPtr->getOp() << " mathRealValue = " << result.realValue.toString() << std::endl; - mathRealValues.push_back(result.realValue); - result.ulpValue = computeUlpUnit(result.realValue); - } - else if constexpr (TisDoublePointer) - { - auto tmpmathRealValues = new mpfr::mpreal[length]; - auto tmpUlpValues = new double[length]; - for(int i = 0; i < length; i++) - { - mpfr::mpreal tmpLhsValue = (lhsValue.realValue)[i]; - mpfr::mpreal tmpRhsValue = (rhsValue.realValue)[i]; + // math real value + tmpLhsValue = (lhsValue.realValue)[i]; + tmpRhsValue = (rhsValue.realValue)[i]; auto mathRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); tmpmathRealValues[i] = mathRealValue; + + // math real value's ulp unit value tmpUlpValues[i] = computeUlpUnit(mathRealValue); + + // error value + tmpErrorValues[i] = computeError(funcRealValue, (result.funcValue)[i], tmpUlpValues[i]); } + funcRealValues.push_back(tmpfuncRealValues); mathRealValues.push_back(tmpmathRealValues); + errorValues.push_back(tmpErrorValues); result.realValue = tmpmathRealValues; result.ulpValue = tmpUlpValues; } @@ -1512,7 +1541,7 @@ void shadowValuePrint(const vector> &funcValues, const vector -void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, string uniqueLabel, string funcName) +vector shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, string uniqueLabel, string funcName) { mpfr::mpreal::set_default_prec(128); vector> funcValues; @@ -1530,12 +1559,13 @@ void shadowValue(const ast_ptr &expr, const std::map &varsValue, int int IDfather = conditionNumbersOp.size() - 1; int IDnow = conditionNumbers.size() - 1; computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); - computeEpsilonE(epsilonE, errorValues, conditionNumbersOp, condNumOrder, length); + auto epsilonEStr = computeEpsilonE(epsilonE, errorValues, conditionNumbersOp, condNumOrder, length); // shadowValuePrint(funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, conditionNumbersOp, epsilonE, varsValue, length, ifUnique, uniqueLabel, funcName); + return epsilonEStr; } -template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, std::string uniqueLabel, std::string funcName); -template void shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, std::string uniqueLabel, std::string funcName); +template vector shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, std::string uniqueLabel, std::string funcName); +template vector shadowValue(const ast_ptr &expr, const std::map &varsValue, int length, bool ifUnique, std::string uniqueLabel, std::string funcName); } \ No newline at end of file -- Gitee From a6ed3b7eaecfc92f33c28d2cdad23c303b0c14e6 Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 30 May 2023 15:21:53 +0800 Subject: [PATCH 17/54] Enhance the print ability --- include/color.hpp | 3 +++ src/geneCode.cpp | 39 ++++++++++++++++++++++++++++++++++----- src/main.cpp | 35 ++++++++++++++++++++--------------- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/include/color.hpp b/include/color.hpp index 74b91f8..3f202d8 100644 --- a/include/color.hpp +++ b/include/color.hpp @@ -11,6 +11,9 @@ #define CYAN "\033[36m" // Cyan #define WHITE "\033[37m" // White +#define BRIGHTRED "\033[91m" // Bright Red +#define BOLDBRIGHTRED "\033[1m\033[91m" // Bold Bright Red + #define BOLDBLACK "\033[1m\033[30m" // Bold Black #define BOLDRED "\033[1m\033[31m" // Bold Red #define BOLDGREEN "\033[1m\033[32m" // Bold Green diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 8625da2..9235567 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -2,6 +2,7 @@ #include "geneCode.hpp" #include "parserASTLY.hpp" #include "shadowValue.hpp" +#include "color.hpp" #include #include @@ -1209,8 +1210,8 @@ void codegen(ast_ptr &expr, vector &vars, const string funcName, ofstrea int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map varsValue, size_t inputNum, vector &outputStr) { // AST init - auto opOrder = setOrder(expr); - auto lenOp = opOrder.size(); + auto opSequence = setOrder(expr); + auto lenOp = opSequence.size(); // set opTypes: method NO.1 // int depth = 0; @@ -1246,7 +1247,7 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel std::map opTypes; for(size_t i = 0; i < lenOp; i++) { - auto id = opOrder[i]; + auto id = opSequence[i]; auto tmp = currentNum % lenDataTypes; opTypes[id] = dataTypes[tmp]; currentNum = currentNum / lenDataTypes; @@ -1258,7 +1259,7 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel string directory = "srcTest/" + uniqueLabel + "/"; string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(num); string fileName = directory + funcName + ".c"; - cout << "fileName: " << fileName << "\topTypes: "; + cout << "\n\nfileName: " << fileName << "\topTypes: "; std::stringstream ss; for(map::iterator it = opTypes.begin(); it != opTypes.end(); it++) { @@ -1272,7 +1273,35 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel /// call shadowValue to generate each step's values of expr. // varsValue is input values // inputNum is the number of input data - Shadow::shadowValue(expr, varsValue, inputNum, true, uniqueLabel, funcName); + auto epsilonEStr = Shadow::shadowValue(expr, varsValue, inputNum, true, uniqueLabel, funcName); + auto it = opSequence.begin(); + for(int i = 0; i < (int)epsilonEStr.size(); i++) + { + auto &epsilonEStrNow = epsilonEStr.at(i); + if(*it == i) + { + if(opTypes[*it] == "DD") + { + cout << BOLDBRIGHTRED << epsilonEStrNow << "\n" << RESET; + } + else + { + cout << RED << epsilonEStrNow << "\n" << RESET; + } + it++; + } + else + { + cout << epsilonEStrNow << "\n"; + } + } + + // unsigned long int hjw = 0x3fe6e4f765fd8adaul; + // double hhh = *((double *)(&hjw)); + // vector values(1, hhh); + // auto varsValue = setVarsValue(vars, values); + // fmt::print("varsValue = {}\n", varsValue); + // Shadow::shadowValue(expr, varsValue); // call codegen to generate code codegen(expr, vars, funcName, ofs); diff --git a/src/main.cpp b/src/main.cpp index 8621ee6..7dd0085 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -284,7 +284,8 @@ int main() showOrder(originExpr); // set calculation order for originExpr - setOrder(originExpr); + auto opSequence = setOrder(originExpr); + fmt::print("opSequence: {}\n", opSequence); //// a simple try for shadow value // vector values(dimension, 1.4); // auto varsValue = setVarsValue(vars, values); @@ -293,7 +294,7 @@ int main() //// generate input data for shadow value vector values1; - size_t inputNum = 500000; + size_t inputNum = 10000; for(int i = 0; i < dimension; i++) { auto &startOriginInterval = intervals.at(i * 2); @@ -310,7 +311,7 @@ int main() } auto varsValue1 = setVarsValue(vars, values1); //// call the shadowValue function to generate the shadow values of the expression. The shadow values are stored into files partly. - Shadow::shadowValue(originExpr, varsValue1, inputNum); + // Shadow::shadowValue(originExpr, varsValue1, inputNum); //// TODO: free values1 //// support DD @@ -329,25 +330,29 @@ int main() double step = width / (double)scales.at(i); steps.push_back(step); } - // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); - vector infos; - for(int i = 0; i < maxNum; i++) { - cout << "-test error-" << i << "\n"; - string tmp = "dd_" + std::to_string(i); - auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); - infos.push_back(infoTmp); - } - cout << std::left << setw(4) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; + testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + // vector infos; + // for(int i = 0; i < maxNum; i++) { + // cout << "-test error-" << i << "\n"; + // string tmp = "dd_" + std::to_string(i); + // auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + // infos.push_back(infoTmp); + // } + cout << std::left << setw(4) << "No"; + // cout << std::left << setw(4) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; for(int i = 0; i < log2(maxNum); i++) { cout << "step Type "; } cout << "\n"; // cout << std::left << setw(4) << "No" << std::left << setw(15) << "average Err" << std::left << setw(15) << "max Err" << "op Type\n"; - for(size_t i = 0; i < infos.size(); i++) + auto it = opSequence.begin(); + for(int i = 0; i < maxNum; i++) { - auto &info = infos.at(i); + // auto &info = infos.at(i); auto &opTypeStr = outputStr.at(i); - cout << std::left << setw(4) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; + cout << std::left << setw(4) << i << opTypeStr << "\n"; + it++; + // cout << std::left << setw(4) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; } // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); -- Gitee From 5a4453977d834c2578c09c111406c5fb091d2bd1 Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 30 May 2023 15:22:38 +0800 Subject: [PATCH 18/54] Implement error detection for the single point --- detectErrorOneSingle.sh | 26 +++++++++++++++ srcTest/test1paramSingle.c | 66 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100755 detectErrorOneSingle.sh create mode 100644 srcTest/test1paramSingle.c diff --git a/detectErrorOneSingle.sh b/detectErrorOneSingle.sh new file mode 100755 index 0000000..6a3795d --- /dev/null +++ b/detectErrorOneSingle.sh @@ -0,0 +1,26 @@ +# Usage: ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${prefix} ${middle} ${suffix} ${errfile} +# set -x + +path=`pwd` +cd ${path} +CC=gcc + +uniqueLabel=${1} # unique number +if [ $# -eq 3 ]; then + suffix=${2} # different version. Eg: herbie daisy origin temp_0_3 final + x0=${3} +else + echo "detectErrorOneSingle.sh: Invalid input parameters" + exit +fi +prefix=expr_${uniqueLabel} # expr_${uniqueLabel}. Eg: expr_20221030155958 + +testFileName=test1paramSingle +numProcs=32 + +directory="./srcTest"/${uniqueLabel} +sourceFile=${prefix}_${suffix} + +${CC} ./srcTest/${testFileName}.c ${directory}/${sourceFile}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -Llibs -lTGen -lmpfr -lm -lqd -o ${testFileName}.exe +./${testFileName}.exe ${x0} +rm ${testFileName}.exe diff --git a/srcTest/test1paramSingle.c b/srcTest/test1paramSingle.c new file mode 100644 index 0000000..51017e9 --- /dev/null +++ b/srcTest/test1paramSingle.c @@ -0,0 +1,66 @@ +#include "common.h" + +#ifndef SUFFIX +#define SUFFIX orgin +#endif +#ifndef EXPRESSION +#define EXPRESSION NMSEproblem334 +#endif + +#define EXPRESSIONMINE ADDSUFFIX(EXPRESSION, SUFFIX) +#define SUFFIX1 mpfr +#define EXPRESSIONMPFR ADDSUFFIX(EXPRESSION, SUFFIX1) + +double EXPRESSIONMPFR(double, mpfr_t); +double EXPRESSIONMINE(double); + +int computeOrcle1param(double x0, mpfr_t orcle) +{ + return EXPRESSIONMPFR(x0, orcle); +} + +int computeResult1param(double x0, mpfr_t mpfrResult) +{ + int status = 1; + + double result = EXPRESSIONMINE(x0); + mpfr_set_d(mpfrResult, result, MPFR_RNDN); + + return status; +} + +void test1param(double x0) +{ + mpfr_t mpfrOrcle, mpfrResult; + mpfr_inits2(PRECISION, mpfrOrcle, mpfrResult, (mpfr_ptr) 0); + + computeResult1param(x0, mpfrResult); + computeOrcle1param(x0, mpfrOrcle); + + double reUlp = computeUlpDiff(mpfrOrcle, mpfrResult); + DL orcle, result; + orcle.d = mpfr_get_d(mpfrOrcle, MPFR_RNDN); + result.d = mpfr_get_d(mpfrResult, MPFR_RNDN); + printf("%8lg %8lg %8lg %8lg\n", x0, result.d, orcle.d, reUlp); + + // clear + mpfr_clears(mpfrOrcle, mpfrResult, (mpfr_ptr) 0); +} + +int main(int argc, char **argv) +{ + DL x0; + + if (argc == 2) + { + x0.l = strtoul(argv[1], NULL, 16); + printf("Value = 0x%016lx\n", x0.l); + } + else + { + printf("Wrong number of arguments.\n"); + exit(EXIT_FAILURE); + } + test1param(x0.d); + return 0; +} -- Gitee From cbc0161f4c0acb87f6c91a34b83d45d964a08b3f Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 31 May 2023 16:09:34 +0800 Subject: [PATCH 19/54] Improve shadowValue method. Details: Increase the calculation of the total error of the model; Improve the Call judgment branch in shadowValueKernel; Improve other details; --- src/shadowValue.cpp | 129 ++++++++++++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 45 deletions(-) diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 3ae415c..e791f0f 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "mpreal.h" #include "shadowValue.hpp" #include "funclist.hpp" @@ -704,9 +705,11 @@ vector computeEpsilonE(vector &epsilonE, const vector &errorValues vector epsilonEStr; for(size_t i = 0; i < errorValues.size(); i++) { - epsilonE.at(i) = errorValues.at(i) * conditionNumbersOp.at(condNumOrder.at(i)); + epsilonE.at(i) = fabs(errorValues.at(i) * conditionNumbersOp.at(condNumOrder.at(i))); epsilonEStr.push_back(std::to_string(epsilonE.at(i))); } + auto sum = std::accumulate(epsilonE.begin(), epsilonE.end(), 0); + std::cout << "The sum of the elements in the vector is: " << sum << std::endl; return epsilonEStr; } else if constexpr (TisDoublePointer) @@ -739,6 +742,9 @@ vector computeEpsilonE(vector &epsilonE, const vector &errorValues auto epsilonEStrNow = fmt::format("{}: {:<15e} {:<15e} {:<15e}", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); epsilonEStr.push_back(epsilonEStrNow); } + auto sum = std::accumulate(epsilonEAverage.begin(), epsilonEAverage.end(), 0.0); + string sumEpsilon = fmt::format("The sum of the epsilon is {:g}\n", sum); + epsilonEStr.push_back(sumEpsilon); return epsilonEStr; } else @@ -895,9 +901,26 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & mpfr::mpreal tmp = tmpSingleCall(x1); result.funcValue = tmp; } + else if(mapType == "_d") + { + if(callTypeStr == "dd") + { + double x1[2]{0}; + x1[0] = paramResults.at(0).toDouble(); + auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; + mpfr::mpreal tmp = tmpSingleCall(x1); + result.funcValue = tmp; + } + else + { + double tmp = tmpCall(paramResultsDouble); + result.funcValue = tmp; + } + } else { - result.funcValue = tmpCall(paramResultsDouble); + fprintf(stderr, "ERROR: %s : Invalid map type: %s\n", __func__, mapType.c_str()); + exit(EXIT_FAILURE); } // std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; funcValues.push_back(result.funcValue); @@ -909,26 +932,45 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & { double x1[2]{0}; mpfr::mpreal tmp; + auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; for(int i = 0; i < length; i++) { x1[0] = ((paramResults.at(0))[i]).toDouble(); x1[1] = ((paramResults.at(0))[i] - x1[0]).toDouble(); - auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; tmpfuncValues[i] = tmpSingleCall(x1); } } - else + else if(mapType == "_d") { - for(int i = 0; i < length; i++) + if(callTypeStr == "dd") { - vector tmpParam; - for(auto ¶m : paramResults) + auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; + double x1[2]{0}; + for(int i = 0; i < length; i++) { - tmpParam.push_back((param[i]).toDouble()); + x1[0] = ((paramResults.at(0))[i]).toDouble(); + mpfr::mpreal funcValue = tmpSingleCall(x1); + tmpfuncValues[i] = funcValue; } - auto funcValue = tmpCall(tmpParam); - tmpfuncValues[i] = funcValue; } + else + { + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : paramResults) + { + tmpParam.push_back((param[i]).toDouble()); + } + double funcValue = tmpCall(tmpParam); + tmpfuncValues[i] = funcValue; + } + } + } + else + { + fprintf(stderr, "ERROR: %s : Invalid map type: %s\n", __func__, mapType.c_str()); + exit(EXIT_FAILURE); } result.funcValue = tmpfuncValues; @@ -943,22 +985,35 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & // real func auto tmpRealCall = callPtr->getRealCallback(); - // func real value + // func real value & math real value & ulp unit value & error value if constexpr (TisDouble) { + // func real value mpfr::mpreal funcRealValue = tmpRealCall(paramFuncRealResults); // std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; funcRealValues.push_back(funcRealValue); - - auto errorValue = computeError(funcRealValue, result.funcValue); + + // math real value + result.realValue = tmpRealCall(parammathRealResults); + // std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; + mathRealValues.push_back(result.realValue); + + // math real value's ulp unit Value + result.ulpValue = computeUlpUnit(result.realValue); + + // error value according funcReal & func & mathReal values + auto errorValue = computeError(funcRealValue, result.funcValue, result.ulpValue); errorValues.push_back(errorValue); } else if constexpr (TisDoublePointer) { auto tmpfuncRealValues = new mpfr::mpreal[length]; + auto tmpmathRealValues = new mpfr::mpreal[length]; + auto tmpUlpValues = new double[length]; auto tmpErrorValues = new double[length]; for(int i = 0; i < length; i++) { + // func real value vector tmpParam; for(auto ¶m : paramResults) { @@ -966,42 +1021,25 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } auto funcRealValue = tmpRealCall(tmpParam); tmpfuncRealValues[i] = funcRealValue; - - tmpErrorValues[i] = computeError(funcRealValue, ((result.funcValue)[i])); - } - funcRealValues.push_back(tmpfuncRealValues); - errorValues.push_back(tmpErrorValues); - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - // math real value - if constexpr (TisDouble) - { - result.realValue = tmpRealCall(parammathRealResults); - // std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; - result.ulpValue = computeUlpUnit(result.realValue); - mathRealValues.push_back(result.realValue); - } - else if constexpr (TisDoublePointer) - { - auto tmpmathRealValues = new mpfr::mpreal[length]; - auto tmpUlpValues = new double[length]; - for(int i = 0; i < length; i++) - { - vector tmpParam; + // math real value + vector tmpParam1; for(auto ¶m : parammathRealResults) { - tmpParam.push_back(param[i]); + tmpParam1.push_back(param[i]); } - auto mathRealValue = tmpRealCall(tmpParam); + auto mathRealValue = tmpRealCall(tmpParam1); tmpmathRealValues[i] = mathRealValue; + + // math real value's ulp unit Value tmpUlpValues[i] = computeUlpUnit(mathRealValue); + + // error value according funcReal & func & mathReal values + tmpErrorValues[i] = computeError(funcRealValue, ((result.funcValue)[i])); } + funcRealValues.push_back(tmpfuncRealValues); mathRealValues.push_back(tmpmathRealValues); + errorValues.push_back(tmpErrorValues); result.realValue = tmpmathRealValues; result.ulpValue = tmpUlpValues; } @@ -1043,7 +1081,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & funcDrv = fDrvMapTwo.find(callee + "R")->second; derivativeFuncValue = funcDrv(inputX1, inputX2); auto &ulpX2 = paramUlpResults.at(1); - conditionNumber = ulpX2 * derivativeFuncValue / ulpX2; + conditionNumber = ulpX2 * derivativeFuncValue / ulpY; conditionNumbers.push_back(conditionNumber); } else @@ -1169,9 +1207,9 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else if(mapType == "d_d") { - auto tmpDoubleCall = doubleCall_d_d_map.find(opStr + "_" + opTypeStr)->second; if(opTypeStr == "dd") { + auto tmpDoubleCall = doubleCall_d_d_map.find(opStr + "_" + opTypeStr)->second; result.funcValue = tmpDoubleCall(x1[0], x2[0]); } else @@ -1188,7 +1226,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & funcValues.push_back(result.funcValue); } - // TODO: 按照double的方法,需要考虑输入为d_d的情况。目前这样可以解决模型不唯一的问题。 + // TODO: (DONE) 按照double的方法,需要考虑输入为d_d的情况。目前这样可以解决模型不唯一的问题。 // TODO: 下一步就是怎么把代码实现对应到模型上。可能需要重新考虑把当前步骤更改为dd带来的影响。 else if constexpr (TisDoublePointer) { @@ -1302,9 +1340,9 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & else if constexpr (TisDoublePointer) { auto tmpfuncRealValues = new mpfr::mpreal[length]; - auto tmpErrorValues = new double[length]; auto tmpmathRealValues = new mpfr::mpreal[length]; auto tmpUlpValues = new double[length]; + auto tmpErrorValues = new double[length]; for(int i = 0; i < length; i++) { // func real value @@ -1458,6 +1496,7 @@ void shadowValuePrint(const vector> &funcValues, const vector Date: Thu, 1 Jun 2023 16:12:18 +0800 Subject: [PATCH 20/54] Support exp & log for shadowValueKernel --- include/funclist.hpp | 6 ++++++ src/basic.cpp | 4 ++++ src/funclist.cpp | 30 +++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/funclist.hpp b/include/funclist.hpp index 602ae0c..7eabf63 100644 --- a/include/funclist.hpp +++ b/include/funclist.hpp @@ -155,4 +155,10 @@ mpfr::mpreal minesin_dd(double *x); template mpfr::mpreal minetan_dd(double *x); +template +mpfr::mpreal mineexp_dd(double *x); + +template +mpfr::mpreal minelog_dd(double *x); + #endif \ No newline at end of file diff --git a/src/basic.cpp b/src/basic.cpp index d08ca11..9eccd33 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -88,6 +88,10 @@ std::map singleCall_dd_map = { {"sin_dd", minesin_dd}, {"tan_d", minetan_dd}, {"tan_dd", minetan_dd}, + {"exp_d", mineexp_dd}, + {"exp_dd", mineexp_dd}, + {"log_d", minelog_dd}, + {"log_dd", minelog_dd}, }; std::map doubleCall_d_d_map = { diff --git a/src/funclist.cpp b/src/funclist.cpp index ec1cd83..264a69c 100644 --- a/src/funclist.cpp +++ b/src/funclist.cpp @@ -415,6 +415,30 @@ mpfr::mpreal minetan_dd(double *x) return result; } +template +mpfr::mpreal mineexp_dd(double *x) +{ + double y[2]; + c_dd_exp(x, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minelog_dd(double *x) +{ + double y[2]; + c_dd_log(x, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + // add template mpfr::mpreal mineadd_d_d(double x, double y); template mpfr::mpreal mineadd_d_d(double x, double y); @@ -459,4 +483,8 @@ template mpfr::mpreal minediv_dd_dd(double *x, double *y); template mpfr::mpreal minesin_dd(double *x); template mpfr::mpreal minesin_dd(double *x); template mpfr::mpreal minetan_dd(double *x); -template mpfr::mpreal minetan_dd(double *x); \ No newline at end of file +template mpfr::mpreal minetan_dd(double *x); +template mpfr::mpreal mineexp_dd(double *x); +template mpfr::mpreal mineexp_dd(double *x); +template mpfr::mpreal minelog_dd(double *x); +template mpfr::mpreal minelog_dd(double *x); \ No newline at end of file -- Gitee From 7df17805b3d3f037b38b88cec1a089a2943c86da Mon Sep 17 00:00:00 2001 From: hjw Date: Mon, 5 Jun 2023 16:26:48 +0800 Subject: [PATCH 21/54] Refine shadowValue method, modify output content and format, remove deprecated code. Details: computeError: remove the absolute value operation in error detection. getRanks function: support ascending and descending sorting, the default is descending. computeEpsilonE: add the evaluation criteria of the calculation step, i.e., the calculation of benefit. Specific modifications include: support for calculating the accuracy optimization gain (benifit), removing the operation of finding the absolute value in epsilon calculation, fixing bugs, and modifying the output content and format. shadowValueKernel: change the variable condNumOrder to errorValueOrder, correct the ulp error calculation method under the DoublePointer branch of Call. shadowValueInit: add the initialization of benefit. shadowValue: correct the calculation method of condNumOrder. Change the evaluation criteria of the calculation step from epsilonE to benefit. --- include/shadowValue.hpp | 2 - src/errorDetect.cpp | 3 +- src/geneCode.cpp | 46 +-- src/main.cpp | 46 ++- src/shadowValue.cpp | 690 ++++++++-------------------------------- 5 files changed, 184 insertions(+), 603 deletions(-) diff --git a/include/shadowValue.hpp b/include/shadowValue.hpp index b2a9ea2..a3da000 100644 --- a/include/shadowValue.hpp +++ b/include/shadowValue.hpp @@ -4,8 +4,6 @@ #include "basic.hpp" namespace Shadow { -void shadowValue(ast_ptr &expr, double input); - template vector shadowValue(const ast_ptr &expr, const std::map &varsValue, int length = 1, bool ifUnique = false, string uniqueLabel = "", string funcName = ""); diff --git a/src/errorDetect.cpp b/src/errorDetect.cpp index c9fbe02..e0d84b0 100644 --- a/src/errorDetect.cpp +++ b/src/errorDetect.cpp @@ -62,7 +62,8 @@ double computeError(mpfr::mpreal oracle, mpfr::mpreal x) double computeError(mpfr::mpreal funcRealValue, mpfr::mpreal funcValue, double unitUlp) { // ulp error - auto errorValue = fabs((funcRealValue - funcValue).toDouble() / unitUlp); + // auto errorValue = fabs((funcRealValue - funcValue).toDouble() / unitUlp); + auto errorValue = (funcRealValue - funcValue).toDouble() / unitUlp; return errorValue; } \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 9235567..798b5d5 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -1259,7 +1259,7 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel string directory = "srcTest/" + uniqueLabel + "/"; string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(num); string fileName = directory + funcName + ".c"; - cout << "\n\nfileName: " << fileName << "\topTypes: "; + // cout << "\n\nfileName: " << fileName << "\topTypes: "; std::stringstream ss; for(map::iterator it = opTypes.begin(); it != opTypes.end(); it++) { @@ -1273,28 +1273,28 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel /// call shadowValue to generate each step's values of expr. // varsValue is input values // inputNum is the number of input data - auto epsilonEStr = Shadow::shadowValue(expr, varsValue, inputNum, true, uniqueLabel, funcName); - auto it = opSequence.begin(); - for(int i = 0; i < (int)epsilonEStr.size(); i++) - { - auto &epsilonEStrNow = epsilonEStr.at(i); - if(*it == i) - { - if(opTypes[*it] == "DD") - { - cout << BOLDBRIGHTRED << epsilonEStrNow << "\n" << RESET; - } - else - { - cout << RED << epsilonEStrNow << "\n" << RESET; - } - it++; - } - else - { - cout << epsilonEStrNow << "\n"; - } - } + // auto epsilonEStr = Shadow::shadowValue(expr, varsValue, inputNum, true, uniqueLabel, funcName); + // auto it = opSequence.begin(); + // for(int i = 0; i < (int)epsilonEStr.size(); i++) + // { + // auto &epsilonEStrNow = epsilonEStr.at(i); + // if(*it == i) + // { + // if(opTypes[*it] == "DD") + // { + // cout << BOLDBRIGHTRED << epsilonEStrNow << "\n" << RESET; + // } + // else + // { + // cout << RED << epsilonEStrNow << "\n" << RESET; + // } + // it++; + // } + // else + // { + // cout << epsilonEStrNow << "\n"; + // } + // } // unsigned long int hjw = 0x3fe6e4f765fd8adaul; // double hhh = *((double *)(&hjw)); diff --git a/src/main.cpp b/src/main.cpp index 7dd0085..c8b3e3a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -286,15 +286,10 @@ int main() // set calculation order for originExpr auto opSequence = setOrder(originExpr); fmt::print("opSequence: {}\n", opSequence); - //// a simple try for shadow value - // vector values(dimension, 1.4); - // auto varsValue = setVarsValue(vars, values); - // fmt::print("varsValue = {}\n", varsValue); - // Shadow::shadowValue(originExpr, varsValue); //// generate input data for shadow value vector values1; - size_t inputNum = 10000; + size_t inputNum = 100000; for(int i = 0; i < dimension; i++) { auto &startOriginInterval = intervals.at(i * 2); @@ -311,12 +306,17 @@ int main() } auto varsValue1 = setVarsValue(vars, values1); //// call the shadowValue function to generate the shadow values of the expression. The shadow values are stored into files partly. - // Shadow::shadowValue(originExpr, varsValue1, inputNum); + auto epsilonEStr = Shadow::shadowValue(originExpr, varsValue1, inputNum); + for(int i = 0; i < (int)epsilonEStr.size(); i++) + { + auto &epsilonEStrNow = epsilonEStr.at(i); + cout << epsilonEStrNow << "\n"; + } //// TODO: free values1 //// support DD - vector outputStr; - auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum, outputStr); + // vector outputStr; + // auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum, outputStr); //// test DD's error vector startNowIdxs(dimension, 0); vector startOriginIntervals; @@ -330,32 +330,28 @@ int main() double step = width / (double)scales.at(i); steps.push_back(step); } - testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); // vector infos; // for(int i = 0; i < maxNum; i++) { - // cout << "-test error-" << i << "\n"; + // cout << "\n\n-test error-" << i << "\n"; // string tmp = "dd_" + std::to_string(i); // auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); // infos.push_back(infoTmp); // } - cout << std::left << setw(4) << "No"; + // cout << std::left << setw(4) << "No"; // cout << std::left << setw(4) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; - for(int i = 0; i < log2(maxNum); i++) { - cout << "step Type "; - } - cout << "\n"; - // cout << std::left << setw(4) << "No" << std::left << setw(15) << "average Err" << std::left << setw(15) << "max Err" << "op Type\n"; - auto it = opSequence.begin(); - for(int i = 0; i < maxNum; i++) - { + // for(int i = 0; i < log2(maxNum); i++) { + // cout << "step Type "; + // } + // cout << "\n"; + // for(int i = 0; i < maxNum; i++) + // { // auto &info = infos.at(i); - auto &opTypeStr = outputStr.at(i); - cout << std::left << setw(4) << i << opTypeStr << "\n"; - it++; + // auto &opTypeStr = outputStr.at(i); + // cout << std::left << setw(4) << i << opTypeStr << "\n"; // cout << std::left << setw(4) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; - } + // } - // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, 0); fprintf(stderr, GREEN "ready> " RESET); continue; diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index e791f0f..84d42c7 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -49,69 +49,6 @@ std::map> fDrvMapTwo = { {"powR", []([[maybe_unused]] double x, [[maybe_unused]] double y) { return log(x) * pow(x, y); }}, }; -// demo -double shadowValueKernel(ast_ptr &expr, double &input, vector &middleValues) -{ - auto type = expr->type(); - double result; - if(type == "Number") - { - NumberExprAST *numberExpr = dynamic_cast(expr.get()); - result = (numberExpr->getNumber()); - middleValues.push_back(result); - return result; - } - else if(type == "Variable") - { - middleValues.push_back(input); - return input; - } - else if(type == "Call") - { - CallExprAST *callPtr = dynamic_cast(expr.get()); - auto &args = callPtr->getArgs(); - vector paramResults; - for(auto& arg : args) - { - auto tmp = shadowValueKernel(arg, input, middleValues); - paramResults.push_back(tmp); - } - auto tmpCall = callPtr->getCallback(); - result = tmpCall(paramResults); - std::cout << "callee = " << callPtr->getCallee() << " result = " << result << std::endl; - middleValues.push_back(result); - - return result; - } - else if(type == "Binary") - { - BinaryExprAST *binPtr = dynamic_cast(expr.get()); - ast_ptr &lhs = binPtr->getLHS(); - ast_ptr &rhs = binPtr->getRHS(); - auto lhsValue = shadowValueKernel(lhs, input, middleValues); - auto rhsValue = shadowValueKernel(rhs, input, middleValues); - auto tmpCall = binPtr->getCallback(); - result = tmpCall(lhsValue, rhsValue); - std::cout << "op = " << binPtr->getOp() << " result = " << result << std::endl; - middleValues.push_back(result); - - return result; - } - else - { - fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); - exit(EXIT_FAILURE); - } -} - -// demo -void shadowValue(ast_ptr &expr, double input) -{ - vector middleValues; - shadowValueKernel(expr, input, middleValues); - fmt::print("middleValues := {}\n", middleValues); -} - std::map binaryOp = { {'+', "add"}, {'-', "sub"}, @@ -146,454 +83,6 @@ struct ParamTypeMapper template using ParamType = typename ParamTypeMapper::ParamType; -/* /// old shadowValueKernel method: not consider conditionNumbers. -template -struct valueTwo { - ParamType funcValue; - ParamType realValue; -}; - -template -valueTwo shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector> &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, int length = 1) -{ - auto type = expr->type(); - constexpr bool TisDouble = (std::is_same::value); - constexpr bool TisDoublePointer = (std::is_same::value); - valueTwo result; - if(type == "Number") - { - NumberExprAST *numberExpr = dynamic_cast(expr.get()); - auto funcValue = (numberExpr->getNumber()); - if constexpr (TisDouble) - { - result.funcValue = funcValue; - result.realValue = result.funcValue; - funcValues.push_back(result.funcValue); - funcRealValues.push_back(result.realValue); - mathRealValues.push_back(result.realValue); - errorValues.push_back(0); - } - else if constexpr (TisDoublePointer) - { - auto tmpfuncValues = new mpfr::mpreal[length]; - auto tmpRealValues = new mpfr::mpreal[length]; - auto tmperrorValues = new double[length](); - for(int i = 0; i < length; i++) - { - tmpfuncValues[i] = funcValue; - tmpRealValues[i] = funcValue; - } - result.funcValue = tmpfuncValues; - result.realValue = tmpRealValues; - funcValues.push_back(tmpfuncValues); - funcRealValues.push_back(tmpRealValues); - mathRealValues.push_back(tmpRealValues); - errorValues.push_back(tmperrorValues); - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - return result; - } - else if(type == "Variable") - { - VariableExprAST *variableExpr = dynamic_cast(expr.get()); - string variable = (variableExpr->getVariable()); - auto varValue = varsValue.find(variable)->second; - // if(std::is_same::type, T>::value) - if constexpr (TisDouble) - { - result.funcValue = varValue; - result.realValue = result.funcValue; - funcValues.push_back(result.funcValue); - funcRealValues.push_back(result.realValue); - mathRealValues.push_back(result.realValue); - errorValues.push_back(0); - } - else if constexpr (TisDoublePointer) - { - auto tmpfuncValues = new mpfr::mpreal[length]; - auto tmpRealValues = new mpfr::mpreal[length]; - auto tmperrorValues = new double[length](); - for(int i = 0; i < length; i++) - { - auto &tmpfuncValue = varValue[i]; - tmpfuncValues[i] = tmpfuncValue; - tmpRealValues[i] = tmpfuncValue; - } - result.funcValue = tmpfuncValues; - result.realValue = tmpRealValues; - funcValues.push_back(tmpfuncValues); - funcRealValues.push_back(tmpRealValues); - mathRealValues.push_back(tmpRealValues); - errorValues.push_back(tmperrorValues); - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - - return result; - } - else if(type == "Call") - { - CallExprAST *callPtr = dynamic_cast(expr.get()); - auto &args = callPtr->getArgs(); - vector> paramResults; - vector paramResultsDouble; - vector> paramFuncRealResults; - vector> parammathRealResults; - - for(auto& arg : args) - { - auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); - paramResults.push_back(tmp.funcValue); - if constexpr (TisDouble) - { - paramFuncRealResults.push_back(tmp.funcValue); - paramResultsDouble.push_back((tmp.funcValue).toDouble()); - } - parammathRealResults.push_back(tmp.realValue); - } - - // func - auto tmpCall = callPtr->getCallback(); - auto callee = callPtr->getCallee(); - auto calleeType = callPtr->getOpType(); - auto callTypeStr = opTypeMap.find(calleeType)->second; - string mapType; - for(const auto& arg : args) - { - auto opType = arg->getOpType(); - auto opTypeStr = opTypeMap.find(opType)->second; - mapType += "_" + opTypeStr; - } - - // func value - if constexpr (TisDouble) - { - if(mapType == "_dd") - { - double x1[2]{0}; - x1[0] = paramResults.at(0).toDouble(); - x1[1] = (paramResults.at(0) - x1[0]).toDouble(); - auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; - mpfr::mpreal tmp = tmpSingleCall(x1); - result.funcValue = tmp; - } - else - { - result.funcValue = tmpCall(paramResultsDouble); - } - std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; - funcValues.push_back(result.funcValue); - } - else if constexpr (TisDoublePointer) - { - auto tmpfuncValues = new mpfr::mpreal[length]; - if(mapType == "_dd") - { - double x1[2]{0}; - mpfr::mpreal tmp; - for(int i = 0; i < length; i++) - { - x1[0] = ((paramResults.at(0))[i]).toDouble(); - x1[1] = ((paramResults.at(0))[i] - x1[0]).toDouble(); - auto tmpSingleCall = singleCall_dd_map.find(callee + "_" + callTypeStr)->second; - tmpfuncValues[i] = tmpSingleCall(x1); - } - } - else - { - for(int i = 0; i < length; i++) - { - vector tmpParam; - for(auto ¶m : paramResults) - { - tmpParam.push_back((param[i]).toDouble()); - } - auto funcValue = tmpCall(tmpParam); - tmpfuncValues[i] = funcValue; - } - } - - result.funcValue = tmpfuncValues; - funcValues.push_back(tmpfuncValues); - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - - // real func - auto tmpRealCall = callPtr->getRealCallback(); - - // func real value - if constexpr (TisDouble) - { - mpfr::mpreal funcRealValue = tmpRealCall(paramFuncRealResults); - std::cout << "callee = " << callPtr->getCallee() << " funcRealValue = " << funcRealValue.toString() << std::endl; - funcRealValues.push_back(funcRealValue); - - auto errorValue = computeError(funcRealValue, result.funcValue); - errorValues.push_back(errorValue); - } - else if constexpr (TisDoublePointer) - { - auto tmpfuncRealValues = new mpfr::mpreal[length]; - auto tmpErrorValues = new double[length]; - for(int i = 0; i < length; i++) - { - vector tmpParam; - for(auto ¶m : paramResults) - { - tmpParam.push_back(param[i]); - } - auto funcRealValue = tmpRealCall(tmpParam); - tmpfuncRealValues[i] = funcRealValue; - - tmpErrorValues[i] = computeError(funcRealValue, ((result.funcValue)[i])); - } - funcRealValues.push_back(tmpfuncRealValues); - errorValues.push_back(tmpErrorValues); - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - - // math real value - if constexpr (TisDouble) - { - result.realValue = tmpRealCall(parammathRealResults); - std::cout << "callee = " << callPtr->getCallee() << " mathRealResult = " << result.realValue.toString() << std::endl; - mathRealValues.push_back(result.realValue); - } - else if constexpr (TisDoublePointer) - { - auto tmpmathRealValues = new mpfr::mpreal[length]; - for(int i = 0; i < length; i++) - { - vector tmpParam; - for(auto ¶m : parammathRealResults) - { - tmpParam.push_back(param[i]); - } - auto mathRealValue = tmpRealCall(tmpParam); - tmpmathRealValues[i] = mathRealValue; - } - mathRealValues.push_back(tmpmathRealValues); - result.realValue = tmpmathRealValues; - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - - return result; - } - else if(type == "Binary") - { - BinaryExprAST *binPtr = dynamic_cast(expr.get()); - ast_ptr &lhs = binPtr->getLHS(); - ast_ptr &rhs = binPtr->getRHS(); - auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); - auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, length); - - // func - auto tmpCall = binPtr->getCallback(); - auto op = binPtr->getOp(); - auto opType = binPtr->getOpType(); - auto opTypeStr = opTypeMap.find(opType)->second; - auto opTypeLHS = lhs->getOpType(); - auto opTypeRHS = rhs->getOpType(); - auto opStr = binaryOp.find(op)->second; - auto opTypeLhsStr = opTypeMap.find(opTypeLHS)->second; - auto opTypeRhsStr = opTypeMap.find(opTypeRHS)->second; - auto mapType = opTypeLhsStr + "_" + opTypeRhsStr; - - // func value - if constexpr (TisDouble) - { - double x1[2]{0}; - double x2[2]{0}; - x1[0] = lhsValue.funcValue.toDouble(); - x2[0] = rhsValue.funcValue.toDouble(); - if(mapType == "d_dd") - { - auto tmpDoubleCall = doubleCall_d_dd_map.find(opStr + "_" + opTypeStr)->second; - result.funcValue = tmpDoubleCall(x1[0], x2); - } - else if(mapType == "dd_d") - { - auto tmpDoubleCall = doubleCall_dd_d_map.find(opStr + "_" + opTypeStr)->second; - result.funcValue = tmpDoubleCall(x1, x2[0]); - } - else if(mapType == "dd_dd") - { - auto tmpDoubleCall = doubleCall_dd_dd_map.find(opStr + "_" + opTypeStr)->second; - result.funcValue = tmpDoubleCall(x1, x2); - } - else - { - result.funcValue = tmpCall(x1[0], x2[0]); - } - std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; - funcValues.push_back(result.funcValue); - - } - else if constexpr (TisDoublePointer) - { - auto tmpfuncValues = new mpfr::mpreal[length]; - double x1[2]{0}; - double x2[2]{0}; - if(mapType == "d_dd") - { - auto tmpDoubleCall = doubleCall_d_dd_map.find(opStr + "_" + opTypeStr)->second; - for(int i = 0; i < length; i++) - { - auto &tmpLhsValue = (lhsValue.funcValue)[i]; - auto &tmpRhsValue = (rhsValue.funcValue)[i]; - x2[0] = tmpRhsValue.toDouble(); - x2[1] = (tmpRhsValue - x2[0]).toDouble(); - tmpfuncValues[i] = tmpDoubleCall(tmpLhsValue.toDouble(), x2); - } - } - else if(mapType == "dd_d") - { - auto tmpDoubleCall = doubleCall_dd_d_map.find(opStr + "_" + opTypeStr)->second; - for(int i = 0; i < length; i++) - { - auto &tmpLhsValue = (lhsValue.funcValue)[i]; - auto &tmpRhsValue = (rhsValue.funcValue)[i]; - x1[0] = tmpLhsValue.toDouble(); - x1[1] = (tmpLhsValue - x1[0]).toDouble(); - tmpfuncValues[i] = tmpDoubleCall(x1, tmpRhsValue.toDouble()); - } - } - else if(mapType == "dd_dd") - { - auto tmpDoubleCall = doubleCall_dd_dd_map.find(opStr + "_" + opTypeStr)->second; - for(int i = 0; i < length; i++) - { - auto &tmpLhsValue = (lhsValue.funcValue)[i]; - auto &tmpRhsValue = (rhsValue.funcValue)[i]; - x1[0] = tmpLhsValue.toDouble(); - x1[1] = (tmpLhsValue - x1[0]).toDouble(); - x2[0] = tmpRhsValue.toDouble(); - x2[1] = (tmpRhsValue - x2[0]).toDouble(); - tmpfuncValues[i] = tmpDoubleCall(x1, x2); - } - } - else // d_d - { - for(int i = 0; i < length; i++) - { - auto &tmpLhsValue = (lhsValue.funcValue)[i]; - auto &tmpRhsValue = (rhsValue.funcValue)[i]; - tmpfuncValues[i] = tmpCall(tmpLhsValue.toDouble(), tmpRhsValue.toDouble()); - } - } - result.funcValue = tmpfuncValues; - funcValues.push_back(tmpfuncValues); - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - - // real func - auto tmpRealCall = binPtr->getRealCallback(); - - // func real value - if constexpr (TisDouble) - { - mpfr::mpreal funcRealValue = tmpRealCall(lhsValue.funcValue, rhsValue.funcValue); - std::cout << "op = " << binPtr->getOp() << " funcRealValue = " << funcRealValue.toString() << std::endl; - funcRealValues.push_back(funcRealValue); - - auto errorValue = computeError(funcRealValue, result.funcValue); - errorValues.push_back(errorValue); - - // absolute error - // double absErrorValue = fabs((funcRealValue - result.funcValue).toDouble()); - // errorValues.push_back(absErrorValue); - // relative error - // double relErrorValue = fabs(((funcRealValue - result.funcValue) / funcRealValue).toDouble()); - // errorValues.push_back(relErrorValue); - // ulp error - // auto unitUlp = computeUlpUnit(funcRealValue.toDouble()); - // auto ulpErrorValue = fabs((funcRealValue - result.funcValue).toDouble() / unitUlp); - // errorValues.push_back(ulpErrorValue); - } - else if constexpr (TisDoublePointer) - { - auto tmpfuncRealValues = new mpfr::mpreal[length]; - auto tmpErrorValues = new double[length]; - for(int i = 0; i < length; i++) - { - mpfr::mpreal tmpLhsValue = (lhsValue.funcValue)[i]; - mpfr::mpreal tmpRhsValue = (rhsValue.funcValue)[i]; - auto funcRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); - tmpfuncRealValues[i] = funcRealValue; - - tmpErrorValues[i] = computeError(funcRealValue, (result.funcValue)[i]); - - // absolute error - // tmpErrorValues[i] = fabs((funcRealValue - (result.funcValue)[i]).toDouble()); - } - funcRealValues.push_back(tmpfuncRealValues); - errorValues.push_back(tmpErrorValues); - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - - // math real value - if constexpr (TisDouble) - { - result.realValue = tmpRealCall(lhsValue.realValue, rhsValue.realValue); - std::cout << "op = " << binPtr->getOp() << " mathRealValue = " << result.realValue.toString() << std::endl; - mathRealValues.push_back(result.realValue); - } - else if constexpr (TisDoublePointer) - { - auto tmpmathRealValues = new mpfr::mpreal[length]; - for(int i = 0; i < length; i++) - { - mpfr::mpreal tmpLhsValue = (lhsValue.realValue)[i]; - mpfr::mpreal tmpRhsValue = (rhsValue.realValue)[i]; - auto mathRealValue = tmpRealCall(tmpLhsValue, tmpRhsValue); - tmpmathRealValues[i] = mathRealValue; - } - mathRealValues.push_back(tmpmathRealValues); - result.realValue = tmpmathRealValues; - } - else - { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); - exit(EXIT_FAILURE); - } - - return result; - } - else - { - fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); - exit(EXIT_FAILURE); - } -} -*/ - template struct valueThree { ParamType funcValue; @@ -679,10 +168,17 @@ void computeConditionNumber(const ast_ptr &expr, vector &conditionNumbers, ve } // The function takes in vecotor v as input, and returns vecotor res, where res[i] represents the rank of the v[i] by descending order." -vector getRanks(const vector &v) +vector getRanks(const vector &v, bool descending = true) { vector sorted = v; - std::sort(sorted.begin(), sorted.end(), std::greater()); + if(descending) + { + std::sort(sorted.begin(), sorted.end(), std::greater()); + } + else + { + std::sort(sorted.begin(), sorted.end(), std::less()); + } auto last = std::unique(sorted.begin(), sorted.end()); // Remove duplicates sorted.erase(last, sorted.end()); // Delete excess elements vector res(v.size()); @@ -696,7 +192,7 @@ vector getRanks(const vector &v) } template -vector computeEpsilonE(vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const int length = 1) +vector computeEpsilonE(vector &benefit, vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const int length = 1) { constexpr bool TisDouble = (std::is_same::value); constexpr bool TisDoublePointer = (std::is_same::value); @@ -705,11 +201,28 @@ vector computeEpsilonE(vector &epsilonE, const vector &errorValues vector epsilonEStr; for(size_t i = 0; i < errorValues.size(); i++) { - epsilonE.at(i) = fabs(errorValues.at(i) * conditionNumbersOp.at(condNumOrder.at(i))); + epsilonE.at(i) = errorValues.at(i) * conditionNumbersOp.at(condNumOrder.at(i)); epsilonEStr.push_back(std::to_string(epsilonE.at(i))); } - auto sum = std::accumulate(epsilonE.begin(), epsilonE.end(), 0); + auto sum = std::accumulate(epsilonE.begin(), epsilonE.end(), 0.0); + fmt::print("the average of epsilonE are: {}\n", epsilonE); std::cout << "The sum of the elements in the vector is: " << sum << std::endl; + + // compute benefit + double minBenefit = std::numeric_limits::infinity(); + int minBenefitIdx = std::numeric_limits::infinity(); + for(size_t i = 0; i < errorValues.size(); i++) + { + benefit.at(i) = fabs(sum - epsilonE.at(i)); + if(benefit.at(i) < minBenefit) + { + minBenefit = benefit.at(i); + minBenefitIdx = i; + } + } + fmt::print("the benefit of steps are: {}\n", benefit); + std::cout << "minBenefitIdx: " << minBenefitIdx << ", minBenefit: " << minBenefit << std::endl; + return epsilonEStr; } else if constexpr (TisDoublePointer) @@ -717,35 +230,87 @@ vector computeEpsilonE(vector &epsilonE, const vector &errorValues vector epsilonEAverage(errorValues.size(), 0.0); vector errorValuesAverage(errorValues.size(), 0.0); vector conditionNumbersOpAverage(errorValues.size(), 0.0); + vector sumOfAll(length, 0.0); + + // compute epsilonE and its sum. These 3 average values are not useful for(size_t i = 0; i < errorValues.size(); i++) { for(int j = 0; j < length; j++) { - epsilonE.at(i)[j] = fabs(errorValues.at(i)[j] * conditionNumbersOp.at(condNumOrder.at(i))[j]); - epsilonEAverage.at(i) += epsilonE.at(i)[j]; // TODO: 实际上,这个fabs函数应该在求取条件数的时候就加上。但从结果讲,在最后加的效果是等价的。errorValues根据我的印象,应该是早都加过fabs了。 - errorValuesAverage.at(i) += errorValues.at(i)[j]; - conditionNumbersOpAverage.at(i) += conditionNumbersOp.at(i)[j]; + epsilonE.at(i)[j] = errorValues.at(i)[j] * conditionNumbersOp.at(condNumOrder.at(i))[j]; + epsilonEAverage.at(i) += epsilonE.at(i)[j]; + // errorValuesAverage.at(i) += errorValues.at(i)[j]; + // conditionNumbersOpAverage.at(i) += conditionNumbersOp.at(i)[j]; + sumOfAll.at(j) += epsilonE.at(i)[j]; } epsilonEAverage.at(i) /= length; - errorValuesAverage.at(i) /= length; - conditionNumbersOpAverage.at(i) /= length; + // errorValuesAverage.at(i) /= length; + // conditionNumbersOpAverage.at(i) /= length; } - auto ranks = getRanks(epsilonEAverage); - // fmt::print("the avarage of epsilonE is: {}\n", epsilonEAverage); - std::cout << "epsilonE rank\n"; - vector epsilonEStr; - for(size_t i = 0; i < epsilonEAverage.size(); i++) + // auto sum = std::accumulate(epsilonEAverage.begin(), epsilonEAverage.end(), 0.0); + auto sum = std::accumulate(sumOfAll.begin(), sumOfAll.end(), 0.0); + auto sumAverage = fabs(sum / length); + + // compute benefit + vector minBenefit(length, std::numeric_limits::infinity()); + vector minBenefitIdx(length, std::numeric_limits::infinity()); + vector benefitAverage(errorValues.size(), 0.0); + for(size_t i = 0; i < errorValues.size(); i++) { - // fmt::print("{} {}\n", epsilonEAverage.at(i), ranks.at(i)); - // fmt::print("rank {}: errorValuesAverage = {} conditionNumbersOpAverage = {} epsilonEAverage = {}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); - // fmt::print("{}: {:<15e} {:<15e} {:<15e}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); - auto epsilonEStrNow = fmt::format("{}: {:<15e} {:<15e} {:<15e}", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); - epsilonEStr.push_back(epsilonEStrNow); + for(int j = 0; j < length; j++) + { + benefit.at(i)[j] = fabs(sumOfAll.at(j) - epsilonE.at(i)[j]); + if(benefit.at(i)[j] < minBenefit.at(j)) + { + minBenefit.at(j) = benefit.at(i)[j]; + minBenefitIdx.at(j) = i; + } + benefitAverage.at(i) += benefit.at(i)[j]; + } + benefitAverage.at(i) /= length; } - auto sum = std::accumulate(epsilonEAverage.begin(), epsilonEAverage.end(), 0.0); - string sumEpsilon = fmt::format("The sum of the epsilon is {:g}\n", sum); - epsilonEStr.push_back(sumEpsilon); - return epsilonEStr; + // for(size_t i = 0; i < errorValues.size(); i++) + // { + // benefitAverage.at(i) = fabs((sum / length) - epsilonEAverage.at(i)); + // } + + // old print + // auto ranks1 = getRanks(benefitAverage, false); + // std::cout << "epsilonE rank\n"; + // vector epsilonEStr; + // for(size_t i = 0; i < epsilonEAverage.size(); i++) + // { + // // fmt::print("{} {}\n", epsilonEAverage.at(i), ranks.at(i)); + // // fmt::print("rank {}: errorValuesAverage = {} conditionNumbersOpAverage = {} epsilonEAverage = {}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); + // // fmt::print("{}: {:<15e} {:<15e} {:<15e}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); + // // auto epsilonEStrNow = fmt::format("{}: {:<15e} {:<15e} {:<15e}", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i)); + // auto epsilonEStrNow = fmt::format("{}: {:<15e}", ranks1.at(i), epsilonEAverage.at(i)); + // epsilonEStr.push_back(epsilonEStrNow); + // } + // auto sumEpsilon = std::accumulate(epsilonEAverage.begin(), epsilonEAverage.end(), 0.0); + // string sumEpsilonStr = fmt::format("The sum of the epsilon is {:g}\n", sumEpsilon); + // epsilonEStr.push_back(sumEpsilonStr); + // return epsilonEStr; + + // print + // fmt::print("the average of benefit are: {}", benefitAverage); + auto ranks = getRanks(benefitAverage, false); + fmt::print("{:<3} {:^4} {:<15}\n", "NO.", "rank", "benefit"); + // fmt::print("{:<3} {:<4} {:<15} {:<15} {:<15} {:<15}\n", "No.", "rank", "errValAver", "condNumOpAver", "epsilonEAver", "benefit"); + vector benefitStr; + for(size_t i = 0; i < benefitAverage.size(); i++) + { + // fmt::print("{} {} {}\n", benefitAverage.at(i), ranks.at(i)); + // fmt::print("rank {}: errorValuesAverage = {} conditionNumbersOpAverage = {} benefitAverage = {}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), benefitAverage.at(i)); + // fmt::print("{}: {:<15e} {:<15e} {:<15e}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), benefitAverage.at(i)); + // auto benefitStrNow = fmt::format("{:<3} {:<4} {:<15e} {:<15e} {:<15e} {:<15e}", i, ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i), benefitAverage.at(i)); + auto benefitStrNow = fmt::format("{:<3} {:^4} {:<15e}", i, ranks.at(i), benefitAverage.at(i)); + benefitStr.push_back(benefitStrNow); + } + string sumStr = fmt::format("The avearge sum of the epsilon is {:g}\n", sumAverage); + benefitStr.push_back(sumStr); + + return benefitStr; } else { @@ -755,7 +320,7 @@ vector computeEpsilonE(vector &epsilonE, const vector &errorValues } template -valueThree shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector> &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, vector &conditionNumbers, vector &condNumOrder, int length = 1) +valueThree shadowValueKernel(const ast_ptr &expr, const std::map &varsValue, vector> &funcValues, vector> &funcRealValues, vector> &mathRealValues, vector &errorValues, vector &conditionNumbers, vector &errorValueOrder, int length = 1) { auto type = expr->type(); constexpr bool TisDouble = (std::is_same::value); @@ -863,7 +428,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & for(auto& arg : args) { - auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, condNumOrder, length); + auto tmp = shadowValueKernel(arg, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, errorValueOrder, length); paramResults.push_back(tmp.funcValue); if constexpr (TisDouble) { @@ -873,7 +438,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & parammathRealResults.push_back(tmp.realValue); paramUlpResults.push_back(tmp.ulpValue); // condition number vector's op order - condNumOrder.push_back(arg->getOrder()); + errorValueOrder.push_back(arg->getOrder()); } // func @@ -1035,7 +600,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & tmpUlpValues[i] = computeUlpUnit(mathRealValue); // error value according funcReal & func & mathReal values - tmpErrorValues[i] = computeError(funcRealValue, ((result.funcValue)[i])); + tmpErrorValues[i] = computeError(funcRealValue, ((result.funcValue)[i]), tmpUlpValues[i]); } funcRealValues.push_back(tmpfuncRealValues); mathRealValues.push_back(tmpmathRealValues); @@ -1160,8 +725,8 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & BinaryExprAST *binPtr = dynamic_cast(expr.get()); ast_ptr &lhs = binPtr->getLHS(); ast_ptr &rhs = binPtr->getRHS(); - auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, condNumOrder, length); - auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, condNumOrder, length); + auto lhsValue = shadowValueKernel(lhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, errorValueOrder, length); + auto rhsValue = shadowValueKernel(rhs, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, errorValueOrder, length); // func auto tmpCall = binPtr->getCallback(); @@ -1176,8 +741,8 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & auto mapType = opTypeLhsStr + "_" + opTypeRhsStr; // condition number vector's op order - condNumOrder.push_back(lhs->getOrder()); - condNumOrder.push_back(rhs->getOrder()); + errorValueOrder.push_back(lhs->getOrder()); + errorValueOrder.push_back(rhs->getOrder()); // func value if constexpr (TisDouble) @@ -1437,7 +1002,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } template -void shadowValueInit(vector &conditionNumbersOp, vector &epsilonE, const size_t condNumOpSize, const int length) +void shadowValueInit(vector &conditionNumbersOp, vector &benefit, vector &epsilonE, const size_t condNumOpSize, const int length) { constexpr bool TisDouble = (std::is_same::value); constexpr bool TisDoublePointer = (std::is_same::value); @@ -1446,6 +1011,7 @@ void shadowValueInit(vector &conditionNumbersOp, vector &epsilonE, const s for(size_t i = 0; i < condNumOpSize; i++) { conditionNumbersOp.push_back(1); + benefit.push_back(0); epsilonE.push_back(0); } } @@ -1461,6 +1027,11 @@ void shadowValueInit(vector &conditionNumbersOp, vector &epsilonE, const s conditionNumbersOp.back()[i] = 1; } for(size_t i = 0; i < condNumOpSize; i++) + { + auto tmp = new double[length]; + benefit.push_back(tmp); + } + for(size_t i = 0; i < condNumOpSize; i++) { auto tmp = new double[length]; epsilonE.push_back(tmp); @@ -1588,17 +1159,32 @@ vector shadowValue(const ast_ptr &expr, const std::map &varsV vector conditionNumbers; std::vector> funcRealValues; std::vector> mathRealValues; - vector condNumOrder; - shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, condNumOrder, length); - condNumOrder.push_back(conditionNumbers.size()); // 令condNumber最后一个元素指向conditionNumber的最后一个元素,同时保证其长度同errorValues、conditionNumberOp一致 - // fmt::print("condNumOrder: {}\n", condNumOrder); + vector errorValueOrder; // for conditionNumbers vector, store the corresponding errorValue order + shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, errorValueOrder, length); + errorValueOrder.push_back(conditionNumbers.size()); // 令condNumber最后一个元素指向conditionNumber的最后一个元素,同时保证其长度同errorValues、conditionNumberOp一致 + fmt::print("errorValueOrder: {}\n", errorValueOrder); + vector condNumOrder; // for errorValue vector, store the corresponding conditionNumbers order + for(int i = 0; i < (int)errorValueOrder.size(); i++) + { + vector::iterator iter = std::find(errorValueOrder.begin(), errorValueOrder.end(), i); + if (iter == errorValueOrder.end()) + { + exit(EXIT_FAILURE); + } + else + { + auto tmp = std::distance(errorValueOrder.begin(), iter); + condNumOrder.push_back(tmp); + } + } + fmt::print("condNumOrder: {}\n", condNumOrder); vector conditionNumbersOp; - vector epsilonE; - shadowValueInit(conditionNumbersOp, epsilonE, conditionNumbers.size() + 1, length); + vector benefit, epsilonE; + shadowValueInit(conditionNumbersOp, benefit, epsilonE, conditionNumbers.size() + 1, length); int IDfather = conditionNumbersOp.size() - 1; int IDnow = conditionNumbers.size() - 1; computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); - auto epsilonEStr = computeEpsilonE(epsilonE, errorValues, conditionNumbersOp, condNumOrder, length); + auto epsilonEStr = computeEpsilonE(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, length); // shadowValuePrint(funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, conditionNumbersOp, epsilonE, varsValue, length, ifUnique, uniqueLabel, funcName); return epsilonEStr; -- Gitee From a29a539fdfcd7cafea2704cac9873a80aaf145ca Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 6 Jun 2023 16:52:10 +0800 Subject: [PATCH 22/54] Add support for two-parameter functions in the dd section of the shadowValue method, which currently supports the pow function. Optimize the debug ability about fprintf function. --- include/funclist.hpp | 12 ++++ src/basic.cpp | 8 +++ src/funclist.cpp | 65 +++++++++++++++++ src/shadowValue.cpp | 164 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 227 insertions(+), 22 deletions(-) diff --git a/include/funclist.hpp b/include/funclist.hpp index 7eabf63..671062b 100644 --- a/include/funclist.hpp +++ b/include/funclist.hpp @@ -149,6 +149,18 @@ mpfr::mpreal minediv_dd_d(double *x, double y); template mpfr::mpreal minediv_dd_dd(double *x, double *y); +template +mpfr::mpreal minepow_d_d(double x, double y); + +template +mpfr::mpreal minepow_d_dd(double x, double *y); + +template +mpfr::mpreal minepow_dd_d(double *x, double y); + +template +mpfr::mpreal minepow_dd_dd(double *x, double *y); + template mpfr::mpreal minesin_dd(double *x); diff --git a/src/basic.cpp b/src/basic.cpp index 9eccd33..6102214 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -103,6 +103,8 @@ std::map doubleCall_d_d_map = { {"mul_dd", minemul_d_d}, {"div_d", minediv_d_d}, {"div_dd", minediv_d_d}, + {"pow_dd", minepow_d_d}, + {"pow_dd", minepow_d_d}, }; std::map doubleCall_d_dd_map = { @@ -114,6 +116,8 @@ std::map doubleCall_d_dd_map = { {"mul_dd", minemul_d_dd}, {"div_d", minediv_d_dd}, {"div_dd", minediv_d_dd}, + {"pow_dd", minepow_d_dd}, + {"pow_dd", minepow_d_dd}, }; std::map doubleCall_dd_d_map = { @@ -125,6 +129,8 @@ std::map doubleCall_dd_d_map = { {"mul_dd", minemul_dd_d}, {"div_d", minediv_dd_d}, {"div_dd", minediv_dd_d}, + {"pow_dd", minepow_dd_d}, + {"pow_dd", minepow_dd_d}, }; std::map doubleCall_dd_dd_map = { @@ -136,6 +142,8 @@ std::map doubleCall_dd_dd_map = { {"mul_dd", minemul_dd_dd}, {"div_d", minediv_dd_dd}, {"div_dd", minediv_dd_dd}, + {"pow_dd", minepow_dd_dd}, + {"pow_dd", minepow_dd_dd}, }; //===----------------------------------------------------------------------===// diff --git a/src/funclist.cpp b/src/funclist.cpp index 264a69c..e33288a 100644 --- a/src/funclist.cpp +++ b/src/funclist.cpp @@ -391,6 +391,61 @@ mpfr::mpreal minediv_dd_dd(double *x1Ptr, double *x2Ptr) return result; } +template +mpfr::mpreal minepow_d_d(double x1, double x2) +{ + double x1Ptr[2]; + x1Ptr[0] = x1; + double x2Ptr[2]; + x2Ptr[0] = x2; + double y[2]; + c_dd_pow_mine(x1Ptr, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minepow_d_dd(double x1, double *x2Ptr) +{ + double x1Ptr[2]; + x1Ptr[0] = x1; + double y[2]; + c_dd_pow_mine(x1Ptr, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minepow_dd_d(double *x1Ptr, double x2) +{ + double x2Ptr[2]; + x2Ptr[0] = x2; + double y[2]; + c_dd_pow_mine(x1Ptr, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + +template +mpfr::mpreal minepow_dd_dd(double *x1Ptr, double *x2Ptr) +{ + double y[2]; + c_dd_pow_mine(x1Ptr, x2Ptr, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} template mpfr::mpreal minesin_dd(double *x) { @@ -479,6 +534,16 @@ template mpfr::mpreal minediv_dd_d(double *x, double y); template mpfr::mpreal minediv_dd_dd(double *x, double *y); template mpfr::mpreal minediv_dd_dd(double *x, double *y); +// pow +template mpfr::mpreal minepow_d_d(double x, double y); +template mpfr::mpreal minepow_d_d(double x, double y); +template mpfr::mpreal minepow_d_dd(double x, double *y); +template mpfr::mpreal minepow_d_dd(double x, double *y); +template mpfr::mpreal minepow_dd_d(double *x, double y); +template mpfr::mpreal minepow_dd_d(double *x, double y); +template mpfr::mpreal minepow_dd_dd(double *x, double *y); +template mpfr::mpreal minepow_dd_dd(double *x, double *y); + // single math function template mpfr::mpreal minesin_dd(double *x); template mpfr::mpreal minesin_dd(double *x); diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 84d42c7..e4ca08a 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -162,7 +162,7 @@ void computeConditionNumber(const ast_ptr &expr, vector &conditionNumbers, ve } else { - fprintf(stderr, "ERROR : %s : unknowntype %s\n", __func__, type.c_str()); + fprintf(stderr, "ERROR: %s : line %d: unknowntype %s\n", __func__, __LINE__, type.c_str()); exit(EXIT_FAILURE); } } @@ -314,7 +314,7 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve } else { - fprintf(stderr, "ERROR: %s: the type of T %s is not supported\n", __func__, typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } } @@ -364,7 +364,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } return result; @@ -410,7 +410,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } @@ -457,7 +457,59 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & // func value if constexpr (TisDouble) { - if(mapType == "_dd") + if(mapType == "_d_dd") + { + double x0[2]{0}; + double x1[2]{0}; + auto tmpDoubleCall = doubleCall_d_dd_map.find(callee + "_" + callTypeStr)->second; + x0[0] = (paramResults.at(0)).toDouble(); + x1[0] = (paramResults.at(1)).toDouble(); + x1[1] = (paramResults.at(1) - x1[0]).toDouble(); + mpfr::mpreal tmp = tmpDoubleCall(x0[0], x1); + result.funcValue = tmp; + } + else if(mapType == "_dd_d") + { + double x0[2]{0}; + double x1[2]{0}; + auto tmpDoubleCall = doubleCall_dd_d_map.find(callee + "_" + callTypeStr)->second; + x0[0] = (paramResults.at(0)).toDouble(); + x0[1] = (paramResults.at(0) - x0[0]).toDouble(); + x1[0] = (paramResults.at(1)).toDouble(); + mpfr::mpreal tmp = tmpDoubleCall(x0, x1[0]); + result.funcValue = tmp; + } + else if(mapType == "_dd_dd") + { + double x0[2]{0}; + double x1[2]{0}; + auto tmpDoubleCall = doubleCall_dd_dd_map.find(callee + "_" + callTypeStr)->second; + x0[0] = (paramResults.at(0)).toDouble(); + x0[1] = (paramResults.at(0) - x0[0]).toDouble(); + x1[0] = (paramResults.at(1)).toDouble(); + x1[1] = (paramResults.at(1) - x1[0]).toDouble(); + mpfr::mpreal tmp = tmpDoubleCall(x0, x1); + result.funcValue = tmp; + } + else if(mapType == "_d_d") + { + double x0[2]{0}; + double x1[2]{0}; + if(callTypeStr == "dd") + { + auto tmpDoubleCall = doubleCall_d_d_map.find(callee + "_" + callTypeStr)->second; + x0[0] = (paramResults.at(0)).toDouble(); + x1[0] = (paramResults.at(1)).toDouble(); + mpfr::mpreal tmp = tmpDoubleCall(x0[0], x1[0]); + result.funcValue = tmp; + } + else + { + double tmp = tmpCall(paramResultsDouble); + result.funcValue = tmp; + } + } + else if(mapType == "_dd") { double x1[2]{0}; x1[0] = paramResults.at(0).toDouble(); @@ -484,7 +536,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "ERROR: %s : Invalid map type: %s\n", __func__, mapType.c_str()); + fprintf(stderr, "ERROR: %s : line %d: Invalid map type: %s\n", __func__, __LINE__, mapType.c_str()); exit(EXIT_FAILURE); } // std::cout << "callee = " << callPtr->getCallee() << " result = " << result.funcValue << std::endl; @@ -493,7 +545,74 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & else if constexpr (TisDoublePointer) { auto tmpfuncValues = new mpfr::mpreal[length]; - if(mapType == "_dd") + if(mapType == "_d_dd") + { + double x0[2]{0}; + double x1[2]{0}; + auto tmpDoubleCall = doubleCall_d_dd_map.find(callee + "_" + callTypeStr)->second; + for(int i = 0; i < length; i++) + { + x0[0] = ((paramResults.at(0))[i]).toDouble(); + x1[0] = ((paramResults.at(1))[i]).toDouble(); + x1[1] = ((paramResults.at(1))[i] - x1[0]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(x0[0], x1); + } + } + else if(mapType == "_dd_d") + { + double x0[2]{0}; + double x1[2]{0}; + auto tmpDoubleCall = doubleCall_dd_d_map.find(callee + "_" + callTypeStr)->second; + for(int i = 0; i < length; i++) + { + x0[0] = ((paramResults.at(0))[i]).toDouble(); + x0[1] = ((paramResults.at(0))[i] - x0[0]).toDouble(); + x1[0] = ((paramResults.at(1))[i]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(x0, x1[0]); + } + } + else if(mapType == "_dd_dd") + { + double x0[2]{0}; + double x1[2]{0}; + auto tmpDoubleCall = doubleCall_dd_dd_map.find(callee + "_" + callTypeStr)->second; + for(int i = 0; i < length; i++) + { + x0[0] = ((paramResults.at(0))[i]).toDouble(); + x0[1] = ((paramResults.at(0))[i] - x0[0]).toDouble(); + x1[0] = ((paramResults.at(1))[i]).toDouble(); + x1[1] = ((paramResults.at(1))[i] - x1[0]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(x0, x1); + } + } + else if(mapType == "_d_d") + { + double x0[2]{0}; + double x1[2]{0}; + if(callTypeStr == "dd") + { + auto tmpDoubleCall = doubleCall_d_d_map.find(callee + "_" + callTypeStr)->second; + for(int i = 0; i < length; i++) + { + x0[0] = ((paramResults.at(0))[i]).toDouble(); + x1[0] = ((paramResults.at(1))[i]).toDouble(); + tmpfuncValues[i] = tmpDoubleCall(x0[0], x1[0]); + } + } + else + { + for(int i = 0; i < length; i++) + { + vector tmpParam; + for(auto ¶m : paramResults) + { + tmpParam.push_back((param[i]).toDouble()); + } + tmpfuncValues[i] = tmpCall(tmpParam); + } + } + } + else if(mapType == "_dd") { double x1[2]{0}; mpfr::mpreal tmp; @@ -534,7 +653,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "ERROR: %s : Invalid map type: %s\n", __func__, mapType.c_str()); + fprintf(stderr, "ERROR: %s : line %d: Invalid map type: %s\n", __func__, __LINE__, mapType.c_str()); exit(EXIT_FAILURE); } @@ -543,7 +662,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } @@ -610,7 +729,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } @@ -651,7 +770,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: we can not support %ld parameters' function call\n", lenParam); + fprintf(stderr, "ERROR: %s : line %d: we can not support %ld parameters' function call\n", __func__, __LINE__, lenParam); exit(EXIT_FAILURE); } // for(size_t i = 0; i < parammathRealResults.size(); i++) @@ -708,13 +827,13 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: we can not support %ld parameters' function call\n", lenParam); + fprintf(stderr, "ERROR: %s : line %d: we can not support %ld parameters' function call\n", __func__, __LINE__, lenParam); exit(EXIT_FAILURE); } } else { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } @@ -784,7 +903,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "ERROR: %s : Invalid map type: %s\n", __func__, mapType.c_str()); + fprintf(stderr, "ERROR: %s : line %d: Invalid map type: %s\n", __func__, __LINE__, mapType.c_str()); exit(EXIT_FAILURE); } // std::cout << "op = " << binPtr->getOp() << " result = " << result.funcValue << std::endl; @@ -860,7 +979,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "ERROR: %s : Invalid map type: %s\n", __func__, mapType.c_str()); + fprintf(stderr, "ERROR: %s : line %d: Invalid map type: %s\n", __func__, __LINE__, mapType.c_str()); exit(EXIT_FAILURE); } result.funcValue = tmpfuncValues; @@ -868,7 +987,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } @@ -936,7 +1055,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } @@ -988,7 +1107,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "shadowValueKernel: the type of T %s is not supported\n", typeid(T).name()); + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); exit(EXIT_FAILURE); } @@ -996,7 +1115,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } else { - fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); + fprintf(stderr, "ERROR: %s : line %d: unknown type %s\n", __func__, __LINE__, type.c_str()); exit(EXIT_FAILURE); } } @@ -1039,7 +1158,7 @@ void shadowValueInit(vector &conditionNumbersOp, vector &benefit, vector> &funcValues, const vector> &funcValues, const vector shadowValue(const ast_ptr &expr, const std::map &varsV vector::iterator iter = std::find(errorValueOrder.begin(), errorValueOrder.end(), i); if (iter == errorValueOrder.end()) { + fprintf(stderr, "ERROR: %s : line %d: %d can not be found in errorValueOrder\n", __func__, __LINE__, i); exit(EXIT_FAILURE); } else -- Gitee From c24e6f99d363c28fd9955843b9e3c6e1ea2512d2 Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 6 Jun 2023 23:21:54 +0800 Subject: [PATCH 23/54] Refine the output content and format and fix a bug about dd codegen --- detectErrorTwoFPEDParallel.sh | 4 ++-- src/basic.cpp | 2 +- src/geneCode.cpp | 15 +++++++------ src/main.cpp | 42 +++++++++++++++++------------------ src/shadowValue.cpp | 10 +++++---- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/detectErrorTwoFPEDParallel.sh b/detectErrorTwoFPEDParallel.sh index e78b686..e55f60a 100755 --- a/detectErrorTwoFPEDParallel.sh +++ b/detectErrorTwoFPEDParallel.sh @@ -58,7 +58,7 @@ fi testFileName=test2paramFPEDParallel numProcs=32 -echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x1Start} ${x1End} ${x0Size} ${x1Size} ${prefix} ${middle} ${suffix} ${errfile}" +# echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x1Start} ${x1End} ${x0Size} ${x1Size} ${prefix} ${middle} ${suffix} ${errfile}" directory="./srcTest"/${uniqueLabel} suffixClean=`echo ${suffix} | sed 's@_x\|_y\|_z@@g'` sourceFile=${prefix}_${suffixClean} @@ -82,5 +82,5 @@ if [ ${errfile} -eq 1 ]; then cd - > /dev/null fi -echo "end detecting ${uniqueLabel}" +# echo "end detecting ${uniqueLabel}" echo diff --git a/src/basic.cpp b/src/basic.cpp index 6102214..0b6a58a 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -970,7 +970,7 @@ std::map setVarsValue(const vector &vars, const vector &va { if (values.size() != vars.size()) { - fprintf(stderr, "values.size() != vars.size(), which are %ld and %ld\n", values.size(), vars.size()); + fprintf(stderr, "ERROR: %s : line %d: values.size() should be equal to vars.size(). But values.size() = %ld, vars.size() = %ld\n", __func__, __LINE__, values.size(), vars.size()); exit(EXIT_FAILURE); } std::map results; diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 798b5d5..ac2c885 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -884,13 +884,13 @@ void showOrdersKernel(ast_ptr &expr, int &orderNow) if(type == "Number") { // string tmp = prompt + std::to_string(orderNow) + ": "; - printExpr(expr); + printExpr(expr, to_string(orderNow) + " "); orderNow++; } else if(type == "Variable") { // string tmp = prompt + std::to_string(orderNow) + ": "; - printExpr(expr); + printExpr(expr, to_string(orderNow) + " "); orderNow++; } else if(type == "Call") @@ -903,7 +903,7 @@ void showOrdersKernel(ast_ptr &expr, int &orderNow) showOrdersKernel(arg, orderNow); } // string tmp = prompt + std::to_string(orderNow) + ": "; - printExpr(expr); + printExpr(expr, to_string(orderNow) + " "); orderNow++; } else if(type == "Binary") @@ -914,7 +914,7 @@ void showOrdersKernel(ast_ptr &expr, int &orderNow) showOrdersKernel(lhs, orderNow); showOrdersKernel(rhs, orderNow); // string tmp = prompt + std::to_string(orderNow) + ": "; - printExpr(expr); + printExpr(expr, to_string(orderNow) + " "); orderNow++; } else @@ -969,18 +969,19 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) { NumberExprAST *numPtr = dynamic_cast(expr.get()); auto num = numPtr->getNumber(); + auto numStr = fmt::format("{}", num); if(opType == "double") { - ofs << "\t" << "double tmp" << order << " = " << num << ";\n"; + ofs << "\t" << "double tmp" << order << " = " << numStr << ";\n"; } else if(opType == "ld") { - ofs << "\t" << "long double tmp" << order << " = " << num << ";\n"; + ofs << "\t" << "long double tmp" << order << " = " << numStr << ";\n"; } else if(opType == "DD") { ofs << "\t" << "double tmp" << order << "[2];\n"; - ofs << "\t" << "tmp" << order << "[0] = " << num << ";\n"; + ofs << "\t" << "tmp" << order << "[0] = " << numStr << ";\n"; ofs << "\t" << "tmp" << order << "[1] = 0.0;\n"; } else diff --git a/src/main.cpp b/src/main.cpp index c8b3e3a..538dc90 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -285,7 +285,7 @@ int main() // set calculation order for originExpr auto opSequence = setOrder(originExpr); - fmt::print("opSequence: {}\n", opSequence); + fmt::print("\noperation's Sequence: {}\nthe number of sequence: {}, the number of mix-prec version: {}\n", opSequence, opSequence.size(), 1 << opSequence.size()); //// generate input data for shadow value vector values1; @@ -315,8 +315,8 @@ int main() //// TODO: free values1 //// support DD - // vector outputStr; - // auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum, outputStr); + vector outputStr; + auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum, outputStr); //// test DD's error vector startNowIdxs(dimension, 0); vector startOriginIntervals; @@ -331,26 +331,26 @@ int main() steps.push_back(step); } // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); - // vector infos; - // for(int i = 0; i < maxNum; i++) { - // cout << "\n\n-test error-" << i << "\n"; - // string tmp = "dd_" + std::to_string(i); - // auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); - // infos.push_back(infoTmp); - // } + vector infos; + for(int i = 0; i < maxNum; i++) { + cout << "\n\n-test error-" << i << "\n"; + string tmp = "dd_" + std::to_string(i); + auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + infos.push_back(infoTmp); + } // cout << std::left << setw(4) << "No"; - // cout << std::left << setw(4) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; - // for(int i = 0; i < log2(maxNum); i++) { - // cout << "step Type "; - // } - // cout << "\n"; - // for(int i = 0; i < maxNum; i++) - // { - // auto &info = infos.at(i); - // auto &opTypeStr = outputStr.at(i); + cout << "\n\n" << std::left << setw(4) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; + for(int i = 0; i < log2(maxNum); i++) { + cout << "step Type "; + } + cout << "\n"; + for(int i = 0; i < maxNum; i++) + { + auto &info = infos.at(i); + auto &opTypeStr = outputStr.at(i); // cout << std::left << setw(4) << i << opTypeStr << "\n"; - // cout << std::left << setw(4) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; - // } + cout << std::left << setw(4) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; + } fprintf(stderr, GREEN "ready> " RESET); continue; diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index e4ca08a..e5469f0 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -295,7 +295,8 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve // print // fmt::print("the average of benefit are: {}", benefitAverage); auto ranks = getRanks(benefitAverage, false); - fmt::print("{:<3} {:^4} {:<15}\n", "NO.", "rank", "benefit"); + fmt::print("{:^4} {:<15}\n", "rank", "benefit"); + // fmt::print("{:<3} {:^4} {:<15}\n", "NO.", "rank", "benefit"); // fmt::print("{:<3} {:<4} {:<15} {:<15} {:<15} {:<15}\n", "No.", "rank", "errValAver", "condNumOpAver", "epsilonEAver", "benefit"); vector benefitStr; for(size_t i = 0; i < benefitAverage.size(); i++) @@ -304,7 +305,8 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve // fmt::print("rank {}: errorValuesAverage = {} conditionNumbersOpAverage = {} benefitAverage = {}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), benefitAverage.at(i)); // fmt::print("{}: {:<15e} {:<15e} {:<15e}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), benefitAverage.at(i)); // auto benefitStrNow = fmt::format("{:<3} {:<4} {:<15e} {:<15e} {:<15e} {:<15e}", i, ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i), benefitAverage.at(i)); - auto benefitStrNow = fmt::format("{:<3} {:^4} {:<15e}", i, ranks.at(i), benefitAverage.at(i)); + auto benefitStrNow = fmt::format("{:^4} {:<15e}", ranks.at(i), benefitAverage.at(i)); + // auto benefitStrNow = fmt::format("{:<3} {:^4} {:<15e}", i, ranks.at(i), benefitAverage.at(i)); benefitStr.push_back(benefitStrNow); } string sumStr = fmt::format("The avearge sum of the epsilon is {:g}\n", sumAverage); @@ -1281,7 +1283,7 @@ vector shadowValue(const ast_ptr &expr, const std::map &varsV vector errorValueOrder; // for conditionNumbers vector, store the corresponding errorValue order shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, errorValueOrder, length); errorValueOrder.push_back(conditionNumbers.size()); // 令condNumber最后一个元素指向conditionNumber的最后一个元素,同时保证其长度同errorValues、conditionNumberOp一致 - fmt::print("errorValueOrder: {}\n", errorValueOrder); + // fmt::print("errorValueOrder: {}\n", errorValueOrder); vector condNumOrder; // for errorValue vector, store the corresponding conditionNumbers order for(int i = 0; i < (int)errorValueOrder.size(); i++) { @@ -1297,7 +1299,7 @@ vector shadowValue(const ast_ptr &expr, const std::map &varsV condNumOrder.push_back(tmp); } } - fmt::print("condNumOrder: {}\n", condNumOrder); + // fmt::print("condNumOrder: {}\n", condNumOrder); vector conditionNumbersOp; vector benefit, epsilonE; shadowValueInit(conditionNumbersOp, benefit, epsilonE, conditionNumbers.size() + 1, length); -- Gitee From 68019a6041f61bc767c17e00d3256a9f242d5757 Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 7 Jun 2023 15:21:36 +0800 Subject: [PATCH 24/54] Fix the bug that average Error occurs overflow --- srcTest/test2paramFPEDParallel.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/srcTest/test2paramFPEDParallel.c b/srcTest/test2paramFPEDParallel.c index c868375..e618f47 100644 --- a/srcTest/test2paramFPEDParallel.c +++ b/srcTest/test2paramFPEDParallel.c @@ -3,7 +3,7 @@ struct errorInfo { - double sumError; + long double sumError; double maxError; double maxInputX0; double maxInputX1; @@ -51,7 +51,9 @@ struct errorInfo test2paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1E DL maxInputX0, maxInputX1; int i0, i1; // int flag; - double x0, x1, reUlp, sumError, aveReUlp, maxReUlp, lenX0, lenX1; + double x0, x1, reUlp, aveReUlp, maxReUlp, lenX0, lenX1; + // double x0, x1, reUlp, sumError, aveReUlp, maxReUlp, lenX0, lenX1; + long double sumError; // mpfr mpfr_t mpfrOrcle, mpfrResult; @@ -122,6 +124,7 @@ struct errorInfo test2paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1E // printf("average ulp\tmax ulp\n"); // printf("%lg\t%lg\n", aveReUlp, maxReUlp); // printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxInputX1 = 0x%016lx %lg, maxInputX2 = 0x%016lx %lg, maxReUlp = %lg\n", aveReUlp, maxInputX0.l, maxInputX0.d, maxInputX1.l, maxInputX1.d, maxInputX2.l, maxInputX2.d, maxReUlp); + // printf("myid = %d, maxReUlp = %g, sumError = %Lg\n", myid, maxReUlp, sumError); #if ERRFILE // fprintf(f, "\n"); @@ -146,7 +149,11 @@ int main(int argc, char **argv) MPI_Comm_rank(MPI_COMM_WORLD, &myid); MPI_Comm_size(MPI_COMM_WORLD, &numProcs); MPI_Datatype MPI_errorInfo; - MPI_Type_contiguous(4, MPI_DOUBLE, &MPI_errorInfo); + // MPI_Type_contiguous(4, MPI_DOUBLE, &MPI_errorInfo); + const int blocklens[4] = {2, 1, 1, 1}; + MPI_Aint blockIndices[4] = {0, 16, 24, 32}; + MPI_Datatype blockType[4] = {MPI_LONG_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE}; + MPI_Type_create_struct(4, blocklens, blockIndices, blockType, &MPI_errorInfo); MPI_Type_commit(&MPI_errorInfo); // parameters init @@ -251,7 +258,7 @@ int main(int argc, char **argv) if (myid == 0) { double maxError = -1; - double aveError = 0; + long double aveError = 0; double errTmp = -1; int maxErrorIdx = -1; for (int i = 0; i < numProcs; i++) @@ -280,12 +287,12 @@ int main(int argc, char **argv) printf("Error opening file %s.\n", fileNameErr); exit(0); } - printf("average ulp\tmax ulp\n"); - printf("%.16le\t%.16le\n", aveError, maxError); - // printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxInputX1 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxInputX1.l, maxInputX1.d, maxError); + // printf("average ulp\tmax ulp\n"); + // printf("%.16Le\t%.16le\n", aveError, maxError); + // printf("\naveReUlp = %Lg\nmaxInputX0 = 0x%016lx %lg, maxInputX1 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxInputX1.l, maxInputX1.d, maxError); fprintf(fErr, "average ulp\tmax ulp\n"); - fprintf(fErr, "%.16le\t%.16le\n", aveError, maxError); - fprintf(fErr, "\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxInputX1 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxInputX1.l, maxInputX1.d, maxError); + fprintf(fErr, "%.16Le\t%.16le\n", aveError, maxError); + fprintf(fErr, "\naveReUlp = %Lg\nmaxInputX0 = 0x%016lx %lg, maxInputX1 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxInputX1.l, maxInputX1.d, maxError); free(fileNameErr); free(uniqueLabel); -- Gitee From 071bcddbc69e7cb1f4e28e0417a7efcee6bec9aa Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 7 Jun 2023 15:30:58 +0800 Subject: [PATCH 25/54] Fix the overflow bug about condition number --- src/shadowValue.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index e5469f0..5dc092b 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -19,6 +19,9 @@ using std::ios; namespace Shadow { +static const unsigned long int hugeNumINT = 0x7FC0000000000000ul; +static const double hugeNum = *(double *)(&hugeNumINT); // 1/8 * inf + std::map> fDrvMapOne = { {"sqrt", [](double x) { return 0.5 / sqrt(x); }}, {"cbrt", [](double x) { return 1 / (3.0 * cbrt(x*x)); }}, @@ -750,6 +753,10 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & auto input = parammathRealResults.at(0).toDouble(); auto derivativeFuncValue = funcDrv(input); auto conditionNumber = ulpX * derivativeFuncValue / ulpY; + if(!finite(conditionNumber)) + { + conditionNumber = hugeNum; + } conditionNumbers.push_back(conditionNumber); } else if (lenParam == 2) @@ -762,12 +769,20 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & auto derivativeFuncValue = funcDrv(inputX1, inputX2); auto &ulpX1 = paramUlpResults.at(0); auto conditionNumber = ulpX1 * derivativeFuncValue / ulpY; + if(!finite(conditionNumber)) + { + conditionNumber = hugeNum; + } conditionNumbers.push_back(conditionNumber); funcDrv = fDrvMapTwo.find(callee + "R")->second; derivativeFuncValue = funcDrv(inputX1, inputX2); auto &ulpX2 = paramUlpResults.at(1); conditionNumber = ulpX2 * derivativeFuncValue / ulpY; + if(!finite(conditionNumber)) + { + conditionNumber = hugeNum; + } conditionNumbers.push_back(conditionNumber); } else @@ -801,6 +816,10 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & auto input = parammathRealResults.at(0)[i].toDouble(); auto derivativeFuncValue = funcDrv(input); tmpConditionNumbers[i] = ulpX * derivativeFuncValue / ulpYs[i]; + if(!finite(tmpConditionNumbers[i])) + { + tmpConditionNumbers[i] = hugeNum; + } } conditionNumbers.push_back(tmpConditionNumbers); } @@ -823,6 +842,15 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & derivativeFuncValue = funcDrvR(inputX1, inputX2); auto &ulpX2 = paramUlpResults.at(1)[i]; tmpConditionNumbers2[i] = ulpX2 * derivativeFuncValue / ulpYs[i]; + + if(!finite(tmpConditionNumbers1[i])) + { + tmpConditionNumbers1[i] = hugeNum; + } + if(!finite(tmpConditionNumbers2[i])) + { + tmpConditionNumbers2[i] = hugeNum; + } } conditionNumbers.push_back(tmpConditionNumbers1); conditionNumbers.push_back(tmpConditionNumbers2); @@ -1074,12 +1102,20 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & auto derivativeFuncValue = funcDrv(inputLhs, inputRhs); auto &ulpXLhs = lhsValue.ulpValue; auto conditionNumber = ulpXLhs * derivativeFuncValue / ulpY; + if(!finite(conditionNumber)) + { + conditionNumber = hugeNum; + } conditionNumbers.push_back(conditionNumber); funcDrv = fDrvMapTwo.find(opStr + "R")->second; derivativeFuncValue = funcDrv(inputLhs, inputRhs); auto &ulpXRhs = rhsValue.ulpValue; conditionNumber = ulpXRhs * derivativeFuncValue / ulpY; + if(!finite(conditionNumber)) + { + conditionNumber = hugeNum; + } conditionNumbers.push_back(conditionNumber); } else if constexpr (TisDoublePointer) @@ -1103,6 +1139,15 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & derivativeFuncValue = funcDrvR(inputLhs, inputRhs); auto &ulpX2 = rhsValue.ulpValue[i]; tmpConditionNumbers2[i] = ulpX2 * derivativeFuncValue / ulpYs[i]; + + if(!finite(tmpConditionNumbers1[i])) + { + tmpConditionNumbers1[i] = hugeNum; + } + if(!finite(tmpConditionNumbers2[i])) + { + tmpConditionNumbers2[i] = hugeNum; + } } conditionNumbers.push_back(tmpConditionNumbers1); conditionNumbers.push_back(tmpConditionNumbers2); -- Gitee From ea1d80e154a6d0c5c097a99792df51ebf8ec4568 Mon Sep 17 00:00:00 2001 From: hjw Date: Thu, 8 Jun 2023 16:17:53 +0800 Subject: [PATCH 26/54] codegenWrapper: add a codegen method and refine. Refine output content and format. --- src/geneCode.cpp | 89 ++++++++++++++++++++++++++++++--------------- src/main.cpp | 11 +++++- src/shadowValue.cpp | 2 +- 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/src/geneCode.cpp b/src/geneCode.cpp index ac2c885..1409eab 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -1210,10 +1210,19 @@ void codegen(ast_ptr &expr, vector &vars, const string funcName, ofstrea // Generate double-double implementations in all states and return the number of generated codes int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map varsValue, size_t inputNum, vector &outputStr) { - // AST init + // init auto opSequence = setOrder(expr); auto lenOp = opSequence.size(); - + typedef std::map mapOpType; + vector opTypesAll; + vector dataTypes = {"DD", "double"}; + + // for these expressions winth huge number mix-precision versions. + // 1st: set the opTypes vector + // 2nd: loop the vector to generate code and do other things + + //// 1st: set opTypesAll. There can be many methods about setting opTypes. + // set opTypes: method NO.1 // int depth = 0; // getDepth(expr, depth); @@ -1221,6 +1230,7 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // int middle = (depth - 3) > 1 ? (depth - 3) : 1; // !!! // int middle = depth - 1; // setType(expr, depth, middle); + // set opTypes: method NO.2 // auto order = expr->getOrder(); // vector opTypes; @@ -1237,41 +1247,63 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // } // currentNum = currentNum >> 1; // } - - vector dataTypes = {"DD", "double"}; - int lenDataTypes = dataTypes.size(); - int maxNum = pow(lenDataTypes, lenOp); // for dataTypes = {"ld", "double"}, maxNum = 1 << lenOp; - for(int num = 0; num < maxNum; num++) - { - // set opTypes: method NO.3 - auto currentNum = num; - std::map opTypes; - for(size_t i = 0; i < lenOp; i++) + + // set opTypes: method NO.3 + // int lenDataTypes = dataTypes.size(); + // int maxNum = pow(lenDataTypes, lenOp); // for dataTypes = {"ld", "double"}, maxNum = 1 << lenOp; + // for(int num = 0; num < maxNum; num++) + // { + // auto currentNum = num; + // std::map opTypes; + // for(size_t i = 0; i < lenOp; i++) + // { + // auto id = opSequence[i]; + // auto tmp = currentNum % lenDataTypes; + // opTypes[id] = dataTypes[tmp]; + // currentNum = currentNum / lenDataTypes; + // } + // opTypesAll.push_back(opTypes); + // } + + // set opTypes: method NO.4 + for (size_t i = 0; i < lenOp; i++) + { + mapOpType opTypes; + for(size_t j = 0; j < lenOp; j++) { - auto id = opSequence[i]; - auto tmp = currentNum % lenDataTypes; - opTypes[id] = dataTypes[tmp]; - currentNum = currentNum / lenDataTypes; + auto id = opSequence[j]; + opTypes[id] = dataTypes.at(1); // double } - setType(expr, opTypes); + auto id = opSequence[i]; + opTypes[id] = dataTypes.at(0); // DD + opTypesAll.push_back(opTypes); + } + //// 2nd: loop the vector to generate code and do other things + int currentNum = 0; + for(const auto &opTypes : opTypesAll) + { + setType(expr, opTypes); // init to generate code string directory = "srcTest/" + uniqueLabel + "/"; - string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(num); + string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(currentNum); string fileName = directory + funcName + ".c"; // cout << "\n\nfileName: " << fileName << "\topTypes: "; + ofstream file_clean(fileName, ios_base::out); + ofstream ofs(fileName, ios::app); + // call codegen to generate code + codegen(expr, vars, funcName, ofs); + std::stringstream ss; - for(map::iterator it = opTypes.begin(); it != opTypes.end(); it++) + for(auto it = opTypes.begin(); it != opTypes.end(); it++) { // cout << it->first << " " << it->second << ", "; ss << it->first << " " << it->second << " "; } outputStr.push_back(ss.str()); - ofstream file_clean(fileName, ios_base::out); - ofstream ofs(fileName, ios::app); - /// call shadowValue to generate each step's values of expr. + /// call shadowValue to generate each step's values of expr. (Many points) // varsValue is input values // inputNum is the number of input data // auto epsilonEStr = Shadow::shadowValue(expr, varsValue, inputNum, true, uniqueLabel, funcName); @@ -1297,16 +1329,15 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // } // } - // unsigned long int hjw = 0x3fe6e4f765fd8adaul; - // double hhh = *((double *)(&hjw)); - // vector values(1, hhh); + /// call shadowValue to generate each step's values of expr. (Single point) + // unsigned long int pointHEX = 0x3fe6e4f765fd8adaul; + // double point = *((double *)(&pointHEX)); + // vector values(1, point); // auto varsValue = setVarsValue(vars, values); // fmt::print("varsValue = {}\n", varsValue); // Shadow::shadowValue(expr, varsValue); - // call codegen to generate code - codegen(expr, vars, funcName, ofs); + currentNum++; } - - return maxNum; + return opTypesAll.size(); } diff --git a/src/main.cpp b/src/main.cpp index 538dc90..fa142a0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -306,6 +306,13 @@ int main() } auto varsValue1 = setVarsValue(vars, values1); //// call the shadowValue function to generate the shadow values of the expression. The shadow values are stored into files partly. + // unsigned long int hjw = 0x3fe6e4f765fd8adaul; + // double hhh = *((double *)(&hjw)); + // vector values(2, hhh); + // auto varsValue = setVarsValue(vars, values); + // fmt::print("varsValue = {}\n", varsValue); + // Shadow::shadowValue(originExpr, varsValue); + auto epsilonEStr = Shadow::shadowValue(originExpr, varsValue1, inputNum); for(int i = 0; i < (int)epsilonEStr.size(); i++) { @@ -339,7 +346,7 @@ int main() infos.push_back(infoTmp); } // cout << std::left << setw(4) << "No"; - cout << "\n\n" << std::left << setw(4) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; + cout << "\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; for(int i = 0; i < log2(maxNum); i++) { cout << "step Type "; } @@ -349,7 +356,7 @@ int main() auto &info = infos.at(i); auto &opTypeStr = outputStr.at(i); // cout << std::left << setw(4) << i << opTypeStr << "\n"; - cout << std::left << setw(4) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; + cout << std::left << setw(6) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; } fprintf(stderr, GREEN "ready> " RESET); diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 5dc092b..1fa96a5 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -312,7 +312,7 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve // auto benefitStrNow = fmt::format("{:<3} {:^4} {:<15e}", i, ranks.at(i), benefitAverage.at(i)); benefitStr.push_back(benefitStrNow); } - string sumStr = fmt::format("The avearge sum of the epsilon is {:g}\n", sumAverage); + string sumStr = fmt::format("The average sum of the epsilon is {:g}\n", sumAverage); benefitStr.push_back(sumStr); return benefitStr; -- Gitee From ec14e8ebc381827dd34959603608ee8ef13850b6 Mon Sep 17 00:00:00 2001 From: hjw Date: Sat, 10 Jun 2023 18:00:56 +0800 Subject: [PATCH 27/54] Change dd generate method and fix bugs and do other things --- benchMark.txt | 12 +- detectErrorThreeFPEDParallel.sh | 4 +- detectErrorTwoSingle.sh | 26 ++++ include/funclist.hpp | 3 + src/basic.cpp | 2 + src/funclist.cpp | 15 +++ src/geneCode.cpp | 199 +++++++++++++++++++++++++++---- src/main.cpp | 5 +- src/shadowValue.cpp | 16 +-- srcTest/test2paramSingle.c | 69 +++++++++++ srcTest/test3paramFPEDParallel.c | 4 +- 11 files changed, 310 insertions(+), 45 deletions(-) create mode 100755 detectErrorTwoSingle.sh create mode 100644 srcTest/test2paramSingle.c diff --git a/benchMark.txt b/benchMark.txt index 3e2ea63..3111c7f 100644 --- a/benchMark.txt +++ b/benchMark.txt @@ -31,9 +31,9 @@ test05_nonlin1_test2 1.0/(1+x) verhulst (4*x)/(1+x/1.11) ComplexSinCos 1.0/2.0*sin(r)*(exp(-i) - exp(i)) ComplexSquareRoot 1.0/2.0*sqrt(2.0*(sqrt(x1*x1+x2*x2)+x1)) -doppler1 ((-(1657.0/5.0+3.0/5.0*T))*v)/(((1657.0/5.0+3.0/5.0*T)+u)*((1657.0/5.0+3.0/5.0*T)+u)) -doppler2 ((-(1657.0/5.0+3.0/5.0*T))*v)/(((1657.0/5.0+3.0/5.0*T)+u)*((1657.0/5.0+3.0/5.0*T)+u)) -doppler3 ((-(1657.0/5.0+3.0/5.0*T))*v)/(((1657.0/5.0+3.0/5.0*T)+u)*((1657.0/5.0+3.0/5.0*T)+u)) +doppler1 (-(331.4 + (0.6 * T)) * v) / (((331.4 + (0.6 * T)) + u) * ((331.4 + (0.6 * T)) + u)) +doppler2 (-(331.4 + (0.6 * T)) * v) / (((331.4 + (0.6 * T)) + u) * ((331.4 + (0.6 * T)) + u)) +doppler3 (-(331.4 + (0.6 * T)) * v) / (((331.4 + (0.6 * T)) + u) * ((331.4 + (0.6 * T)) + u)) hypot32 sqrt(x1*x1+x2*x2) i4 sqrtf(x+y*y) i6 sinf(x*y) @@ -42,11 +42,11 @@ NMSEproblem332 tan(x+eps) - tan(x) NMSEproblem335 cos(x+eps) - cos(x) NMSEproblem346 pow((x+1),1/n) - pow(x,1/n) NMSEsection35 exp(a*x) - 1 -polarToCarthesianX radius*cos(3.14159265359/180*theta) -polarToCarthesianY radius*sin(3.14159265359/180*theta) +polarToCarthesianX radius*cos(0.01745329251994444444444444444444*theta) +polarToCarthesianY radius*sin(0.01745329251994444444444444444444*theta) sec4example ((x1*x2) - 1)/((x1*x2)*(x1*x2) - 1) test03_nonlin2 (x+y)/(x - y) -theta atan(x2/x1)*180/3.14159265359 +theta atan(x2/x1)*57.29577951307855 turbine1 (2.0/(r*r)+3.0) - ((3.0 - 2.0*v)*(1.0/8.0)*((w*w)*r*r))/(1.0 - v) - 9.0/2.0 nonlin1 z/(z+1) carbonGas 35000000+(401.0/v)*(1000/v)*(v - 0.0427) - 0.0000000000000000041419509 diff --git a/detectErrorThreeFPEDParallel.sh b/detectErrorThreeFPEDParallel.sh index 8495768..128d51d 100755 --- a/detectErrorThreeFPEDParallel.sh +++ b/detectErrorThreeFPEDParallel.sh @@ -70,7 +70,7 @@ fi testFileName=test3paramFPEDParallel numProcs=32 -echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${prefix} ${middle} ${suffix} ${errfile}" +# echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${prefix} ${middle} ${suffix} ${errfile}" directory="./srcTest"/${uniqueLabel} sourceFile=${prefix}_${suffix} fileNameKernel=${prefix}__${middle}_${suffix} @@ -92,5 +92,5 @@ if [ ${errfile} -eq 1 ]; then cd - > /dev/null fi -echo "end detecting ${uniqueLabel}" +# echo "end detecting ${uniqueLabel}" echo diff --git a/detectErrorTwoSingle.sh b/detectErrorTwoSingle.sh new file mode 100755 index 0000000..7b64aa4 --- /dev/null +++ b/detectErrorTwoSingle.sh @@ -0,0 +1,26 @@ +# Usage: ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${prefix} ${middle} ${suffix} ${errfile} +# set -x + +path=`pwd` +cd ${path} +CC=gcc + +uniqueLabel=${1} # unique number +if [ $# -eq 4 ]; then + suffix=${2} # different version. Eg: herbie daisy origin temp_0_3 final + x0=${3} + x1=${4} +else + echo "detectErrorTwoSingle.sh: Invalid input parameters" + exit +fi +prefix=expr_${uniqueLabel} # expr_${uniqueLabel}. Eg: expr_20221030155958 + +testFileName=test2paramSingle + +directory="./srcTest"/${uniqueLabel} +sourceFile=${prefix}_${suffix} + +${CC} ./srcTest/${testFileName}.c ${directory}/${sourceFile}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -Llibs -lTGen -lmpfr -lm -lqd -o ${testFileName}.exe +./${testFileName}.exe ${x0} ${x1} +rm ${testFileName}.exe diff --git a/include/funclist.hpp b/include/funclist.hpp index 671062b..1b3e09c 100644 --- a/include/funclist.hpp +++ b/include/funclist.hpp @@ -164,6 +164,9 @@ mpfr::mpreal minepow_dd_dd(double *x, double *y); template mpfr::mpreal minesin_dd(double *x); +template +mpfr::mpreal minecos_dd(double *x); + template mpfr::mpreal minetan_dd(double *x); diff --git a/src/basic.cpp b/src/basic.cpp index 0b6a58a..d2a8ac8 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -86,6 +86,8 @@ std::map commonRealCall_map = { std::map singleCall_dd_map = { {"sin_d", minesin_dd}, {"sin_dd", minesin_dd}, + {"cos_d", minecos_dd}, + {"cos_dd", minecos_dd}, {"tan_d", minetan_dd}, {"tan_dd", minetan_dd}, {"exp_d", mineexp_dd}, diff --git a/src/funclist.cpp b/src/funclist.cpp index e33288a..313a1b5 100644 --- a/src/funclist.cpp +++ b/src/funclist.cpp @@ -446,6 +446,7 @@ mpfr::mpreal minepow_dd_dd(double *x1Ptr, double *x2Ptr) result = tmp + y[1]; return result; } + template mpfr::mpreal minesin_dd(double *x) { @@ -458,6 +459,18 @@ mpfr::mpreal minesin_dd(double *x) return result; } +template +mpfr::mpreal minecos_dd(double *x) +{ + double y[2]; + c_dd_cos(x, y); + T tmp; + mpfr::mpreal result; + tmp = y[0]; + result = tmp + y[1]; + return result; +} + template mpfr::mpreal minetan_dd(double *x) { @@ -547,6 +560,8 @@ template mpfr::mpreal minepow_dd_dd(double *x, double *y); // single math function template mpfr::mpreal minesin_dd(double *x); template mpfr::mpreal minesin_dd(double *x); +template mpfr::mpreal minecos_dd(double *x); +template mpfr::mpreal minecos_dd(double *x); template mpfr::mpreal minetan_dd(double *x); template mpfr::mpreal minetan_dd(double *x); template mpfr::mpreal mineexp_dd(double *x); diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 1409eab..fc4cd11 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -1031,6 +1031,154 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) paramOrders.push_back(paramOrder); } + // to find the highest type of the parameters + bool hasDDparam = false; + bool hasLDparam = false; + for(const auto& paramOpType : paramOpTypes) + { + if(paramOpType == "DD") + { + hasDDparam = true; + break; + } + } + if(hasDDparam == false) + { + for(const auto& paramOpType : paramOpTypes) + { + if(paramOpType == "ld") + { + hasLDparam = true; + break; + } + else if(paramOpType != "double") // the type of param's op is not in {double, ld, DD} + { + fprintf(stderr, "ERROR: Unknown paramOpType %s\n", paramOpType.c_str()); + exit(EXIT_FAILURE); + } + } + } + + // set all the parameters to the highest type and set the callee according to the highest type + if(hasDDparam == true) + { + // paramOpType must be DD or ld or double + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + auto ¶mOpType = paramOpTypes.at(i); + ofs << "\t" << "double p" << paramOrders.at(i) << "[2];\n"; + if(paramOpType == "DD") + { + ofs << "\t" << "p" << paramOrders.at(i) << "[0] = tmp" << paramOrders.at(i) << "[0];\n"; + ofs << "\t" << "p" << paramOrders.at(i) << "[1] = tmp" << paramOrders.at(i) << "[1];\n"; + } + else if(paramOpType == "ld") + { + ofs << "\t" << "p" << paramOrders.at(i) << "[0] = tmp" << paramOrders.at(i) << ";\n"; + ofs << "\t" << "p" << paramOrders.at(i) << "[1] = tmp" << paramOrders.at(i) << " - p" << paramOrders.at(i) << "[0];\n"; + } + else // must be double + { + ofs << "\t" << "p" << paramOrders.at(i) << "[0] = tmp" << paramOrders.at(i) << ";\n"; + ofs << "\t" << "p" << paramOrders.at(i) << "[1] = 0\n"; + } + } + + ofs << "\t" << "double tmpCallResult" << order << "[2];\n"; + auto it = callMap.find(callee); + auto callStr = it->second; + ofs << "\t" << callStr << "("; + for(size_t i = 0; i < paramOrders.size(); i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "tmpCallResult" << order; + ofs << ");\n"; + + if(opType == "DD") + { + ofs << "\t" << "double tmp" << order << "[2];\n"; + ofs << "\t" << "tmp" << order << "[0] = tmpCallResult" << order << "[0];\n"; + ofs << "\t" << "tmp" << order << "[1] = tmpCallResult" << order << "[1];\n"; + } + else if(opType == "ld") + { + ofs << "\t" << "long double tmp" << order << ";\n"; + ofs << "\t" << "tmp" << order << " = tmpCallResult" << order << "[0];\n"; + ofs << "\t" << "tmp" << order << "+= tmpCallResult" << order << "[1];\n"; + + } + else + { + ofs << "\t" << "double tmp" << order << ";\n"; + ofs << "\t" << "tmp" << order << " = tmpCallResult" << order << "[0];\n"; + ofs << "\t" << "tmp" << order << " += tmpCallResult" << order << "[1];\n"; + } + } + else if(hasLDparam == true) + { + // paramOpType must be ld or double + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + ofs << "\t" << "long double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + + ofs << "\t" << "long double tmpCallResult" << order << " = " << callee << "("; + for(size_t i = 0; i < paramOrders.size() - 1; i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "p" << paramOrders.back(); + ofs << ");\n"; + + if(opType == "DD") + { + ofs << "\t" << "double tmp" << order << "[2];\n"; + ofs << "\t" << "tmp" << order << "[0] = tmpCallResult" << order << ";\n"; + ofs << "\t" << "tmp" << order << "[1] = tmpCallResult" << order << " - tmp" << order << ";\n"; + } + else if(opType == "ld") + { + ofs << "\t" << "long double tmp" << order << " = tmpCallResult" << order << ";\n"; + } + else + { + ofs << "\t" << "double tmp" << order << " = tmpCallResult" << order << ";\n"; + } + } + else + { + // paramOpType must be double + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + ofs << "\t" << "double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + + ofs << "\t" << "double tmpCallResult" << order << " = " << callee << "("; + for(size_t i = 0; i < paramOrders.size() - 1; i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "p" << paramOrders.back(); + ofs << ");\n"; + + if(opType == "DD") + { + ofs << "\t" << "double tmp" << order << "[2];\n"; + ofs << "\t" << "tmp" << order << "[0] = tmpCallResult" << order << ";\n"; + ofs << "\t" << "tmp" << order << "[1] = 0;\n"; + } + else if(opType == "ld") + { + ofs << "\t" << "long double tmp" << order << " = tmpCallResult" << order << ";\n"; + } + else + { + ofs << "\t" << "double tmp" << order << " = tmpCallResult" << order << ";\n"; + } + } + + /* if(opType == "double") { for(size_t i = 0; i < paramOpTypes.size(); i++) @@ -1139,6 +1287,7 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) fprintf(stderr, "ERROR: Unknown opType %s\n", opType.c_str()); exit(EXIT_FAILURE); } + */ return order; } @@ -1249,36 +1398,36 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // } // set opTypes: method NO.3 - // int lenDataTypes = dataTypes.size(); - // int maxNum = pow(lenDataTypes, lenOp); // for dataTypes = {"ld", "double"}, maxNum = 1 << lenOp; - // for(int num = 0; num < maxNum; num++) - // { - // auto currentNum = num; - // std::map opTypes; - // for(size_t i = 0; i < lenOp; i++) - // { - // auto id = opSequence[i]; - // auto tmp = currentNum % lenDataTypes; - // opTypes[id] = dataTypes[tmp]; - // currentNum = currentNum / lenDataTypes; - // } - // opTypesAll.push_back(opTypes); - // } - - // set opTypes: method NO.4 - for (size_t i = 0; i < lenOp; i++) + int lenDataTypes = dataTypes.size(); + int maxNum = pow(lenDataTypes, lenOp); // for dataTypes = {"ld", "double"}, maxNum = 1 << lenOp; + for(int num = 0; num < maxNum; num++) { - mapOpType opTypes; - for(size_t j = 0; j < lenOp; j++) + auto currentNum = num; + std::map opTypes; + for(size_t i = 0; i < lenOp; i++) { - auto id = opSequence[j]; - opTypes[id] = dataTypes.at(1); // double + auto id = opSequence[i]; + auto tmp = currentNum % lenDataTypes; + opTypes[id] = dataTypes[tmp]; + currentNum = currentNum / lenDataTypes; } - auto id = opSequence[i]; - opTypes[id] = dataTypes.at(0); // DD opTypesAll.push_back(opTypes); } + // set opTypes: method NO.4 + // for (size_t i = 0; i < lenOp; i++) + // { + // mapOpType opTypes; + // for(size_t j = 0; j < lenOp; j++) + // { + // auto id = opSequence[j]; + // opTypes[id] = dataTypes.at(1); // double + // } + // auto id = opSequence[i]; + // opTypes[id] = dataTypes.at(0); // DD + // opTypesAll.push_back(opTypes); + // } + //// 2nd: loop the vector to generate code and do other things int currentNum = 0; for(const auto &opTypes : opTypesAll) @@ -1313,7 +1462,7 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // auto &epsilonEStrNow = epsilonEStr.at(i); // if(*it == i) // { - // if(opTypes[*it] == "DD") + // if(opTypes.at(i) == "DD") // { // cout << BOLDBRIGHTRED << epsilonEStrNow << "\n" << RESET; // } diff --git a/src/main.cpp b/src/main.cpp index fa142a0..181553f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -281,11 +281,12 @@ int main() auto exprDaisy = geneDaisyCode(uniqueLabel); auto funcNameMpfr = geneMpfrCode(inputStr, uniqueLabel, vars); printExpr(originExpr, "the origin expr: "); + std::cout << "NO. step\n"; showOrder(originExpr); // set calculation order for originExpr auto opSequence = setOrder(originExpr); - fmt::print("\noperation's Sequence: {}\nthe number of sequence: {}, the number of mix-prec version: {}\n", opSequence, opSequence.size(), 1 << opSequence.size()); + fmt::print("\noperation's Sequence: {}\nthe number of sequence: {}, the max number of mix-prec version: {}\n", opSequence, opSequence.size(), 1 << opSequence.size()); //// generate input data for shadow value vector values1; @@ -347,7 +348,7 @@ int main() } // cout << std::left << setw(4) << "No"; cout << "\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; - for(int i = 0; i < log2(maxNum); i++) { + for(size_t i = 0; i < opSequence.size(); i++) { cout << "step Type "; } cout << "\n"; diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 1fa96a5..1eec7ef 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -242,13 +242,13 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve { epsilonE.at(i)[j] = errorValues.at(i)[j] * conditionNumbersOp.at(condNumOrder.at(i))[j]; epsilonEAverage.at(i) += epsilonE.at(i)[j]; - // errorValuesAverage.at(i) += errorValues.at(i)[j]; - // conditionNumbersOpAverage.at(i) += conditionNumbersOp.at(i)[j]; + errorValuesAverage.at(i) += errorValues.at(i)[j]; + conditionNumbersOpAverage.at(i) += conditionNumbersOp.at(i)[j]; sumOfAll.at(j) += epsilonE.at(i)[j]; } epsilonEAverage.at(i) /= length; - // errorValuesAverage.at(i) /= length; - // conditionNumbersOpAverage.at(i) /= length; + errorValuesAverage.at(i) /= length; + conditionNumbersOpAverage.at(i) /= length; } // auto sum = std::accumulate(epsilonEAverage.begin(), epsilonEAverage.end(), 0.0); auto sum = std::accumulate(sumOfAll.begin(), sumOfAll.end(), 0.0); @@ -298,17 +298,17 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve // print // fmt::print("the average of benefit are: {}", benefitAverage); auto ranks = getRanks(benefitAverage, false); - fmt::print("{:^4} {:<15}\n", "rank", "benefit"); + // fmt::print("{:^4} {:<15}\n", "rank", "benefit"); // fmt::print("{:<3} {:^4} {:<15}\n", "NO.", "rank", "benefit"); - // fmt::print("{:<3} {:<4} {:<15} {:<15} {:<15} {:<15}\n", "No.", "rank", "errValAver", "condNumOpAver", "epsilonEAver", "benefit"); + fmt::print("{:<3} {:<4} {:<15} {:<15} {:<15} {:<15}\n", "No.", "rank", "errValAver", "condNumOpAver", "epsilonEAver", "benefit"); vector benefitStr; for(size_t i = 0; i < benefitAverage.size(); i++) { // fmt::print("{} {} {}\n", benefitAverage.at(i), ranks.at(i)); // fmt::print("rank {}: errorValuesAverage = {} conditionNumbersOpAverage = {} benefitAverage = {}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), benefitAverage.at(i)); // fmt::print("{}: {:<15e} {:<15e} {:<15e}\n", ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), benefitAverage.at(i)); - // auto benefitStrNow = fmt::format("{:<3} {:<4} {:<15e} {:<15e} {:<15e} {:<15e}", i, ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i), benefitAverage.at(i)); - auto benefitStrNow = fmt::format("{:^4} {:<15e}", ranks.at(i), benefitAverage.at(i)); + auto benefitStrNow = fmt::format("{:<3} {:<4} {:<15e} {:<15e} {:<15e} {:<15e}", i, ranks.at(i), errorValuesAverage.at(i), conditionNumbersOpAverage.at(i), epsilonEAverage.at(i), benefitAverage.at(i)); + // auto benefitStrNow = fmt::format("{:^4} {:<15e}", ranks.at(i), benefitAverage.at(i)); // auto benefitStrNow = fmt::format("{:<3} {:^4} {:<15e}", i, ranks.at(i), benefitAverage.at(i)); benefitStr.push_back(benefitStrNow); } diff --git a/srcTest/test2paramSingle.c b/srcTest/test2paramSingle.c new file mode 100644 index 0000000..8b9072f --- /dev/null +++ b/srcTest/test2paramSingle.c @@ -0,0 +1,69 @@ +#include "common.h" + +#ifndef SUFFIX +#define SUFFIX orgin +#endif +#ifndef EXPRESSION +#define EXPRESSION NMSEproblem334 +#endif + +#define EXPRESSIONMINE ADDSUFFIX(EXPRESSION, SUFFIX) +#define SUFFIX1 mpfr +#define EXPRESSIONMPFR ADDSUFFIX(EXPRESSION, SUFFIX1) + +double EXPRESSIONMPFR(double, double, mpfr_t); +double EXPRESSIONMINE(double, double); + +int computeOrcle2param(double x0, double x1, mpfr_t orcle) +{ + return EXPRESSIONMPFR(x0, x1, orcle); +} + +int computeResult2param(double x0, double x1, mpfr_t mpfrResult) +{ + int status = 1; + + double result = EXPRESSIONMINE(x0, x1); + mpfr_set_d(mpfrResult, result, MPFR_RNDN); + + return status; +} + +void test2param(double x0, double x1) +{ + mpfr_t mpfrOrcle, mpfrResult; + mpfr_inits2(PRECISION, mpfrOrcle, mpfrResult, (mpfr_ptr) 0); + + computeResult2param(x0, x1, mpfrResult); + computeOrcle2param(x0, x1, mpfrOrcle); + + double reUlp = computeUlpDiff(mpfrOrcle, mpfrResult); + DL orcle, result; + orcle.d = mpfr_get_d(mpfrOrcle, MPFR_RNDN); + result.d = mpfr_get_d(mpfrResult, MPFR_RNDN); + printf("%8lg %8lg %8lg\n", result.d, orcle.d, reUlp); + printf("0x%016lx 0x%016lx %8lg\n", result.l, orcle.l, reUlp); + + // clear + mpfr_clears(mpfrOrcle, mpfrResult, (mpfr_ptr) 0); +} + +int main(int argc, char **argv) +{ + DL x0, x1; + + if (argc == 3) + { + x0.l = strtoul(argv[1], NULL, 16); + x1.l = strtoul(argv[2], NULL, 16); + printf("x0 = 0x%016lx\t", x0.l); + printf("x1 = 0x%016lx\n", x1.l); + } + else + { + printf("Wrong number of arguments.\n"); + exit(EXIT_FAILURE); + } + test2param(x0.d, x1.d); + return 0; +} diff --git a/srcTest/test3paramFPEDParallel.c b/srcTest/test3paramFPEDParallel.c index 80f58e5..13b859d 100644 --- a/srcTest/test3paramFPEDParallel.c +++ b/srcTest/test3paramFPEDParallel.c @@ -288,8 +288,8 @@ int main(int argc, char **argv) { printf("Error opening file %s.\n", fileNameErr); exit(0); } - printf("average ulp\tmax ulp\n"); - printf("%.16le\t%.16le\n", aveError, maxError); + // printf("average ulp\tmax ulp\n"); + // printf("%.16le\t%.16le\n", aveError, maxError); // printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxInputX1 = 0x%016lx %lg, maxInputX2 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxInputX1.l, maxInputX1.d, maxInputX2.l, maxInputX2.d, maxError); fprintf(fErr, "average ulp\tmax ulp\n"); fprintf(fErr, "%.16le\t%.16le\n", aveError, maxError); -- Gitee From 8162287296ebaa1e90000ddb062e34b071e40c3e Mon Sep 17 00:00:00 2001 From: hjw Date: Mon, 26 Jun 2023 22:27:18 +0800 Subject: [PATCH 28/54] codegenKernel: improve dd method --- src/geneCode.cpp | 142 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 109 insertions(+), 33 deletions(-) diff --git a/src/geneCode.cpp b/src/geneCode.cpp index fc4cd11..eff521c 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -1059,7 +1059,9 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) } } - // set all the parameters to the highest type and set the callee according to the highest type + // set all the parameters to the highest type + // set the callee according to the highest type and opType + // set the return value type according to the opType if(hasDDparam == true) { // paramOpType must be DD or ld or double @@ -1080,7 +1082,7 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) else // must be double { ofs << "\t" << "p" << paramOrders.at(i) << "[0] = tmp" << paramOrders.at(i) << ";\n"; - ofs << "\t" << "p" << paramOrders.at(i) << "[1] = 0\n"; + ofs << "\t" << "p" << paramOrders.at(i) << "[1] = 0;\n"; } } @@ -1117,66 +1119,141 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) } else if(hasLDparam == true) { - // paramOpType must be ld or double - for(size_t i = 0; i < paramOpTypes.size(); i++) + if(opType == "DD") { - ofs << "\t" << "long double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; - } + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + auto ¶mOpType = paramOpTypes.at(i); + ofs << "\t" << "double p" << paramOrders.at(i) << "[2];\n"; + if(paramOpType == "ld") + { + ofs << "\t" << "p" << paramOrders.at(i) << "[0] = tmp" << paramOrders.at(i) << ";\n"; + ofs << "\t" << "p" << paramOrders.at(i) << "[1] = tmp" << paramOrders.at(i) << " - p" << paramOrders.at(i) << "[0];\n"; + } + else // must be double + { + ofs << "\t" << "p" << paramOrders.at(i) << "[0] = tmp" << paramOrders.at(i) << ";\n"; + ofs << "\t" << "p" << paramOrders.at(i) << "[1] = 0;\n"; + } + } - ofs << "\t" << "long double tmpCallResult" << order << " = " << callee << "("; - for(size_t i = 0; i < paramOrders.size() - 1; i++) - { - ofs << "p" << paramOrders.at(i) << ", "; - } - ofs << "p" << paramOrders.back(); - ofs << ");\n"; + ofs << "\t" << "double tmpCallResult" << order << "[2];\n"; + auto it = callMap.find(callee); + auto callStr = it->second; + ofs << "\t" << callStr << "("; + for(size_t i = 0; i < paramOrders.size(); i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "tmpCallResult" << order; + ofs << ");\n"; - if(opType == "DD") - { ofs << "\t" << "double tmp" << order << "[2];\n"; - ofs << "\t" << "tmp" << order << "[0] = tmpCallResult" << order << ";\n"; - ofs << "\t" << "tmp" << order << "[1] = tmpCallResult" << order << " - tmp" << order << ";\n"; + ofs << "\t" << "tmp" << order << "[0] = tmpCallResult" << order << "[0];\n"; + ofs << "\t" << "tmp" << order << "[1] = tmpCallResult" << order << "[1];\n"; } else if(opType == "ld") { + // paramOpType must be ld or double + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + ofs << "\t" << "long double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + + ofs << "\t" << "long double tmpCallResult" << order << " = " << callee << "("; + for(size_t i = 0; i < paramOrders.size() - 1; i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "p" << paramOrders.back(); + ofs << ");\n"; + ofs << "\t" << "long double tmp" << order << " = tmpCallResult" << order << ";\n"; } else { + // paramOpType must be ld or double + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + ofs << "\t" << "long double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + + ofs << "\t" << "long double tmpCallResult" << order << " = " << callee << "("; + for(size_t i = 0; i < paramOrders.size() - 1; i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "p" << paramOrders.back(); + ofs << ");\n"; + ofs << "\t" << "double tmp" << order << " = tmpCallResult" << order << ";\n"; } } else { - // paramOpType must be double - for(size_t i = 0; i < paramOpTypes.size(); i++) + if(opType == "DD") { - ofs << "\t" << "double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; - } + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + auto ¶mOpType = paramOpTypes.at(i); + ofs << "\t" << "double p" << paramOrders.at(i) << "[2];\n"; + ofs << "\t" << "p" << paramOrders.at(i) << "[0] = tmp" << paramOrders.at(i) << ";\n"; + ofs << "\t" << "p" << paramOrders.at(i) << "[1] = 0;\n"; + } - ofs << "\t" << "double tmpCallResult" << order << " = " << callee << "("; - for(size_t i = 0; i < paramOrders.size() - 1; i++) - { - ofs << "p" << paramOrders.at(i) << ", "; - } - ofs << "p" << paramOrders.back(); - ofs << ");\n"; + ofs << "\t" << "double tmpCallResult" << order << "[2];\n"; + auto it = callMap.find(callee); + auto callStr = it->second; + ofs << "\t" << callStr << "("; + for(size_t i = 0; i < paramOrders.size(); i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "tmpCallResult" << order; + ofs << ");\n"; - if(opType == "DD") - { ofs << "\t" << "double tmp" << order << "[2];\n"; - ofs << "\t" << "tmp" << order << "[0] = tmpCallResult" << order << ";\n"; - ofs << "\t" << "tmp" << order << "[1] = 0;\n"; + ofs << "\t" << "tmp" << order << "[0] = tmpCallResult" << order << "[0];\n"; + ofs << "\t" << "tmp" << order << "[1] = tmpCallResult" << order << "[1];\n"; } else if(opType == "ld") { + // paramOpType must be double + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + ofs << "\t" << "long double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + + ofs << "\t" << "long double tmpCallResult" << order << " = " << callee << "("; // 应该可以根据函数参数类型,直接调用到ld版本吧 + for(size_t i = 0; i < paramOrders.size() - 1; i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "p" << paramOrders.back(); + ofs << ");\n"; + ofs << "\t" << "long double tmp" << order << " = tmpCallResult" << order << ";\n"; } else { + // paramOpType must be ld or double + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + ofs << "\t" << "double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + + ofs << "\t" << "double tmpCallResult" << order << " = " << callee << "("; + for(size_t i = 0; i < paramOrders.size() - 1; i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "p" << paramOrders.back(); + ofs << ");\n"; + ofs << "\t" << "double tmp" << order << " = tmpCallResult" << order << ";\n"; } } + /* if(opType == "double") @@ -1288,7 +1365,6 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) exit(EXIT_FAILURE); } */ - return order; } else if(type == "Binary") -- Gitee From 3e91a0da10bb682ab218f711d12c90b146b0071b Mon Sep 17 00:00:00 2001 From: hjw Date: Sat, 8 Jul 2023 09:34:53 +0800 Subject: [PATCH 29/54] Support performance test and setting dataTypes by cin --- include/basic.hpp | 2 ++ include/geneCode.hpp | 2 +- src/basic.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/geneCode.cpp | 3 +-- src/main.cpp | 13 ++++++++++--- 5 files changed, 55 insertions(+), 6 deletions(-) diff --git a/include/basic.hpp b/include/basic.hpp index 812f3a0..367d74b 100644 --- a/include/basic.hpp +++ b/include/basic.hpp @@ -314,4 +314,6 @@ void write_to_file_wrapper(string uniqueLabel, string exprOriginBest, int dimens template std::map setVarsValue(const vector &vars, const vector &values); +void setDataTypes(vector &dataTypes); + #endif \ No newline at end of file diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 57a02a8..bff8172 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -45,6 +45,6 @@ vector setOrder(ast_ptr &expr); int showOrder(ast_ptr &expr); -int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map values, size_t inputNum, vector &outputStr); +int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map values, size_t inputNum, vector &outputStr, vector dataTypes = {"DD", "double"}); #endif \ No newline at end of file diff --git a/src/basic.cpp b/src/basic.cpp index d2a8ac8..c8fc675 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -10,6 +10,7 @@ #include "mpreal.h" using std::cerr; +using std::cin; using std::cout; using std::endl; using std::string; @@ -987,3 +988,43 @@ std::map setVarsValue(const vector &vars, const vector &va template std::map setVarsValue(const vector &vars, const vector &values); template std::map setVarsValue(const vector &vars, const vector &values); + +void setDataTypes(vector &dataTypes) +{ + cout << "please input the mixed-precision types. if input Enter, then set DD & double by default.\n"; + string tmpDataTypes; + cin >> tmpDataTypes; // TODO: improve the input method + cin.clear(); // clear the error signal + cin.ignore(std::numeric_limits::max(),'\n'); // clear the current line in input buffer + if (tmpDataTypes != "") + { + dataTypes.clear(); + if(tmpDataTypes == "0") + { + dataTypes.push_back("ld"); + dataTypes.push_back("double"); + } + else if(tmpDataTypes == "1") + { + dataTypes.push_back("DD"); + dataTypes.push_back("double"); + } + else if(tmpDataTypes == "2") + { + dataTypes.push_back("DD"); + dataTypes.push_back("ld"); + } + else if(tmpDataTypes == "3") + { + dataTypes.push_back("DD"); + dataTypes.push_back("ld"); + dataTypes.push_back("double"); + } + else + { + cout << "ERROR: Unknown input. please enter 0~4 to to indicate a mixed-precision configuration"; + exit(EXIT_FAILURE); + } + } + fmt::print("mix precision dataTypes: {}", dataTypes); +} \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index eff521c..d0b05d3 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -1433,14 +1433,13 @@ void codegen(ast_ptr &expr, vector &vars, const string funcName, ofstrea // Note: Each operator node has two states, double or double-double. if there are n node in that expression, there are 2^n states. // Generate double-double implementations in all states and return the number of generated codes -int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map varsValue, size_t inputNum, vector &outputStr) +int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail, std::map varsValue, size_t inputNum, vector &outputStr, vector dataTypes) { // init auto opSequence = setOrder(expr); auto lenOp = opSequence.size(); typedef std::map mapOpType; vector opTypesAll; - vector dataTypes = {"DD", "double"}; // for these expressions winth huge number mix-precision versions. // 1st: set the opTypes vector diff --git a/src/main.cpp b/src/main.cpp index 181553f..7a9a022 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -324,7 +324,9 @@ int main() //// support DD vector outputStr; - auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum, outputStr); + vector dataTypes = {"DD", "double"}; + setDataTypes(dataTypes); + auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum, outputStr, dataTypes); //// test DD's error vector startNowIdxs(dimension, 0); vector startOriginIntervals; @@ -340,14 +342,19 @@ int main() } // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); vector infos; + vector perfValues; for(int i = 0; i < maxNum; i++) { cout << "\n\n-test error-" << i << "\n"; string tmp = "dd_" + std::to_string(i); auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + auto tmpPerformance = testPerformance(uniqueLabel, tmp, intervals); + cout << tmp << " performance: " << tmpPerformance << "\n\n"; infos.push_back(infoTmp); + perfValues.push_back(tmpPerformance); } // cout << std::left << setw(4) << "No"; - cout << "\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; + // cout << "\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; + cout << "\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "performamce" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; for(size_t i = 0; i < opSequence.size(); i++) { cout << "step Type "; } @@ -357,7 +364,7 @@ int main() auto &info = infos.at(i); auto &opTypeStr = outputStr.at(i); // cout << std::left << setw(4) << i << opTypeStr << "\n"; - cout << std::left << setw(6) << i << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; + cout << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; } fprintf(stderr, GREEN "ready> " RESET); -- Gitee From 38de3fa7d9db98d97a3fd9db429cf1d9903e5ce6 Mon Sep 17 00:00:00 2001 From: hjw Date: Sun, 9 Jul 2023 17:55:06 +0800 Subject: [PATCH 30/54] computeEpsilonE: support n-step mixed-precision --- include/basic.hpp | 2 ++ include/geneCode.hpp | 2 ++ src/basic.cpp | 30 ++++++++++++++++++++++++++++++ src/geneCode.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 13 +++++++------ src/shadowValue.cpp | 40 +++++++++++++++++++++++++++++++++++++--- 6 files changed, 118 insertions(+), 9 deletions(-) diff --git a/include/basic.hpp b/include/basic.hpp index 367d74b..3187845 100644 --- a/include/basic.hpp +++ b/include/basic.hpp @@ -304,6 +304,8 @@ std::vector geneRandom(size_t start, size_t end); vector> combination(const int num, const vector& indexs); +vector> combinationNew(const int num, const vector& indexs); + size_t combination(size_t k, size_t n); void write_to_file(const string &uniqueLabel, const string &exprOriginBest, const vector &numIntervalsSoloBefore, const vector &numIntervalsSoloAfter, const std::vector thresholds, const std::vector &data, const std::string &filename); diff --git a/include/geneCode.hpp b/include/geneCode.hpp index bff8172..41e5da3 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -41,6 +41,8 @@ string geneFinalCode(string exprStr, string uniqueLabel, vector exprIn void getDepth(ast_ptr &expr, int &depth); +void getOrders(const ast_ptr &expr, vector &opOrder); + vector setOrder(ast_ptr &expr); int showOrder(ast_ptr &expr); diff --git a/src/basic.cpp b/src/basic.cpp index c8fc675..a71e469 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -854,6 +854,36 @@ vector> combination(const int num, const vector &indexs) return set; } +// add at 20230709, update from the origin combination +vector> combinationNew(const int num, const vector &indexs) +{ + vector> set; + if(num > (int)indexs.size()) + return set; + + vector elements; + elements.resize(indexs.size()); + for(int i = 0; i < num; i++) + { + elements.at(i) = 1; + } + + do + { + vector currentCombination; + for(size_t i = 0; i < elements.size(); ++i) + { + if(elements[i]) + { + currentCombination.push_back(indexs[i]); + } + } + set.push_back(currentCombination); + } while(prev_permutation(elements.begin(), elements.end())); + + return set; +} + inline unsigned int factorial(unsigned int value) { unsigned int local_value = value; diff --git a/src/geneCode.cpp b/src/geneCode.cpp index d0b05d3..5daa0a4 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -824,6 +824,46 @@ void setType(ast_ptr &expr, map opTypes) } } +void getOrders(const ast_ptr &expr, vector &opOrder) +{ + auto type = expr->type(); + if(type == "Number") + { + ; + } + else if(type == "Variable") + { + ; + } + else if(type == "Call") + { + CallExprAST *callPtr = dynamic_cast(expr.get()); + auto &args = callPtr->getArgs(); + vector paramOrders; + for(auto& arg : args) + { + getOrders(arg, opOrder); + } + auto orderNow = expr->getOrder(); + opOrder.push_back(orderNow); + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + getOrders(lhs, opOrder); + getOrders(rhs, opOrder); + auto orderNow = expr->getOrder(); + opOrder.push_back(orderNow); + } + else + { + fprintf(stderr, "ERROR: %s : line %d: unknown type %s\n", __func__, __LINE__, type.c_str()); + exit(EXIT_FAILURE); + } +} + void setOrdersKernel(ast_ptr &expr, int &orderNow, vector &opOrder) { auto type = expr->type(); diff --git a/src/main.cpp b/src/main.cpp index 7a9a022..66d811f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -325,7 +325,7 @@ int main() //// support DD vector outputStr; vector dataTypes = {"DD", "double"}; - setDataTypes(dataTypes); + // setDataTypes(dataTypes); auto maxNum = codegenWrapper(originExpr, vars, uniqueLabel, "dd", varsValue1, inputNum, outputStr, dataTypes); //// test DD's error vector startNowIdxs(dimension, 0); @@ -344,12 +344,12 @@ int main() vector infos; vector perfValues; for(int i = 0; i < maxNum; i++) { - cout << "\n\n-test error-" << i << "\n"; + // cout << "\n\n-test error-" << i << "\n"; string tmp = "dd_" + std::to_string(i); - auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + // auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); auto tmpPerformance = testPerformance(uniqueLabel, tmp, intervals); cout << tmp << " performance: " << tmpPerformance << "\n\n"; - infos.push_back(infoTmp); + // infos.push_back(infoTmp); perfValues.push_back(tmpPerformance); } // cout << std::left << setw(4) << "No"; @@ -361,10 +361,11 @@ int main() cout << "\n"; for(int i = 0; i < maxNum; i++) { - auto &info = infos.at(i); + // auto &info = infos.at(i); auto &opTypeStr = outputStr.at(i); // cout << std::left << setw(4) << i << opTypeStr << "\n"; - cout << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; + cout << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << "\n"; + // cout << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; } fprintf(stderr, GREEN "ready> " RESET); diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 1eec7ef..8432923 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -10,6 +10,7 @@ #include "shadowValue.hpp" #include "funclist.hpp" #include "errorDetect.hpp" +#include "geneCode.hpp" using std::string; @@ -195,7 +196,7 @@ vector getRanks(const vector &v, bool descending = true) } template -vector computeEpsilonE(vector &benefit, vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const int length = 1) +vector computeEpsilonE(vector &benefit, vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const vector &opSequence, const int length = 1) { constexpr bool TisDouble = (std::is_same::value); constexpr bool TisDoublePointer = (std::is_same::value); @@ -254,7 +255,8 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve auto sum = std::accumulate(sumOfAll.begin(), sumOfAll.end(), 0.0); auto sumAverage = fabs(sum / length); - // compute benefit + // compute benefit for 1-step + // notes: benefit is the predicted error value after mixed-precision tuning. vector minBenefit(length, std::numeric_limits::infinity()); vector minBenefitIdx(length, std::numeric_limits::infinity()); vector benefitAverage(errorValues.size(), 0.0); @@ -315,6 +317,35 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve string sumStr = fmt::format("The average sum of the epsilon is {:g}\n", sumAverage); benefitStr.push_back(sumStr); + // compute n-step mixed-precision + fmt::print("opSequence (remove the last step) for n-step: {}\n", opSequence); + for(size_t numStep = 1; numStep < opSequence.size(); numStep++) + { + auto combResults = combinationNew(numStep, opSequence); + fmt::print("for {}-step, combResult = {}\n", numStep, combResults); + vector benefitAverage; + vector tmp(length, 1); + for(const auto &combResult : combResults) + { + double benefitTmp = 0.0; + for(int j = 0; j < length; j++) + { + tmp.at(j) = sumOfAll.at(j); + for(size_t i = 0; i < combResult.size(); i++) + { + auto stepIdx = combResult.at(i); + tmp.at(j) = tmp.at(j) - epsilonE.at(stepIdx)[j]; + } + tmp.at(j) = fabs(tmp.at(j)); + benefitTmp += tmp.at(j); + } + benefitTmp /= length; + benefitAverage.push_back(benefitTmp); + } + auto ranks = getRanks(benefitAverage, false); + fmt::print("for {}-step, benefitAverage = {}\n", numStep, benefitAverage); + fmt::print("for {}-step, ranks = {}\n", numStep, ranks); + } return benefitStr; } else @@ -1351,7 +1382,10 @@ vector shadowValue(const ast_ptr &expr, const std::map &varsV int IDfather = conditionNumbersOp.size() - 1; int IDnow = conditionNumbers.size() - 1; computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); - auto epsilonEStr = computeEpsilonE(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, length); + vector opSequence; + getOrders(expr, opSequence); + opSequence.pop_back(); + auto epsilonEStr = computeEpsilonE(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, opSequence, length); // shadowValuePrint(funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, conditionNumbersOp, epsilonE, varsValue, length, ifUnique, uniqueLabel, funcName); return epsilonEStr; -- Gitee From b07d3ef10e1d2099dfd13a436753c1da9f572658 Mon Sep 17 00:00:00 2001 From: hjw Date: Sun, 9 Jul 2023 21:46:23 +0800 Subject: [PATCH 31/54] Support write mix precision log to file. --- src/main.cpp | 18 +++++++++++++++++- src/shadowValue.cpp | 19 ++++++++++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 66d811f..e528eb1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -315,11 +315,27 @@ int main() // Shadow::shadowValue(originExpr, varsValue); auto epsilonEStr = Shadow::shadowValue(originExpr, varsValue1, inputNum); + string tmpStr; + tmpStr = fmt::format("expr: {}\n", exprOrigin); + epsilonEStr.insert(epsilonEStr.begin(), tmpStr); + tmpStr = fmt::format("uniqueLabel: {}\n", uniqueLabel); + epsilonEStr.insert(epsilonEStr.begin(), tmpStr); + std::ofstream outputFile; + outputFile.open("mixPrec.log", std::ios::out | std::ios::app); + if (outputFile.is_open() == false) + { + exit(EXIT_FAILURE); + } for(int i = 0; i < (int)epsilonEStr.size(); i++) { auto &epsilonEStrNow = epsilonEStr.at(i); - cout << epsilonEStrNow << "\n"; + cout << epsilonEStrNow; + outputFile << epsilonEStrNow; } + outputFile << "\n"; + outputFile.close(); + fprintf(stderr, GREEN "ready> " RESET); + continue; //// TODO: free values1 //// support DD diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 8432923..2feba95 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -302,7 +302,7 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve auto ranks = getRanks(benefitAverage, false); // fmt::print("{:^4} {:<15}\n", "rank", "benefit"); // fmt::print("{:<3} {:^4} {:<15}\n", "NO.", "rank", "benefit"); - fmt::print("{:<3} {:<4} {:<15} {:<15} {:<15} {:<15}\n", "No.", "rank", "errValAver", "condNumOpAver", "epsilonEAver", "benefit"); + // fmt::print("{:<3} {:<4} {:<15} {:<15} {:<15} {:<15}\n", "No.", "rank", "errValAver", "condNumOpAver", "epsilonEAver", "benefit"); vector benefitStr; for(size_t i = 0; i < benefitAverage.size(); i++) { @@ -318,11 +318,16 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve benefitStr.push_back(sumStr); // compute n-step mixed-precision - fmt::print("opSequence (remove the last step) for n-step: {}\n", opSequence); + benefitStr.clear(); + // fmt::print("opSequence (remove the last step) for n-step: {}\n", opSequence); + string tmpStr = fmt::format("opSequence (remove the last step) for n-step: {}\n", opSequence); + benefitStr.push_back(tmpStr); for(size_t numStep = 1; numStep < opSequence.size(); numStep++) { auto combResults = combinationNew(numStep, opSequence); - fmt::print("for {}-step, combResult = {}\n", numStep, combResults); + // fmt::print("for {}-step, combResult = {}\n", numStep, combResults); + tmpStr = fmt::format("for {}-step, combResult = {}\n", numStep, combResults); + benefitStr.push_back(tmpStr); vector benefitAverage; vector tmp(length, 1); for(const auto &combResult : combResults) @@ -343,8 +348,12 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve benefitAverage.push_back(benefitTmp); } auto ranks = getRanks(benefitAverage, false); - fmt::print("for {}-step, benefitAverage = {}\n", numStep, benefitAverage); - fmt::print("for {}-step, ranks = {}\n", numStep, ranks); + // fmt::print("\tbenefitAverage = {}\n", benefitAverage); + // fmt::print("\tranks = {}\n", ranks); + tmpStr = fmt::format("\tbenefitAverage = {}\n", benefitAverage);; + benefitStr.push_back(tmpStr); + string tmpStr = fmt::format("\tranks = {}\n", ranks); + benefitStr.push_back(tmpStr); } return benefitStr; } -- Gitee From eb5507dc5ed8a6a34486b1d17a360baa9a132a19 Mon Sep 17 00:00:00 2001 From: hjw Date: Thu, 10 Aug 2023 15:03:51 +0800 Subject: [PATCH 32/54] Fix a type bug of factorial --- src/basic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic.cpp b/src/basic.cpp index a71e469..8b23e08 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -884,9 +884,9 @@ vector> combinationNew(const int num, const vector &indexs) return set; } -inline unsigned int factorial(unsigned int value) +inline double factorial(unsigned int value) { - unsigned int local_value = value; + double local_value = value; while(value-- > 1) { local_value *= value; -- Gitee From b181039844b9ee5b01d9d195fae73ca18cd7a8c0 Mon Sep 17 00:00:00 2001 From: hjw Date: Thu, 10 Aug 2023 15:05:26 +0800 Subject: [PATCH 33/54] Add a new DD generation method --- src/geneCode.cpp | 59 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 5daa0a4..35b1b50 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -1513,21 +1513,21 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // } // set opTypes: method NO.3 - int lenDataTypes = dataTypes.size(); - int maxNum = pow(lenDataTypes, lenOp); // for dataTypes = {"ld", "double"}, maxNum = 1 << lenOp; - for(int num = 0; num < maxNum; num++) - { - auto currentNum = num; - std::map opTypes; - for(size_t i = 0; i < lenOp; i++) - { - auto id = opSequence[i]; - auto tmp = currentNum % lenDataTypes; - opTypes[id] = dataTypes[tmp]; - currentNum = currentNum / lenDataTypes; - } - opTypesAll.push_back(opTypes); - } + // int lenDataTypes = dataTypes.size(); + // int maxNum = pow(lenDataTypes, lenOp); // for dataTypes = {"ld", "double"}, maxNum = 1 << lenOp; + // for(int num = 0; num < maxNum; num++) + // { + // auto currentNum = num; + // std::map opTypes; + // for(size_t i = 0; i < lenOp; i++) + // { + // auto id = opSequence[i]; + // auto tmp = currentNum % lenDataTypes; + // opTypes[id] = dataTypes[tmp]; + // currentNum = currentNum / lenDataTypes; + // } + // opTypesAll.push_back(opTypes); + // } // set opTypes: method NO.4 // for (size_t i = 0; i < lenOp; i++) @@ -1543,6 +1543,35 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // opTypesAll.push_back(opTypes); // } + // set opTypes: method NO.5 + opSequence.pop_back(); + for(size_t numStep = 1; numStep < opSequence.size(); numStep++) + { + // judge if too many combination number + auto combNum = combination(numStep, opSequence.size()); + if(combNum > 200) + { + cout << "ATTENTION: combination number " << combNum << " is too big to run!!!\n"; + continue; + } + auto combResults = combinationNew(numStep, opSequence); + for(const auto &combResult : combResults) + { + mapOpType opTypes; + for(size_t j = 0; j < lenOp; j++) + { + auto id = opSequence[j]; + opTypes[id] = dataTypes.at(1); // double + } + for(size_t j = 0; j < combResult.size(); j++) + { + auto id = combResult.at(j); + opTypes[id] = dataTypes.at(0); // DD + } + opTypesAll.push_back(opTypes); + } + } + //// 2nd: loop the vector to generate code and do other things int currentNum = 0; for(const auto &opTypes : opTypesAll) -- Gitee From 150b7110762cd8af3e62fb5a4918f4f06634c8db Mon Sep 17 00:00:00 2001 From: hjw Date: Thu, 10 Aug 2023 16:17:14 +0800 Subject: [PATCH 34/54] Improve computeEpsilonE and create a new version for it. --- src/shadowValue.cpp | 184 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 4 deletions(-) diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index 2feba95..c1e9e4d 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -320,13 +320,21 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve // compute n-step mixed-precision benefitStr.clear(); // fmt::print("opSequence (remove the last step) for n-step: {}\n", opSequence); - string tmpStr = fmt::format("opSequence (remove the last step) for n-step: {}\n", opSequence); + string tmpStr = fmt::format("## mixed-precision predict\nopSequence (remove the last step) for n-step: {}\n", opSequence); benefitStr.push_back(tmpStr); for(size_t numStep = 1; numStep < opSequence.size(); numStep++) + // for(size_t numStep = 1; numStep < 2; numStep++) { + // judge if too many combination number + auto combNum = combination(numStep, opSequence.size()); + if(combNum > 200) + { + cout << "ATTENTION: combination number " << combNum << " is too big to run!!!\n"; + continue; + } auto combResults = combinationNew(numStep, opSequence); // fmt::print("for {}-step, combResult = {}\n", numStep, combResults); - tmpStr = fmt::format("for {}-step, combResult = {}\n", numStep, combResults); + tmpStr = fmt::format("### for {}-step\n\tcombResult = {}\n", numStep, combResults); benefitStr.push_back(tmpStr); vector benefitAverage; vector tmp(length, 1); @@ -352,8 +360,175 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve // fmt::print("\tranks = {}\n", ranks); tmpStr = fmt::format("\tbenefitAverage = {}\n", benefitAverage);; benefitStr.push_back(tmpStr); - string tmpStr = fmt::format("\tranks = {}\n", ranks); + tmpStr = fmt::format("\tranks = {}\n", ranks); benefitStr.push_back(tmpStr); + + benefitStr.push_back("step log\n"); + cout << "step log\n"; + for(size_t i = 0; i < benefitAverage.size(); i++) + { + // tmpStr = fmt::format("{}", combResults.at(i)); + auto &combResult = combResults.at(i); + tmpStr = std::to_string(combResult.at(0)); + for(size_t j = 1; j < combResult.size(); j++) + { + tmpStr = tmpStr + "," + std::to_string(combResult.at(j)); + } + tmpStr = tmpStr + " " + std::to_string(ranks.at(i)) + "\n"; + cout << tmpStr; + benefitStr.push_back(tmpStr); + } + } + return benefitStr; + } + else + { + fprintf(stderr, "ERROR: %s : line %d: the type of T %s is not supported\n", __func__, __LINE__, typeid(T).name()); + exit(EXIT_FAILURE); + } +} + +template +vector computeEpsilonENew(vector &benefit, vector &epsilonE, const vector &errorValues, const vector &conditionNumbersOp, const vector &condNumOrder, const vector &opSequence, const int length = 1) +{ + constexpr bool TisDouble = (std::is_same::value); + constexpr bool TisDoublePointer = (std::is_same::value); + if constexpr (TisDouble) + { + vector epsilonEStr; + for(size_t i = 0; i < errorValues.size(); i++) + { + epsilonE.at(i) = errorValues.at(i) * conditionNumbersOp.at(condNumOrder.at(i)); + epsilonEStr.push_back(std::to_string(epsilonE.at(i))); + } + auto sum = std::accumulate(epsilonE.begin(), epsilonE.end(), 0.0); + fmt::print("the average of epsilonE are: {}\n", epsilonE); + std::cout << "The sum of the elements in the vector is: " << sum << std::endl; + + // compute benefit + double minBenefit = std::numeric_limits::infinity(); + int minBenefitIdx = std::numeric_limits::infinity(); + for(size_t i = 0; i < errorValues.size(); i++) + { + benefit.at(i) = fabs(sum - epsilonE.at(i)); + if(benefit.at(i) < minBenefit) + { + minBenefit = benefit.at(i); + minBenefitIdx = i; + } + } + fmt::print("the benefit of steps are: {}\n", benefit); + std::cout << "minBenefitIdx: " << minBenefitIdx << ", minBenefit: " << minBenefit << std::endl; + + return epsilonEStr; + } + else if constexpr (TisDoublePointer) + { + vector epsilonEAverage(errorValues.size(), 0.0); + vector errorValuesAverage(errorValues.size(), 0.0); + vector conditionNumbersOpAverage(errorValues.size(), 0.0); + vector sumOfAll(length, 0.0); + + // compute epsilonE and its sum. These 3 average values are not useful + for(size_t i = 0; i < errorValues.size(); i++) + { + for(int j = 0; j < length; j++) + { + epsilonE.at(i)[j] = errorValues.at(i)[j] * conditionNumbersOp.at(condNumOrder.at(i))[j]; + epsilonEAverage.at(i) += epsilonE.at(i)[j]; + errorValuesAverage.at(i) += errorValues.at(i)[j]; + conditionNumbersOpAverage.at(i) += conditionNumbersOp.at(i)[j]; + sumOfAll.at(j) += epsilonE.at(i)[j]; + } + epsilonEAverage.at(i) /= length; + errorValuesAverage.at(i) /= length; + conditionNumbersOpAverage.at(i) /= length; + } + // auto sum = std::accumulate(epsilonEAverage.begin(), epsilonEAverage.end(), 0.0); + auto sum = std::accumulate(sumOfAll.begin(), sumOfAll.end(), 0.0); + auto sumAverage = fabs(sum / length); + + // compute benefit for 1-step + // notes: benefit is the predicted error value after mixed-precision tuning. + vector minBenefit(length, std::numeric_limits::infinity()); + vector minBenefitIdx(length, std::numeric_limits::infinity()); + vector benefitAverage(errorValues.size(), 0.0); + for(size_t i = 0; i < errorValues.size(); i++) + { + for(int j = 0; j < length; j++) + { + benefit.at(i)[j] = fabs(sumOfAll.at(j) - epsilonE.at(i)[j]); + if(benefit.at(i)[j] < minBenefit.at(j)) + { + minBenefit.at(j) = benefit.at(i)[j]; + minBenefitIdx.at(j) = i; + } + benefitAverage.at(i) += benefit.at(i)[j]; + } + benefitAverage.at(i) /= length; + } + + // print + vector benefitStr; + // compute n-step mixed-precision + // string tmpStr = fmt::format("## mixed-precision predict\nopSequence (remove the last step) for n-step: {}\n", opSequence); + // benefitStr.push_back(tmpStr); + string tmpStr; + for(size_t numStep = 1; numStep < opSequence.size(); numStep++) + { + // judge if too many combination number + auto combNum = combination(numStep, opSequence.size()); + if(combNum > 200) + { + cout << "ATTENTION: combination number " << combNum << " is too big to run!!!\n"; + continue; + } + auto combResults = combinationNew(numStep, opSequence); + fmt::print("for {}-step, combResult = {}\n", numStep, combResults); + // tmpStr = fmt::format("### for {}-step\n\tcombResult = {}\n", numStep, combResults); + // benefitStr.push_back(tmpStr); + vector benefitAverage; + vector tmp(length, 1); + for(const auto &combResult : combResults) + { + double benefitTmp = 0.0; + for(int j = 0; j < length; j++) + { + tmp.at(j) = sumOfAll.at(j); + for(size_t i = 0; i < combResult.size(); i++) + { + auto stepIdx = combResult.at(i); + tmp.at(j) = tmp.at(j) - epsilonE.at(stepIdx)[j]; + } + tmp.at(j) = fabs(tmp.at(j)); + benefitTmp += tmp.at(j); + } + benefitTmp /= length; + benefitAverage.push_back(benefitTmp); + } + auto ranks = getRanks(benefitAverage, false); + fmt::print("\tbenefitAverage = {}\n", benefitAverage); + fmt::print("\tranks = {}\n", ranks); + // tmpStr = fmt::format("\tbenefitAverage = {}\n", benefitAverage);; + // benefitStr.push_back(tmpStr); + // tmpStr = fmt::format("\tranks = {}\n", ranks); + // benefitStr.push_back(tmpStr); + + // benefitStr.push_back("step log\n"); + cout << "step log\n"; + for(size_t i = 0; i < benefitAverage.size(); i++) + { + // tmpStr = fmt::format("{}", combResults.at(i)); + auto &combResult = combResults.at(i); + tmpStr = std::to_string(combResult.at(0)); + for(size_t j = 1; j < combResult.size(); j++) + { + tmpStr = tmpStr + "," + std::to_string(combResult.at(j)); + } + tmpStr = tmpStr + " " + std::to_string(ranks.at(i)); + cout << tmpStr << "\n"; + benefitStr.push_back(tmpStr); + } } return benefitStr; } @@ -1394,7 +1569,8 @@ vector shadowValue(const ast_ptr &expr, const std::map &varsV vector opSequence; getOrders(expr, opSequence); opSequence.pop_back(); - auto epsilonEStr = computeEpsilonE(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, opSequence, length); + // auto epsilonEStr = computeEpsilonE(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, opSequence, length); + auto epsilonEStr = computeEpsilonENew(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, opSequence, length); // shadowValuePrint(funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, conditionNumbersOp, epsilonE, varsValue, length, ifUnique, uniqueLabel, funcName); return epsilonEStr; -- Gitee From 016b69c013cd5b4b8953b9333c5305e27a9129b6 Mon Sep 17 00:00:00 2001 From: hjw Date: Thu, 10 Aug 2023 16:25:07 +0800 Subject: [PATCH 35/54] Fix the inputData bug and Improve the output style --- src/main.cpp | 72 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e528eb1..f6b9d5f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -291,6 +291,28 @@ int main() //// generate input data for shadow value vector values1; size_t inputNum = 100000; + size_t inputAllNum = 100000; + if (dimension == 1) + { + inputNum = 100000; + } + else if (dimension == 2) + { + inputNum = 316; // 316*316=99,856 + } + else if (dimension == 3) + { + inputNum = 100; + } + else if (dimension == 4) + { + inputNum = 18; // 18*18*18*18=104,976 + } + else + { + inputNum = 10; + } + inputAllNum = pow(inputNum, dimension); for(int i = 0; i < dimension; i++) { auto &startOriginInterval = intervals.at(i * 2); @@ -298,10 +320,10 @@ int main() double width = endOriginInterval - startOriginInterval; double step = width / inputNum; - double *tmp = new double[inputNum]; - for(size_t j = 0; j < inputNum; j++) + double *tmp = new double[inputAllNum]; + for(size_t j = 0; j < inputAllNum; j++) { - tmp[j] = startOriginInterval + j * step; + tmp[j] = startOriginInterval + (j % inputNum) * step; } values1.push_back(tmp); } @@ -318,10 +340,10 @@ int main() string tmpStr; tmpStr = fmt::format("expr: {}\n", exprOrigin); epsilonEStr.insert(epsilonEStr.begin(), tmpStr); - tmpStr = fmt::format("uniqueLabel: {}\n", uniqueLabel); + tmpStr = fmt::format("# uniqueLabel: {}\n", uniqueLabel); epsilonEStr.insert(epsilonEStr.begin(), tmpStr); std::ofstream outputFile; - outputFile.open("mixPrec.log", std::ios::out | std::ios::app); + outputFile.open("mixPrecNew.log", std::ios::out | std::ios::app); if (outputFile.is_open() == false) { exit(EXIT_FAILURE); @@ -329,13 +351,13 @@ int main() for(int i = 0; i < (int)epsilonEStr.size(); i++) { auto &epsilonEStrNow = epsilonEStr.at(i); - cout << epsilonEStrNow; + cout << epsilonEStrNow << "\n"; outputFile << epsilonEStrNow; } outputFile << "\n"; - outputFile.close(); - fprintf(stderr, GREEN "ready> " RESET); - continue; + // outputFile.close(); + // fprintf(stderr, GREEN "ready> " RESET); + // continue; //// TODO: free values1 //// support DD @@ -360,30 +382,48 @@ int main() vector infos; vector perfValues; for(int i = 0; i < maxNum; i++) { - // cout << "\n\n-test error-" << i << "\n"; + cout << "\n\n-test error-" << i << "\n"; string tmp = "dd_" + std::to_string(i); - // auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); auto tmpPerformance = testPerformance(uniqueLabel, tmp, intervals); cout << tmp << " performance: " << tmpPerformance << "\n\n"; - // infos.push_back(infoTmp); + infos.push_back(infoTmp); perfValues.push_back(tmpPerformance); } // cout << std::left << setw(4) << "No"; // cout << "\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; - cout << "\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "performamce" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; + cout << "\n## Actual data\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "performamce" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; + outputFile << "\n## Actual data\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "performamce" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; for(size_t i = 0; i < opSequence.size(); i++) { cout << "step Type "; + outputFile << "step Type "; } cout << "\n"; + outputFile << "\n"; for(int i = 0; i < maxNum; i++) { - // auto &info = infos.at(i); + auto &info = infos.at(i); auto &opTypeStr = outputStr.at(i); // cout << std::left << setw(4) << i << opTypeStr << "\n"; - cout << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << "\n"; - // cout << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; + // cout << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << "\n"; + cout << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; + outputFile << std::left << setw(6) << i << std::left << setw(15) << perfValues.at(i) << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << opTypeStr << "\n"; } + outputFile << "\n\n"; + outputFile << "## Final data\n\n"; + cout << "\n\n## Final data\n\n"; + cout << std::left << setw(6) << "No" << std::left << setw(15) << "step log" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err" << "performamce\n"; + outputFile << std::left << setw(6) << "No" << std::left << setw(15) << "step log" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err" << "performamce\n"; + for(int i = 0; i < maxNum; i++) + { + auto &info = infos.at(i); + auto &opTypeStr = outputStr.at(i); + cout << std::left << setw(6) << i << std::left << setw(15) << epsilonEStr.at(i + 2) << " " << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << std::left << setw(15) << perfValues.at(i) << "\n"; + outputFile << std::left << setw(6) << i << std::left << setw(15) << epsilonEStr.at(i + 2) << " " << std::left << setw(15) << info.aveError << std::left << setw(15) << info.maxError << std::left << setw(15) << perfValues.at(i) << "\n"; + } + outputFile << "\n\n"; + outputFile.close(); fprintf(stderr, GREEN "ready> " RESET); continue; -- Gitee From 3d1ead1c9f41880bf02d02b9f84ec38e97ac9550 Mon Sep 17 00:00:00 2001 From: hjw Date: Thu, 7 Sep 2023 22:47:52 +0800 Subject: [PATCH 36/54] update performance test, support TGen --- srcTest/testPerformanceOneManual.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/srcTest/testPerformanceOneManual.sh b/srcTest/testPerformanceOneManual.sh index ff23c00..27961dc 100755 --- a/srcTest/testPerformanceOneManual.sh +++ b/srcTest/testPerformanceOneManual.sh @@ -26,15 +26,15 @@ fi resultFileName=result_${uniqueLabel}_${start}_${end}.txt funcName=expr_${uniqueLabel}_${suffix} -# gcc gccPerformanceTest.c binary.c ${uniqueLabel}/${funcName}.c -DFUNCNAME=${funcName} -DRUNTIME=${runtime} -I../includeTEST -lm -o gccPerformanceTest_${uniqueLabel}.exe -O3 +# gcc testPerformanceOne.c binary.c ${uniqueLabel}/${funcName}.c -DFUNCNAME=${funcName} -DRUNTIME=${runtime} -I../includeTEST -lm -o testPerformanceOne_${uniqueLabel}.exe -O3 -# make gccPerformanceTest.o -s CFLAGS="-DFUNCNAME=${funcName} -DRUNTIME=${runtime}" -gcc gccPerformanceTest.c -DFUNCNAME=${funcName} -DRUNTIME=${runtime} -I../includeTEST -c -O3 +# make testPerformanceOne.o -s CFLAGS="-DFUNCNAME=${funcName} -DRUNTIME=${runtime}" +gcc testPerformanceOne.c -DFUNCNAME=${funcName} -DRUNTIME=${runtime} -I../includeTEST -c -O3 make binary.o -s # gcc binary.c -I../includeTEST -c -O3 gcc ${uniqueLabel}/${funcName}.c -I../includeDD -c -O3 -gcc gccPerformanceTest.o binary.o ${funcName}.o -lmpfr -lm -lqd -o gccPerformanceTest_${uniqueLabel}.exe -O3 -./gccPerformanceTest_${uniqueLabel}.exe ${resultFileName} ${start} ${end} -# rm -rf gccPerformanceTest_${uniqueLabel}.exe +gcc testPerformanceOne.o binary.o ${funcName}.o ../libs/libTGen.so -lmpfr -lm -lqd -o testPerformanceOne_${uniqueLabel}.exe -O3 +./testPerformanceOne_${uniqueLabel}.exe ${resultFileName} ${start} ${end} +# rm -rf testPerformanceOne_${uniqueLabel}.exe ### compute the cycles of the function ${uniqueLabel} make dataClean.exe -s CFLAGS="-DRUNTIME=${runtime}" # gcc dataClean.c -DRUNTIME=${runtime} -o dataClean.exe -- Gitee From 3ce9b378a64c57d7bcb8c0ddd989bfc594a7621c Mon Sep 17 00:00:00 2001 From: hjw Date: Fri, 15 Sep 2023 10:18:29 +0800 Subject: [PATCH 37/54] Adjust output format to show condNum and error Note: condNum and error are to fabs firstly before cumulative summation --- src/errorDetect.cpp | 4 ++-- src/main.cpp | 32 +++++++++++++++++--------------- src/shadowValue.cpp | 18 +++++++++--------- src/tools.cpp | 2 +- srcTest/test1paramFPEDParallel.c | 4 ++-- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/errorDetect.cpp b/src/errorDetect.cpp index e0d84b0..54f20d4 100644 --- a/src/errorDetect.cpp +++ b/src/errorDetect.cpp @@ -62,8 +62,8 @@ double computeError(mpfr::mpreal oracle, mpfr::mpreal x) double computeError(mpfr::mpreal funcRealValue, mpfr::mpreal funcValue, double unitUlp) { // ulp error - // auto errorValue = fabs((funcRealValue - funcValue).toDouble() / unitUlp); - auto errorValue = (funcRealValue - funcValue).toDouble() / unitUlp; + auto errorValue = fabs((funcRealValue - funcValue).toDouble() / unitUlp); + // auto errorValue = (funcRealValue - funcValue).toDouble() / unitUlp; return errorValue; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f6b9d5f..e0c3461 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -338,10 +338,10 @@ int main() auto epsilonEStr = Shadow::shadowValue(originExpr, varsValue1, inputNum); string tmpStr; - tmpStr = fmt::format("expr: {}\n", exprOrigin); - epsilonEStr.insert(epsilonEStr.begin(), tmpStr); - tmpStr = fmt::format("# uniqueLabel: {}\n", uniqueLabel); - epsilonEStr.insert(epsilonEStr.begin(), tmpStr); + // tmpStr = fmt::format("expr: {}\n", exprOrigin); + // epsilonEStr.insert(epsilonEStr.begin(), tmpStr); + // tmpStr = fmt::format("# uniqueLabel: {}\n", uniqueLabel); + // epsilonEStr.insert(epsilonEStr.begin(), tmpStr); std::ofstream outputFile; outputFile.open("mixPrecNew.log", std::ios::out | std::ios::app); if (outputFile.is_open() == false) @@ -355,7 +355,7 @@ int main() outputFile << epsilonEStrNow; } outputFile << "\n"; - // outputFile.close(); + outputFile.close(); // fprintf(stderr, GREEN "ready> " RESET); // continue; //// TODO: free values1 @@ -378,18 +378,20 @@ int main() double step = width / (double)scales.at(i); steps.push_back(step); } - // testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps, false); vector infos; vector perfValues; - for(int i = 0; i < maxNum; i++) { - cout << "\n\n-test error-" << i << "\n"; - string tmp = "dd_" + std::to_string(i); - auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); - auto tmpPerformance = testPerformance(uniqueLabel, tmp, intervals); - cout << tmp << " performance: " << tmpPerformance << "\n\n"; - infos.push_back(infoTmp); - perfValues.push_back(tmpPerformance); - } + // for(int i = 0; i < maxNum; i++) { + // cout << "\n\n-test error-" << i << "\n"; + // string tmp = "dd_" + std::to_string(i); + // auto infoTmp = testError(uniqueLabel, tmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, false); + // auto tmpPerformance = testPerformance(uniqueLabel, tmp, intervals); + // cout << tmp << " performance: " << tmpPerformance << "\n\n"; + // infos.push_back(infoTmp); + // perfValues.push_back(tmpPerformance); + // } + fprintf(stderr, GREEN "ready> " RESET); + continue; // cout << std::left << setw(4) << "No"; // cout << "\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; cout << "\n## Actual data\n\n" << std::left << setw(6) << "No" << std::left << setw(15) << "performamce" << std::left << setw(15) << "average_Err" << std::left << setw(15) << "max_Err"; diff --git a/src/shadowValue.cpp b/src/shadowValue.cpp index c1e9e4d..54ada26 100644 --- a/src/shadowValue.cpp +++ b/src/shadowValue.cpp @@ -244,7 +244,7 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve epsilonE.at(i)[j] = errorValues.at(i)[j] * conditionNumbersOp.at(condNumOrder.at(i))[j]; epsilonEAverage.at(i) += epsilonE.at(i)[j]; errorValuesAverage.at(i) += errorValues.at(i)[j]; - conditionNumbersOpAverage.at(i) += conditionNumbersOp.at(i)[j]; + conditionNumbersOpAverage.at(i) += fabs(conditionNumbersOp.at(i)[j]); sumOfAll.at(j) += epsilonE.at(i)[j]; } epsilonEAverage.at(i) /= length; @@ -302,7 +302,7 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve auto ranks = getRanks(benefitAverage, false); // fmt::print("{:^4} {:<15}\n", "rank", "benefit"); // fmt::print("{:<3} {:^4} {:<15}\n", "NO.", "rank", "benefit"); - // fmt::print("{:<3} {:<4} {:<15} {:<15} {:<15} {:<15}\n", "No.", "rank", "errValAver", "condNumOpAver", "epsilonEAver", "benefit"); + fmt::print("{:<3} {:<4} {:<15} {:<15} {:<15} {:<15}\n", "No.", "rank", "errValAver", "condNumOpAver", "epsilonEAver", "benefit"); vector benefitStr; for(size_t i = 0; i < benefitAverage.size(); i++) { @@ -316,9 +316,9 @@ vector computeEpsilonE(vector &benefit, vector &epsilonE, const ve } string sumStr = fmt::format("The average sum of the epsilon is {:g}\n", sumAverage); benefitStr.push_back(sumStr); - + return benefitStr; // compute n-step mixed-precision - benefitStr.clear(); + // benefitStr.clear(); // fmt::print("opSequence (remove the last step) for n-step: {}\n", opSequence); string tmpStr = fmt::format("## mixed-precision predict\nopSequence (remove the last step) for n-step: {}\n", opSequence); benefitStr.push_back(tmpStr); @@ -1294,7 +1294,7 @@ valueThree shadowValueKernel(const ast_ptr &expr, const std::map & } funcRealValues.push_back(tmpfuncRealValues); mathRealValues.push_back(tmpmathRealValues); - errorValues.push_back(tmpErrorValues); + errorValues.push_back(tmpErrorValues); // error between funcRealValue and funcValue result.realValue = tmpmathRealValues; result.ulpValue = tmpUlpValues; } @@ -1541,7 +1541,7 @@ vector shadowValue(const ast_ptr &expr, const std::map &varsV std::vector> funcRealValues; std::vector> mathRealValues; vector errorValueOrder; // for conditionNumbers vector, store the corresponding errorValue order - shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, errorValueOrder, length); + shadowValueKernel(expr, varsValue, funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, errorValueOrder, length); // compute condition numbers of each operation in expr for varsValue. This condition number is only for the corresponding opeation. errorValueOrder.push_back(conditionNumbers.size()); // 令condNumber最后一个元素指向conditionNumber的最后一个元素,同时保证其长度同errorValues、conditionNumberOp一致 // fmt::print("errorValueOrder: {}\n", errorValueOrder); vector condNumOrder; // for errorValue vector, store the corresponding conditionNumbers order @@ -1565,12 +1565,12 @@ vector shadowValue(const ast_ptr &expr, const std::map &varsV shadowValueInit(conditionNumbersOp, benefit, epsilonE, conditionNumbers.size() + 1, length); int IDfather = conditionNumbersOp.size() - 1; int IDnow = conditionNumbers.size() - 1; - computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); + computeConditionNumber(expr, conditionNumbers, conditionNumbersOp, IDfather, IDnow, length); // compute the segma condition number for operations. vector opSequence; getOrders(expr, opSequence); opSequence.pop_back(); - // auto epsilonEStr = computeEpsilonE(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, opSequence, length); - auto epsilonEStr = computeEpsilonENew(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, opSequence, length); + auto epsilonEStr = computeEpsilonE(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, opSequence, length); + // auto epsilonEStr = computeEpsilonENew(benefit, epsilonE, errorValues, conditionNumbersOp, condNumOrder, opSequence, length); // shadowValuePrint(funcValues, funcRealValues, mathRealValues, errorValues, conditionNumbers, conditionNumbersOp, epsilonE, varsValue, length, ifUnique, uniqueLabel, funcName); return epsilonEStr; diff --git a/src/tools.cpp b/src/tools.cpp index 4a1ea09..685d446 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -421,7 +421,7 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte string commandStr = ss.str(); // cout << "fileNameKernel: " << fileNameKernel << "\n"; - // cout << "command: " << commandStr << "\n"; + cout << "command: " << commandStr << "\n"; // cout << "testName: " << testName << "\n"; char command[512] = {0}; strcat(command, commandStr.c_str()); diff --git a/srcTest/test1paramFPEDParallel.c b/srcTest/test1paramFPEDParallel.c index 0574211..450f4cc 100644 --- a/srcTest/test1paramFPEDParallel.c +++ b/srcTest/test1paramFPEDParallel.c @@ -258,8 +258,8 @@ int main(int argc, char **argv) printf("Error opening file %s.\n", fileNameErr); exit(0); } - // printf("average ulp\tmax ulp\n"); - // printf("%.16le\t%.16le\n", aveError, maxError); + printf("average ulp\tmax ulp\n"); + printf("%.16le\t%.16le\n", aveError, maxError); // printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); fprintf(fErr, "average ulp\tmax ulp\n"); fprintf(fErr, "%.16le\t%.16le\n", aveError, maxError); -- Gitee From 24e980027cff26eb8e75c32cfe689541f629b42b Mon Sep 17 00:00:00 2001 From: hjw Date: Sat, 16 Sep 2023 16:05:27 +0800 Subject: [PATCH 38/54] add pareto optimization --- srcTest/MPMF_1.sh | 62 ++++++++++++++++++++++++++++++++++ srcTest/MPMF_2.sh | 77 ++++++++++++++++++++++++++++++++++++++++++ srcTest/funcMap.sh | 79 +++++++++++++++++++++++++++++++++++++++++++ srcTest/pareto_2.py | 81 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 299 insertions(+) create mode 100755 srcTest/MPMF_1.sh create mode 100755 srcTest/MPMF_2.sh create mode 100755 srcTest/funcMap.sh create mode 100644 srcTest/pareto_2.py diff --git a/srcTest/MPMF_1.sh b/srcTest/MPMF_1.sh new file mode 100755 index 0000000..2c74099 --- /dev/null +++ b/srcTest/MPMF_1.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# set -x +# 多精度版本函数的路径是TGen的路径,特定于北京服务器的固定路径。 +# NMSEproblem345的单参特供版,仅能修改其中的sin函数,用来测试使用不同函数的表达式的性能和精度 +#init for mix-precision +source funcMap.sh +func1=sin +path_TGen=/home/xyy/helloBro/TGen +path_func1=${path_TGen}/${func1}_gen +path_current=`pwd` +temp_file=${path_current}/temp.log # 临时文件,在循环中被刷新 +log_file=${path_current}/hjw.log # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 + +if [ -f "${log_file}" ]; then + rm "${log_file}" +fi + +# init for error detection and performance detection +uniqueLabel=NMSEproblem345 +x0Start=0.01 +x0End=100 +x0Size=500000 +x0startNowIdx=0 +x0startOriginInterval=0.01 +stepX0=0.00019998 +prefix=expr_${uniqueLabel} +middle=${x0Start}_${x0End}_${x0Size} +suffix=origin +errfile=0 + +# init for the expression code file +expr_file=${uniqueLabel}/${prefix}_${suffix}.c +expr_bkp_file=${uniqueLabel}/${prefix}_${suffix}_bkp.c +if [ -f "${expr_bkp_file}" ]; then + cp ${expr_bkp_file} ${expr_file} +else + echo "ERROR" + exit +fi +sed -i "1a\#include \"${func1}_gen.c\"" ${expr_file} +sed -i "s@${func1}(@${func1}_gen(@g" ${expr_file} + +# loop to generate different version + +# loop1,2 for func1 +# for ((bit1=0; bit1<=1; bit1++)) +for ((bit1=0; bit1<=${bit_range[$func1]}; bit1++)) +do + # for ((degree1=0; degree1<1; degree1++)) + for ((degree1=0; degree1<${degree_range[$func1]}; degree1++)) + do + cp ${path_func1}/${func1}_gen_${bit1}_1_${degree1}.c ${uniqueLabel}/${func1}_gen.c + echo "${func1}: bit = ${bit1} degree = ${degree1}" + echo -e "${func1}\t${bit1}\t${degree1}:" > ${temp_file} + cd .. + ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + cd - >/dev/null + taskset -c 8 ./testPerformanceOneManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} | tee -a ${temp_file} + awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $0 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} + echo + done +done \ No newline at end of file diff --git a/srcTest/MPMF_2.sh b/srcTest/MPMF_2.sh new file mode 100755 index 0000000..4f901dc --- /dev/null +++ b/srcTest/MPMF_2.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# set -x +# 多精度版本函数的路径是TGen的路径,特定于北京服务器的固定路径。 +# NMSEproblem345的双参特供版,能修改其中的tan, sin函数的精度版本,用来测试使用不同函数的表达式的性能和精度 +#init for mix-precision +source funcMap.sh +func1=tan +func2=sin +path_TGen=/home/xyy/helloBro/TGen +path_func1=${path_TGen}/${func1}_gen +path_func2=${path_TGen}/${func2}_gen +path_current=`pwd` +temp_file=${path_current}/temp.log # 临时文件,在循环中被刷新 +log_file=${path_current}/hjw.log # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 + +if [ -f "${log_file}" ]; then + rm "${log_file}" +fi + +# init for error detection and performance detection +uniqueLabel=NMSEproblem345 +x0Start=0.01 +x0End=100 +x0Size=500000 +x0startNowIdx=0 +x0startOriginInterval=0.01 +stepX0=0.00019998 +prefix=expr_${uniqueLabel} +middle=${x0Start} +suffix=origin +errfile=0 + +# init for the expression code file +expr_file=${uniqueLabel}/${prefix}_${suffix}.c +expr_bkp_file=${uniqueLabel}/${prefix}_${suffix}_bkp.c +if [ -f "${expr_bkp_file}" ]; then + cp ${expr_bkp_file} ${expr_file} +else + echo "ERROR" + exit +fi +sed -i "1a\#include \"${func1}_gen.c\"" ${expr_file} +sed -i "2a\#include \"${func2}_gen.c\"" ${expr_file} +sed -i "s@${func1}(@${func1}_gen(@g" ${expr_file} +sed -i "s@${func2}(@${func2}_gen(@g" ${expr_file} + +# loop to generate different version + +# loop1,2 for func1 +# for ((bit1=0; bit1<=1; bit1++)) +for ((bit1=0; bit1<=${bit_range[$func1]}; bit1++)) +do + # for ((degree1=0; degree1<1; degree1++)) + for ((degree1=0; degree1<${degree_range[$func1]}; degree1++)) + do + cp ${path_func1}/${func1}_gen_${bit1}_1_${degree1}.c ${uniqueLabel}/${func1}_gen.c + + # loop3,4 for func2 + # for ((bit2=0; bit2<=1; bit2++)) + for ((bit2=0; bit2<=${bit_range[$func2]}; bit2++)) + do + # for ((degree2=0; degree2<1; degree2++)) + for ((degree2=0; degree2<${degree_range[$func2]}; degree2++)) + do + cp ${path_func2}/${func2}_gen_${bit2}_1_${degree2}.c ${uniqueLabel}/${func2}_gen.c + echo "${func1}: bit = ${bit1} degree = ${degree1}; ${func2}: bit2 = ${bit2} degree = ${degree2}" + echo -e "${func1}\t${bit1}\t${degree1}\t${func2}\t${bit2}\t${degree2}:" > ${temp_file} + cd .. + ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + cd - >/dev/null + taskset -c 8 ./testPerformanceOneManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} | tee -a ${temp_file} + awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $0 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} + echo + done + done + done +done \ No newline at end of file diff --git a/srcTest/funcMap.sh b/srcTest/funcMap.sh new file mode 100755 index 0000000..8e59d25 --- /dev/null +++ b/srcTest/funcMap.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# 定义关联数组,模拟map +declare -A bit_range=( + ["sin"]=7 + ["cos"]=7 + ["tan"]=7 + ["exp"]=7 + ["exp2"]=7 + ["exp10"]=7 + ["log"]=7 + ["log2"]=7 + ["log10"]=7 + ["asinh"]=7 + ["acosh"]=7 + ["atanh"]=7 + ["asin"]=7 + ["acos"]=7 + ["atan"]=7 + ["sinh"]=7 + ["cosh"]=7 + ["tanh"]=7 +) +declare -A fnum_range=( + ["sin"]=1 + ["cos"]=1 + ["tan"]=1 + ["exp"]=1 + ["exp2"]=1 + ["exp10"]=1 + ["log"]=1 + ["log2"]=1 + ["log10"]=1 + ["asinh"]=1 + ["acosh"]=1 + ["atanh"]=1 + ["asin"]=1 + ["acos"]=1 + ["atan"]=1 + ["sinh"]=1 + ["cosh"]=1 + ["tanh"]=1 +) +declare -A degree_range=( + ["sin"]=7 + ["cos"]=7 + ["tan"]=7 + ["exp"]=8 + ["exp2"]=8 + ["exp10"]=8 + ["log"]=8 + ["log2"]=8 + ["log10"]=8 + ["asinh"]=8 + ["acosh"]=8 + ["atanh"]=8 + ["asin"]=8 + ["acos"]=8 + ["atan"]=8 + ["sinh"]=8 + ["cosh"]=8 + ["tanh"]=8 +) + +# 打印map中的值 +# echo "bit_range:" +# for key in "${!bit_range[@]}"; do +# echo "$key: ${bit_range[$key]}" +# done + +# echo "fnum_range:" +# for key in "${!fnum_range[@]}"; do +# echo "$key: ${fnum_range[$key]}" +# done + +# echo "degree_range:" +# for key in "${!degree_range[@]}"; do +# echo "$key: ${degree_range[$key]}" +# done \ No newline at end of file diff --git a/srcTest/pareto_2.py b/srcTest/pareto_2.py new file mode 100644 index 0000000..11e5f07 --- /dev/null +++ b/srcTest/pareto_2.py @@ -0,0 +1,81 @@ +import pandas as pd +import itertools + +# 读取2个文件,对应表达式中的两个函数。每个文件有2列,对应函数的误差和性能。 +def geneData(): + # 读取文件并将数据存储在 DataFrame 中 + func1 = pd.read_csv("func1.csv", delimiter='\t', dtype={0: str}) + func2 = pd.read_csv("func2.csv", delimiter='\t', dtype={0: str}) + + # 获取第一列数据 + error1 = func1.iloc[:, 0].tolist() + error2 = func2.iloc[:, 0].tolist() + + # 转换为浮点数 + error1 = [float(x) for x in error1] + error2 = [float(x) for x in error2] + + # 获取第二列数据 + perf1 = func1.iloc[:, 1].tolist() + perf2 = func2.iloc[:, 1].tolist() + + + # 对error和perf两个数据列表进行两两组合求和,并存储在新的数组中 + result1 = [] + for pair in itertools.product(error1, error2): + sum = pair[0] + pair[1] + result1.append(sum) + + result2 = [] + for pair in itertools.product(perf1, perf2): + sum = pair[0] + pair[1] + result2.append(sum) + + result = [] + for error, perf in zip(result1, result2): + pair = (error, perf) + result.append(pair) + + # 按科学计数法输出结果 + # for num in result1: + # print(f"{num:.2e}", end=' ') + # print(f"\nLength of 'result2' array: {len(result2)}") + # for pair in result: + # print(f"error: {pair[0]:.2e}, perf: {pair[1]}") + + return result + +def pareto_optimal(points): + pareto_points = [] + + for i in range(len(points)): + is_pareto = True + x1, y1 = points[i] + + for j in range(len(points)): + x2, y2 = points[j] + if x2 < x1 and y2 < y1: + is_pareto = False + break + + if is_pareto: + pareto_points.append((x1, y1, i)) + + return pareto_points + +# 默认读取2个文件:func1.csv func2.csv,分别存储的是两个函数的误差-开销信息 +if __name__ == '__main__': + # input_points = [(1, 5), (2, 4), (1, 3), (2, 1), (3, 3), (4, 2), (5, 1)] + input_points = geneData() + + pareto_result = pareto_optimal(input_points) + + # 输出符合帕累托最优化的点集 + print("符合帕累托最优化的点集:") + for pair in pareto_result: + print(f"No.{pair[2]}: error: {pair[0]:.2e}, perf: {pair[1]}") + print(f"\nLength of 'pareto_optimal points': {len(pareto_result)}") + for pair in pareto_result: + print(f"{pair[0]:.2e} {pair[1]}") + # for point in pareto_result: + # print(point) \ No newline at end of file -- Gitee From ea6dd501dd9f0adadde1e12a31609e3f5846e675 Mon Sep 17 00:00:00 2001 From: hjw Date: Sun, 17 Sep 2023 23:38:02 +0800 Subject: [PATCH 39/54] Improve pareto taking NMSEproblem345 as example. NOTE: using the new method --- srcTest/MPMF_2.sh | 38 ++------------- srcTest/combine_2.py | 90 ++++++++++++++++++++++++++++++++++ srcTest/getRealErrCost.sh | 66 +++++++++++++++++++++++++ srcTest/init.sh | 32 ++++++++++++ srcTest/pareto_2.py | 81 ------------------------------- srcTest/pareto_2Files.py | 87 +++++++++++++++++++++++++++++++++ srcTest/pareto_all.sh | 7 +++ srcTest/pareto_singleFunc.py | 94 ++++++++++++++++++++++++++++++++++++ srcTest/pareto_twoFunc.py | 54 +++++++++++++++++++++ srcTest/readmePareto.md | 41 ++++++++++++++++ srcTest/sortData.py | 36 ++++++++++++++ 11 files changed, 512 insertions(+), 114 deletions(-) create mode 100644 srcTest/combine_2.py create mode 100755 srcTest/getRealErrCost.sh create mode 100644 srcTest/init.sh delete mode 100644 srcTest/pareto_2.py create mode 100644 srcTest/pareto_2Files.py create mode 100755 srcTest/pareto_all.sh create mode 100644 srcTest/pareto_singleFunc.py create mode 100644 srcTest/pareto_twoFunc.py create mode 100644 srcTest/readmePareto.md create mode 100644 srcTest/sortData.py diff --git a/srcTest/MPMF_2.sh b/srcTest/MPMF_2.sh index 4f901dc..d006a70 100755 --- a/srcTest/MPMF_2.sh +++ b/srcTest/MPMF_2.sh @@ -2,13 +2,12 @@ # set -x # 多精度版本函数的路径是TGen的路径,特定于北京服务器的固定路径。 # NMSEproblem345的双参特供版,能修改其中的tan, sin函数的精度版本,用来测试使用不同函数的表达式的性能和精度 -#init for mix-precision + +# init for multi-precision func source funcMap.sh -func1=tan -func2=sin -path_TGen=/home/xyy/helloBro/TGen -path_func1=${path_TGen}/${func1}_gen -path_func2=${path_TGen}/${func2}_gen +source init.sh + +# init for current path path_current=`pwd` temp_file=${path_current}/temp.log # 临时文件,在循环中被刷新 log_file=${path_current}/hjw.log # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 @@ -17,33 +16,6 @@ if [ -f "${log_file}" ]; then rm "${log_file}" fi -# init for error detection and performance detection -uniqueLabel=NMSEproblem345 -x0Start=0.01 -x0End=100 -x0Size=500000 -x0startNowIdx=0 -x0startOriginInterval=0.01 -stepX0=0.00019998 -prefix=expr_${uniqueLabel} -middle=${x0Start} -suffix=origin -errfile=0 - -# init for the expression code file -expr_file=${uniqueLabel}/${prefix}_${suffix}.c -expr_bkp_file=${uniqueLabel}/${prefix}_${suffix}_bkp.c -if [ -f "${expr_bkp_file}" ]; then - cp ${expr_bkp_file} ${expr_file} -else - echo "ERROR" - exit -fi -sed -i "1a\#include \"${func1}_gen.c\"" ${expr_file} -sed -i "2a\#include \"${func2}_gen.c\"" ${expr_file} -sed -i "s@${func1}(@${func1}_gen(@g" ${expr_file} -sed -i "s@${func2}(@${func2}_gen(@g" ${expr_file} - # loop to generate different version # loop1,2 for func1 diff --git a/srcTest/combine_2.py b/srcTest/combine_2.py new file mode 100644 index 0000000..63a6961 --- /dev/null +++ b/srcTest/combine_2.py @@ -0,0 +1,90 @@ +import pandas as pd +import itertools +import math + +condNumSin = 8.943225 +condNumTan = 1.07E+00 + +# 读取2个文件,对应表达式中的两个函数。每个文件有2列,对应函数的误差和性能。 +def geneData(file1, file2): + # 读取文件并将数据存储在 DataFrame 中 + func1 = pd.read_csv(file1, sep='\t') # sin + func2 = pd.read_csv(file2, sep='\t') # tan + + # regime + regime1 = func1["regime"] + regime2 = func2["regime"] + + # degree + degree1 = func1["degree"] + degree2 = func2["degree"] + + # 平均误差 + error1 = func1["averageErr"] + error2 = func2["averageErr"] + + # 将平均误差的字符串数据转换为浮点数 + error1 = [float(x) for x in error1] + error2 = [float(x) for x in error2] + + # 性能节拍 + perf1 = func1["performance"] + perf2 = func2["performance"] + + # 两两组合 + result = [] + for i in range(len(error1)): + for j in range(len(error2)): + # errorSum = error1[i] + error2[j] # !!! 这里是关键,关键在于要不要从error变成epsilon。 + errorSum = error1[i] * condNumSin + error2[j] * condNumTan # !!! 这里是关键,关键在于要不要从error变成epsilon。 + perfSum = perf1[i] + perf2[j] + pair = (regime1[i], degree1[i], degree1[j], degree2[j], errorSum, perfSum) + result.append(pair) + return result + +def pareto_optimal(points): + pareto_points = [] + is_pareto = [True] * len(points) + for i in range(len(points)): + # if is_pareto[i] == False: + # continue + + regime1, degree1, regime2, degree2, err, cost = points[i] + + for j in range(len(points)): + # if is_pareto[j] == False: + # continue + if j == i: + continue + err2 = points[j][4] + cost2 = points[j][5] + if (err2 < err) and (cost2 <= cost): + is_pareto[i] = False + break + + for i in range(len(points)): + if is_pareto[i]: + pareto_points.append(points[i]) + + return pareto_points + +def writeToFile(data, file_path): + # file_path = 'output.csv' + + with open(file_path, 'w') as file: + file.write(f"regime1\tdegree1\tregime2\tdegree2\tepsilon\tcost\n") + for item in data: + # file.write(f"{item[2]} {item[0]:.6e} {item[1]}\n") + file.write(f"{item[0]}\t{item[1]}\t{item[2]}\t{item[3]}\t{item[4]:.6e}\t{item[5]}\n") + print("output file is %s"%(str(file_path))) + +# 默认读取2个文件:func1.csv func2.csv,分别存储的是两个函数的误差-开销信息 +if __name__ == '__main__': + func1 = "sin" + func1OutputFile = func1 + "Output.csv" + func2 = "tan" + func2OutputFile = func2 + "Output.csv" + uniqueLabel = "NMSEproblem345" + outputFile = uniqueLabel + "Output.csv" + input_points = geneData(func1OutputFile, func2OutputFile) + writeToFile(input_points, outputFile) \ No newline at end of file diff --git a/srcTest/getRealErrCost.sh b/srcTest/getRealErrCost.sh new file mode 100755 index 0000000..73d8f30 --- /dev/null +++ b/srcTest/getRealErrCost.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# set -x + +# 多精度版本函数的路径是TGen的路径,特定于北京服务器的固定路径。 +# NMSEproblem345的双参特供版,能修改其中的tan, sin函数的精度版本,用来测试使用不同函数的表达式的性能和精度 +# getRealErrCost脚本的测试对象是帕累托优化得到的所有混合精度方案,用来验证帕累托优化效果 +# getRealErrCost脚本从output.csv中读取数据。该数据是利用pareto_2.py生成的。 +# pareto_2.py是根据函数的测试信息,生成帕累托优化结果。 +# pareto_2.py中的数据是从func1.csv、func2.csv中获取得来的,即直接复制自TGen的结果。 +# !!!func1.csv、func2.csv中的数据不能直接复制自TGen,还需要对其乘以“条件数”!!! + +# 与getRealErrCost脚本功能类似的是MPMF_2.sh。 +# MPMF_2.sh脚本是直接测试所有不同的混合精度组合下的表达式“误差-性能”信息。 + +# init for mix-precision +source funcMap.sh +source init.sh + +# 读取CSV文件,保存到数组 +uniqueLabel="NMSEproblem345" +csv_file="${uniqueLabel}Output.csv" +data_array=() + +# init for current path +path_current=`pwd` +temp_file=${path_current}/temp.log # 临时文件,在循环中被刷新 +log_file=${path_current}/${uniqueLabel}_errPerf.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 + +while IFS=$'\t' read -r -a cols +do + data=() + for ((i=0; i<${#cols[@]}; i++)) + do + if [ $i -lt 4 ]; then # 只保存前4列数据 + data+=("${cols[i]}") + fi + done + data_array+=("${data[@]}") +done < <(tail -n +2 "$csv_file") # 从第二行开始读取文件,跳过标题行 + +# loop to generate different version +echo -e "${func1}_regime1\tdegree1\t${func2}_regime2\tdegree2\terror\tperformance" > ${log_file} +step=4 +for ((i=0; i<${#data_array[@]}; i+=step)) +do + # echo "Batch $((i/step+1)): ${data_array[@]:i:step}" + bit1=${data_array[i]} + degree1=${data_array[i+1]} + bit2=${data_array[i+2]} + degree2=${data_array[i+3]} + + # echo "当前参数:$bit1 $degree1 $bit2 $degree2" + cp ${path_func1}/${func1}_gen_${bit1}_1_${degree1}.c ${uniqueLabel}/${func1}_gen.c + cp ${path_func2}/${func2}_gen_${bit2}_1_${degree2}.c ${uniqueLabel}/${func2}_gen.c + echo "${func1}: bit = ${bit1} degree = ${degree1}; ${func2}: bit2 = ${bit2} degree = ${degree2}" + echo -e "${bit1}\t${degree1}\t${bit2}\t${degree2}" > ${temp_file} + cd .. + ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + cd - >/dev/null + taskset -c 0 ./testPerformanceOneManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} | tee -a ${temp_file} + awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} + echo +done + +cp ${expr_bkp_file} ${expr_file} +echo "The data is logged into ${log_file}" \ No newline at end of file diff --git a/srcTest/init.sh b/srcTest/init.sh new file mode 100644 index 0000000..070a3de --- /dev/null +++ b/srcTest/init.sh @@ -0,0 +1,32 @@ +func1=sin +func2=tan +path_TGen=/home/xyy/helloBro/TGen +path_func1=${path_TGen}/${func1}_gen +path_func2=${path_TGen}/${func2}_gen + +# init for error detection and performance detection +uniqueLabel=NMSEproblem345 +x0Start=0.01 +x0End=100 +x0Size=500000 +x0startNowIdx=0 +x0startOriginInterval=0.01 +stepX0=0.00019998 +prefix=expr_${uniqueLabel} +middle=${x0Start} +suffix=origin +errfile=0 + +# init for the expression code file +expr_file=${uniqueLabel}/${prefix}_${suffix}.c +expr_bkp_file=${uniqueLabel}/${prefix}_${suffix}_bkp.c +if [ -f "${expr_bkp_file}" ]; then + cp ${expr_bkp_file} ${expr_file} +else + echo "ERROR" + exit +fi +sed -i "1a\#include \"${func1}_gen.c\"" ${expr_file} +sed -i "2a\#include \"${func2}_gen.c\"" ${expr_file} +sed -i "s@${func1}(@${func1}_gen(@g" ${expr_file} +sed -i "s@${func2}(@${func2}_gen(@g" ${expr_file} \ No newline at end of file diff --git a/srcTest/pareto_2.py b/srcTest/pareto_2.py deleted file mode 100644 index 11e5f07..0000000 --- a/srcTest/pareto_2.py +++ /dev/null @@ -1,81 +0,0 @@ -import pandas as pd -import itertools - -# 读取2个文件,对应表达式中的两个函数。每个文件有2列,对应函数的误差和性能。 -def geneData(): - # 读取文件并将数据存储在 DataFrame 中 - func1 = pd.read_csv("func1.csv", delimiter='\t', dtype={0: str}) - func2 = pd.read_csv("func2.csv", delimiter='\t', dtype={0: str}) - - # 获取第一列数据 - error1 = func1.iloc[:, 0].tolist() - error2 = func2.iloc[:, 0].tolist() - - # 转换为浮点数 - error1 = [float(x) for x in error1] - error2 = [float(x) for x in error2] - - # 获取第二列数据 - perf1 = func1.iloc[:, 1].tolist() - perf2 = func2.iloc[:, 1].tolist() - - - # 对error和perf两个数据列表进行两两组合求和,并存储在新的数组中 - result1 = [] - for pair in itertools.product(error1, error2): - sum = pair[0] + pair[1] - result1.append(sum) - - result2 = [] - for pair in itertools.product(perf1, perf2): - sum = pair[0] + pair[1] - result2.append(sum) - - result = [] - for error, perf in zip(result1, result2): - pair = (error, perf) - result.append(pair) - - # 按科学计数法输出结果 - # for num in result1: - # print(f"{num:.2e}", end=' ') - # print(f"\nLength of 'result2' array: {len(result2)}") - # for pair in result: - # print(f"error: {pair[0]:.2e}, perf: {pair[1]}") - - return result - -def pareto_optimal(points): - pareto_points = [] - - for i in range(len(points)): - is_pareto = True - x1, y1 = points[i] - - for j in range(len(points)): - x2, y2 = points[j] - if x2 < x1 and y2 < y1: - is_pareto = False - break - - if is_pareto: - pareto_points.append((x1, y1, i)) - - return pareto_points - -# 默认读取2个文件:func1.csv func2.csv,分别存储的是两个函数的误差-开销信息 -if __name__ == '__main__': - # input_points = [(1, 5), (2, 4), (1, 3), (2, 1), (3, 3), (4, 2), (5, 1)] - input_points = geneData() - - pareto_result = pareto_optimal(input_points) - - # 输出符合帕累托最优化的点集 - print("符合帕累托最优化的点集:") - for pair in pareto_result: - print(f"No.{pair[2]}: error: {pair[0]:.2e}, perf: {pair[1]}") - print(f"\nLength of 'pareto_optimal points': {len(pareto_result)}") - for pair in pareto_result: - print(f"{pair[0]:.2e} {pair[1]}") - # for point in pareto_result: - # print(point) \ No newline at end of file diff --git a/srcTest/pareto_2Files.py b/srcTest/pareto_2Files.py new file mode 100644 index 0000000..1c82294 --- /dev/null +++ b/srcTest/pareto_2Files.py @@ -0,0 +1,87 @@ +import pandas as pd +import itertools +import math + +condNumSin = 8.943225 +condNumTan = 1.07E+00 + +# 读取2个文件,对应表达式中的两个函数。每个文件有2列,对应函数的误差和性能。 +def geneData(file1, file2): + # 读取文件并将数据存储在 DataFrame 中 + func1 = pd.read_csv(file1, sep='\t') # sin + func2 = pd.read_csv(file2, sep='\t') # tan + + # regime + regime1 = func1["regime"] + regime2 = func2["regime"] + + # degree + degree1 = func1["degree"] + degree2 = func2["degree"] + + # 平均误差 + error1 = func1["averageErr"] + error2 = func2["averageErr"] + + # 将平均误差的字符串数据转换为浮点数 + error1 = [float(x) for x in error1] + error2 = [float(x) for x in error2] + + # 性能节拍 + perf1 = func1["performance"] + perf2 = func2["performance"] + + # 两两组合 + result = [] + for i in range(len(error1)): + for j in range(len(error2)): + # errorSum = error1[i] + error2[j] # !!! 这里是关键,关键在于要不要从error变成epsilon。 + errorSum = error1[i] * condNumSin + error2[j] * condNumTan # !!! 这里是关键,关键在于要不要从error变成epsilon。 + perfSum = perf1[i] + perf2[j] + pair = (regime1[i], degree1[i], degree1[j], degree2[j], errorSum, perfSum) + result.append(pair) + return result + +def pareto_optimal(points): + pareto_points = [] + is_pareto = [True] * len(points) + for i in range(len(points)): + # if is_pareto[i] == False: + # continue + + regime1, degree1, regime2, degree2, err, cost = points[i] + + for j in range(len(points)): + # if is_pareto[j] == False: + # continue + if j == i: + continue + err2 = points[j][4] + cost2 = points[j][5] + if (err2 < err) and (cost2 <= cost): + is_pareto[i] = False + break + + for i in range(len(points)): + if is_pareto[i]: + pareto_points.append(points[i]) + + return pareto_points + +def writeToFile(data, file_path): + # file_path = 'output.csv' + + with open(file_path, 'w') as file: + file.write(f"regime1\tdegree1\tregime2\tdegree2\tepsilon\tcost\n") + for item in data: + # file.write(f"{item[2]} {item[0]:.6e} {item[1]}\n") + file.write(f"{item[0]}\t{item[1]}\t{item[2]}\t{item[3]}\t{item[4]:.6e}\t{item[5]}\n") + print("output file is %s"%(str(file_path))) + +# 默认读取2个文件:func1.csv func2.csv,分别存储的是两个函数的误差-开销信息 +if __name__ == '__main__': + input_points = geneData("sinInput.csv", "tanInput.csv") + + pareto_result = pareto_optimal(input_points) + print(f"\nLength of 'pareto_optimal points': {len(pareto_result)}") + writeToFile(pareto_result, "NMSEproblem345ParetoOutput.csv") \ No newline at end of file diff --git a/srcTest/pareto_all.sh b/srcTest/pareto_all.sh new file mode 100755 index 0000000..a5d18f8 --- /dev/null +++ b/srcTest/pareto_all.sh @@ -0,0 +1,7 @@ +# !!! 缺少对函数input.csv 的预处理,即去除低精度代码 +python3 pareto_singleFunc.py sin +python3 pareto_singleFunc.py tan +python3 combine_2.py +./getRealErrCost.sh +python3 pareto_twoFunc.py +python3 sortData.py \ No newline at end of file diff --git a/srcTest/pareto_singleFunc.py b/srcTest/pareto_singleFunc.py new file mode 100644 index 0000000..0e092cf --- /dev/null +++ b/srcTest/pareto_singleFunc.py @@ -0,0 +1,94 @@ +import pandas as pd +import sys + +condNumSin = 8.943225 +condNumTan = 1.07E+00 + +# 读取1个文件,对应表达式中的两个函数。每个文件有2列,对应函数的误差和性能。 +def geneData(file1): + # 读取文件并将数据存储在 DataFrame 中 + func1 = pd.read_csv(file1, sep='\t') # sin + + # regime + regime1 = func1["regime"] + + # degree + degree1 = func1["degree"] + + # 平均误差 + error1 = func1["averageErr"] + + # 将平均误差的字符串数据转换为浮点数 + error1 = [float(x) for x in error1] + + # 性能节拍 + perf1 = func1["performance"] + + # 两两组合 + result = [] + for i in range(len(error1)): + # errorSum = error1[i] + error2[j] # !!! 这里是关键,关键在于要不要从error变成epsilon。 + errorSum = error1[i] + perfSum = perf1[i] + pair = (regime1[i], degree1[i], errorSum, perfSum) + result.append(pair) + return result + +def pareto_optimal(points): + pareto_points = [] + is_pareto = [True] * len(points) + for i in range(len(points)): + # if is_pareto[i] == False: + # continue + + err1 = points[i][2] + cost1 = points[i][3] + + for j in range(len(points)): + # if is_pareto[j] == False: + # continue + if j == i: + continue + err2 = points[j][2] + cost2 = points[j][3] + if (err2 < err1) and (cost2 <= cost1): + is_pareto[i] = False + break + + for i in range(len(points)): + if is_pareto[i]: + pareto_points.append(points[i]) + + return pareto_points + +def writeToFile(data, file_path): + # file_path = 'output.csv' + + with open(file_path, 'w') as file: + file.write(f"regime\tdegree\taverageErr\tperformance\n") + for item in data: + file.write(f"{item[0]}\t{item[1]}\t{item[2]:.6e}\t{item[3]}\n") + print("output file is %s"%(str(file_path))) + +# 默认读取1个文件:func1.csv,存储的是函数的误差-开销信息 +if __name__ == '__main__': + # 读取命令行参数 + arguments = sys.argv + + func = "tan" + # 检查是否传递了参数 + if len(arguments) > 2: + print("please input only one paremeter!") + sys.exit(1) + elif len(arguments) > 1: + func = arguments[1] + + funcInputFile = func + "Input.csv" + funcOutputFile = func + "Output.csv" + input_points = geneData(funcInputFile) + + pareto_result = pareto_optimal(input_points) + + # 输出符合帕累托最优化的点集 + print(f"\nLength of 'pareto_optimal points': {len(pareto_result)}") + writeToFile(pareto_result, funcOutputFile) \ No newline at end of file diff --git a/srcTest/pareto_twoFunc.py b/srcTest/pareto_twoFunc.py new file mode 100644 index 0000000..bbe0990 --- /dev/null +++ b/srcTest/pareto_twoFunc.py @@ -0,0 +1,54 @@ +import pandas as pd + +def geneData(file1): + data = pd.read_csv(file1, sep='\t') + return data.values.tolist() + +def pareto_optimal(points): + pareto_points = [] + is_pareto = [True] * len(points) + for i in range(len(points)): + # if is_pareto[i] == False: + # continue + + err1 = points[i][4] + cost1 = points[i][5] + + for j in range(len(points)): + # if is_pareto[j] == False: + # continue + if j == i: + continue + err2 = points[j][4] + cost2 = points[j][5] + if (err2 <= err1) and (cost2 <= cost1): + is_pareto[i] = False + break + + for i in range(len(points)): + if is_pareto[i]: + pareto_points.append(points[i]) + + return pareto_points + +def writeToFile(data, file_path, func1, func2): + with open(file_path, 'w') as file: + file.write(f"{func1}_regime1\tdegree1\t{func2}_regime2\tdegree2\terror\tperformance\n") + for item in data: + file.write(f"{int(item[0])}\t{int(item[1])}\t{int(item[2])}\t{int(item[3])}\t{item[4]:.7e}\t{int(item[5])}\n") + print("output file is %s"%(str(file_path))) + +# 默认读取1个文件:func1.csv,存储的是函数的误差-开销信息 +if __name__ == '__main__': + expr = "NMSEproblem345" + inputFile = expr + "_errPerf.csv" + outputFile = expr + "_errPerfPareto.csv" + func1 = "sin" + func2 = "tan" + + input_points = geneData(inputFile) + pareto_result = pareto_optimal(input_points) + + # 输出符合帕累托最优化的点集 + print(f"\nLength of 'pareto_optimal points': {len(pareto_result)}") + writeToFile(pareto_result, outputFile, func1, func2) \ No newline at end of file diff --git a/srcTest/readmePareto.md b/srcTest/readmePareto.md new file mode 100644 index 0000000..9227644 --- /dev/null +++ b/srcTest/readmePareto.md @@ -0,0 +1,41 @@ +# 函数级混合精度优化思路 + +## 旧思路 + +第一步: +先用MP脚本生成不同混合精度配置的实际性能-精度二元组信息。 +使用上述数据,构建数据表,即func1.csv,func2.csv +然后调用pareto_2.py脚本,构建混合精度方案的误差-开销二元组。并从中生成帕累托最优集合(帕累托前沿) +第一步得到的信息就是纯作为对比。这是理想情况下能找到的最优组合。 + +第二步(与第一步并行): +执行TGen,生成函数的性能-精度数据 +使用上述数据,构建数据表,即func1.csv,func2.csv +然后调用pareto_2.py脚本,构建混合精度方案的误差-开销二元组。并从中生成帕累托最优集合(帕累托前沿) +这是初步通过估算得到的预测的最优组合。当然此时的组合因为没有实测,其性能-精度数据并不一定对 + +第三步(承接第二步): +把第二步最后得到的帕累托最优集合,再重新用MP脚本测一下表达式的性能-精度二元组数据。 +然后再对实测的二元组信息执行帕累托优化。 + + +## 新思路 + +步骤: + +0. 预处理:把误差低于float32的都删除 +1. 先用 pareto_singleFunc.py 生成各函数的帕累托优化结果 (NMSEproblem345 sin tan) +2. 再用 combine_2.py 将其两两组合,生成所有可能的混合精度方案 +3. 再用 getRealErrCost.sh 对所有的混合精度方案进行测试,生成表达式的实际值构成的误差-开销二元组集合 +4. 再用 pareto_twoFunc.py 对该集合执行帕累托优化,缩小数量 +5. 最后用 sortData.py 对混合精度方案按照误差升序排序 + +对应的执行脚本: +```shell +python3 pareto_singleFunc.py sin +python3 pareto_singleFunc.py tan +python3 combine_2.py +./getRealErrCost.sh +python3 pareto_twoFunc.py +python3 sortData.py +``` \ No newline at end of file diff --git a/srcTest/sortData.py b/srcTest/sortData.py new file mode 100644 index 0000000..f8b2f46 --- /dev/null +++ b/srcTest/sortData.py @@ -0,0 +1,36 @@ +import csv + +def sort_csv_by_column(csv_file, sort_column, output_file, func1, func2): + # 读取CSV文件数据 + data = [] + with open(csv_file, 'r') as file: + lines = file.readlines() + + # 跳过第一行 + lines = lines[1:] + + for line in lines: + row = line.strip().split('\t') + data.append(row) + + # 按照指定列进行排序 + sorted_data = sorted(data, key=lambda row: float(row[sort_column])) + + # 将排序后的结果写入新文件 + with open(output_file, 'w', newline='') as file: + csv_writer = csv.writer(file, delimiter = "\t") + header = [f"{func1}_regime1", "degree1", f"{func2}_regime2", "degree2", "error", "performance", ] + csv_writer.writerow(header) + csv_writer.writerows(sorted_data) + print("input file: %s"%(csv_file)) + print("output file: %s"%(output_file)) + +# 按照第 sort_column 列数据对 inputFile 文件进行排序,结果写入 outputFile 文件 +if __name__ == '__main__': + uniqueLabel = "NMSEproblem345" + inputFile = uniqueLabel + "_errPerfPareto.csv" + outputFile = uniqueLabel + "_errPerfParetoSorted.csv" + sort_column = int(4) # 说明表达式中有2个函数,故第5列才是平均误差 + func1 = "sin" + func2 = "tan" + sort_csv_by_column(inputFile, sort_column, outputFile, func1, func2) \ No newline at end of file -- Gitee From 6c0a81da7f19e54f295f464f5551e8a7af680347 Mon Sep 17 00:00:00 2001 From: hjw Date: Mon, 18 Sep 2023 16:36:46 +0800 Subject: [PATCH 40/54] Implement pareto method with one function taking exp1x as the example. --- srcTest/exprMap.sh | 17 ++++++ srcTest/getRealErrCost_1.sh | 110 +++++++++++++++++++++++++++++++++++ srcTest/pareto_all_1.sh | 8 +++ srcTest/pareto_singleFunc.py | 41 ++++++++----- srcTest/readmePareto.md | 26 ++++++++- srcTest/sortData.py | 69 ++++++++++++++++++---- 6 files changed, 242 insertions(+), 29 deletions(-) create mode 100644 srcTest/exprMap.sh create mode 100755 srcTest/getRealErrCost_1.sh create mode 100755 srcTest/pareto_all_1.sh diff --git a/srcTest/exprMap.sh b/srcTest/exprMap.sh new file mode 100644 index 0000000..044632e --- /dev/null +++ b/srcTest/exprMap.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# 定义关联数组,模拟map +declare -A x0Starts=( + ["NMSEproblem345"]=0.01 + ["exp1x"]=0.01 +) + +declare -A x0Ends=( + ["NMSEproblem345"]=100 + ["exp1x"]=0.5 +) + +declare -A stepX0s=( + ["NMSEproblem345"]=0.00019998 + ["exp1x"]=9.8e-07 +) \ No newline at end of file diff --git a/srcTest/getRealErrCost_1.sh b/srcTest/getRealErrCost_1.sh new file mode 100755 index 0000000..13303fd --- /dev/null +++ b/srcTest/getRealErrCost_1.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# set -x + +# 多精度版本函数的路径是TGen的路径,特定于北京服务器的固定路径。 +# getRealErrCost_1 脚本的测试对象是帕累托优化得到的所有混合精度方案,用来验证帕累托优化效果 +# getRealErrCost_1 脚本从 funcOutput.csv 中读取数据。该数据是利用 pareto_singleFunc.py 生成的。 +# pareto_singleFunc.py 是根据函数的测试信息,生成帕累托优化结果。 +# pareto_singleFunc.py 中的数据是从 funcInput.csv 中获取得来的 + +# 与 getRealErrCost_1 脚本功能类似的是 MPMF_1.sh。 +# MPMF_1.sh 脚本是直接测试所有不同的混合精度组合下的表达式“误差-性能”信息。 + +# init for mix-precision +source funcMap.sh +source exprMap.sh + +# init for error detection and performance detection +if [ $# == 2 ]; then + uniqueLabel=${1} + x0Start=${x0Starts[${uniqueLabel}]} + x0End=${x0Ends[${uniqueLabel}]} + stepX0=${stepX0s[${uniqueLabel}]} + + func1=${2} +elif [ $# == 1 ]; then + uniqueLabel=${1} + x0Start=${x0Starts[${uniqueLabel}]} + x0End=${x0Ends[${uniqueLabel}]} + stepX0=${stepX0s[${uniqueLabel}]} + + func1=sin +else + uniqueLabel="NMSEproblem345" + x0Start=0.01 + x0End=100 + stepX0=0.00019998 + + func1=sin +fi + +x0Size=500000 +x0startNowIdx=0 +x0startOriginInterval=${x0Start} +prefix=expr_${uniqueLabel} +middle=${x0Start} +suffix=origin +errfile=0 + +# init for TGen +path_TGen=/home/xyy/helloBro/TGen +path_func1=${path_TGen}/${func1}_gen + +# init for the expression code file +expr_file=${uniqueLabel}/${prefix}_${suffix}.c +expr_bkp_file=${uniqueLabel}/${prefix}_${suffix}_bkp.c +if [ -f "${expr_bkp_file}" ]; then + cp ${expr_bkp_file} ${expr_file} +else + echo "ERROR" + exit +fi +sed -i "1a\#include \"${func1}_gen.c\"" ${expr_file} +sed -i "s@${func1}(@${func1}_gen(@g" ${expr_file} + +# 读取CSV文件,保存到数组 +csv_file="${uniqueLabel}Output.csv" +data_array=() + +# init for current path +path_current=`pwd` +temp_file=${path_current}/temp.log # 临时文件,在循环中被刷新 +log_file=${path_current}/${uniqueLabel}_errPerf.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 + +# 解析 csv 文件,保存到数组 data_array +while IFS=$'\t' read -r -a cols +do + data=() + for ((i=0; i<${#cols[@]}; i++)) + do + if [ $i -lt 4 ]; then # 只保存前4列数据 + data+=("${cols[i]}") + fi + done + data_array+=("${data[@]}") +done < <(tail -n +2 "$csv_file") # 从第二行开始读取文件,跳过标题行 + +# loop to generate different version +echo -e "${func1}_regime\tdegree\taverageErr\tperformance" > ${log_file} +step=4 +for ((i=0; i<${#data_array[@]}; i+=step)) +do + # echo "Batch $((i/step+1)): ${data_array[@]:i:step}" + bit1=${data_array[i]} + degree1=${data_array[i+1]} + + # echo "当前参数:$bit1 $degree1 $bit2 $degree2" + cp ${path_func1}/${func1}_gen_${bit1}_1_${degree1}.c ${uniqueLabel}/${func1}_gen.c + echo "${func1}: bit = ${bit1} degree = ${degree1}" + echo -e "${bit1}\t${degree1}" > ${temp_file} + cd .. + ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + cd - >/dev/null + taskset -c 0 ./testPerformanceOneManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} | tee -a ${temp_file} + awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} + echo +done + +cp ${expr_bkp_file} ${expr_file} +echo "Input file: ${csv_file}" +echo "Output file: ${uniqueLabel}_errPerf.csv" \ No newline at end of file diff --git a/srcTest/pareto_all_1.sh b/srcTest/pareto_all_1.sh new file mode 100755 index 0000000..0bd9bc3 --- /dev/null +++ b/srcTest/pareto_all_1.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -x +# !!! 缺少对函数input.csv 的预处理,即去除低精度代码 + +python3 pareto_singleFunc.py exp_gen_0.01-0.5 +./getRealErrCost_1.sh exp1x exp +python3 pareto_singleFunc.py exp1x exp +python3 sortData.py exp1x exp \ No newline at end of file diff --git a/srcTest/pareto_singleFunc.py b/srcTest/pareto_singleFunc.py index 0e092cf..3d15a5a 100644 --- a/srcTest/pareto_singleFunc.py +++ b/srcTest/pareto_singleFunc.py @@ -4,25 +4,25 @@ import sys condNumSin = 8.943225 condNumTan = 1.07E+00 -# 读取1个文件,对应表达式中的两个函数。每个文件有2列,对应函数的误差和性能。 -def geneData(file1): +# 读取1个文件,对应表达式中的函数。每个文件有若干列,但只需要 regime 和 degree 这2列,对应函数的误差和性能。 +def geneData(file1, regimeStr): # 读取文件并将数据存储在 DataFrame 中 - func1 = pd.read_csv(file1, sep='\t') # sin + csvReader = pd.read_csv(file1, sep='\t') # sin # regime - regime1 = func1["regime"] + regime1 = csvReader[regimeStr] # degree - degree1 = func1["degree"] + degree1 = csvReader["degree"] # 平均误差 - error1 = func1["averageErr"] + error1 = csvReader["averageErr"] # 将平均误差的字符串数据转换为浮点数 error1 = [float(x) for x in error1] # 性能节拍 - perf1 = func1["performance"] + perf1 = csvReader["performance"] # 两两组合 result = [] @@ -68,7 +68,6 @@ def writeToFile(data, file_path): file.write(f"regime\tdegree\taverageErr\tperformance\n") for item in data: file.write(f"{item[0]}\t{item[1]}\t{item[2]:.6e}\t{item[3]}\n") - print("output file is %s"%(str(file_path))) # 默认读取1个文件:func1.csv,存储的是函数的误差-开销信息 if __name__ == '__main__': @@ -76,19 +75,29 @@ if __name__ == '__main__': arguments = sys.argv func = "tan" + funcInputFile = func + "Input.csv" + funcOutputFile = func + "Output.csv" + regimeStr="regime" # 检查是否传递了参数 - if len(arguments) > 2: + if len(arguments) > 3: print("please input only one paremeter!") sys.exit(1) - elif len(arguments) > 1: - func = arguments[1] - - funcInputFile = func + "Input.csv" - funcOutputFile = func + "Output.csv" - input_points = geneData(funcInputFile) + elif len(arguments) == 3: # 表达式中只有一个函数。用于实测性能误差后的对表达式的帕累托优化 + funcInputFile = arguments[1] + "_errPerf.csv" # arguments[1] 为 exp1x, 即优化表达式 + funcOutputFile = arguments[1] + "_errPerfPareto.csv" + func = arguments[2] # arguments[1] 为 exp, 即优化函数 + regimeStr = func + "_regime" + elif len(arguments) == 2: # 用于一开始针对单个函数的帕累托优化 + func = arguments[1] # arguments[1] 为 exp, 即优化函数 + funcInputFile = func + "Input.csv" + funcOutputFile = func + "Output.csv" + + input_points = geneData(funcInputFile, regimeStr) pareto_result = pareto_optimal(input_points) # 输出符合帕累托最优化的点集 print(f"\nLength of 'pareto_optimal points': {len(pareto_result)}") - writeToFile(pareto_result, funcOutputFile) \ No newline at end of file + writeToFile(pareto_result, funcOutputFile) + print("Input file is %s"%(str(funcInputFile))) + print("Output file is %s"%(str(funcOutputFile))) \ No newline at end of file diff --git a/srcTest/readmePareto.md b/srcTest/readmePareto.md index 9227644..367131f 100644 --- a/srcTest/readmePareto.md +++ b/srcTest/readmePareto.md @@ -21,7 +21,7 @@ ## 新思路 -步骤: +双函数的步骤: 0. 预处理:把误差低于float32的都删除 1. 先用 pareto_singleFunc.py 生成各函数的帕累托优化结果 (NMSEproblem345 sin tan) @@ -30,7 +30,10 @@ 4. 再用 pareto_twoFunc.py 对该集合执行帕累托优化,缩小数量 5. 最后用 sortData.py 对混合精度方案按照误差升序排序 -对应的执行脚本: +双函数执行脚本: + +shell script name: pareto_all.sh + ```shell python3 pareto_singleFunc.py sin python3 pareto_singleFunc.py tan @@ -38,4 +41,23 @@ python3 combine_2.py ./getRealErrCost.sh python3 pareto_twoFunc.py python3 sortData.py +``` + +单函数的步骤: + +0. 预处理:把误差低于float32的都删除 +1. 先用 pareto_singleFunc.py 生成函数的帕累托优化结果 (exp1x exp) +2. 再用 getRealErrCost_1.sh 对所有的混合精度方案进行测试,生成表达式的实际值构成的误差-开销二元组集合 +3. 再用 pareto_singleFunc.py 对该集合执行帕累托优化,缩小数量 +4. 最后用 sortData.py 对混合精度方案按照误差升序排序 + +单函数执行脚本: + +shell script name: pareto_all_1.sh + +```shell +python3 pareto_singleFunc.py exp_gen_0.01-0.5 +./getRealErrCost_1.sh exp1x exp +python3 pareto_singleFunc.py exp1x exp +python3 sortData.py exp1x exp ``` \ No newline at end of file diff --git a/srcTest/sortData.py b/srcTest/sortData.py index f8b2f46..3e5ee11 100644 --- a/srcTest/sortData.py +++ b/srcTest/sortData.py @@ -1,6 +1,7 @@ import csv +import sys -def sort_csv_by_column(csv_file, sort_column, output_file, func1, func2): +def sort_csv_by_column(csv_file, output_file, sort_column, func1, func2): # 读取CSV文件数据 data = [] with open(csv_file, 'r') as file: @@ -19,18 +20,64 @@ def sort_csv_by_column(csv_file, sort_column, output_file, func1, func2): # 将排序后的结果写入新文件 with open(output_file, 'w', newline='') as file: csv_writer = csv.writer(file, delimiter = "\t") - header = [f"{func1}_regime1", "degree1", f"{func2}_regime2", "degree2", "error", "performance", ] + header = [f"{func1}_regime1", "degree1", f"{func2}_regime2", "degree2", "averageErr", "performance", ] csv_writer.writerow(header) csv_writer.writerows(sorted_data) - print("input file: %s"%(csv_file)) - print("output file: %s"%(output_file)) + print("Input file: %s"%(csv_file)) + print("Output file: %s"%(output_file)) + + +def sort_csv_by_column_1(csv_file, output_file, sort_column, func1): + # 读取CSV文件数据 + data = [] + with open(csv_file, 'r') as file: + lines = file.readlines() + + # 跳过第一行 + lines = lines[1:] + + for line in lines: + row = line.strip().split('\t') + data.append(row) + + # 按照指定列进行排序 + sorted_data = sorted(data, key=lambda row: float(row[sort_column])) + + # 将排序后的结果写入新文件 + with open(output_file, 'w', newline='') as file: + csv_writer = csv.writer(file, delimiter = "\t") + header = [f"{func1}_regime", "degree", "averageErr", "performance", ] + csv_writer.writerow(header) + csv_writer.writerows(sorted_data) + print("Input file: %s"%(csv_file)) + print("Output file: %s"%(output_file)) + # 按照第 sort_column 列数据对 inputFile 文件进行排序,结果写入 outputFile 文件 if __name__ == '__main__': - uniqueLabel = "NMSEproblem345" - inputFile = uniqueLabel + "_errPerfPareto.csv" - outputFile = uniqueLabel + "_errPerfParetoSorted.csv" - sort_column = int(4) # 说明表达式中有2个函数,故第5列才是平均误差 - func1 = "sin" - func2 = "tan" - sort_csv_by_column(inputFile, sort_column, outputFile, func1, func2) \ No newline at end of file + # 读取命令行参数 + arguments = sys.argv + + # 检查是否传递了参数 + if len(arguments) > 3: + print("please input only 2 paremeters or none paremeter!") + sys.exit(1) + elif len(arguments) == 3: # 表达式中只有一个函数。用于实测性能误差后的对表达式的帕累托优化 + uniqueLabel = arguments[1] # arguments[2] 为 exp1x, 即优化表达式 + + inputFile = uniqueLabel + "_errPerfPareto.csv" + outputFile = uniqueLabel + "_errPerfParetoSorted.csv" + sort_column = int(2) # 说明表达式中有1个函数,故第3列才是平均误差 + func1 = arguments[2] # arguments[1] 为 exp, 即优化函数 + + sort_csv_by_column_1(inputFile, outputFile, sort_column, func1) + elif len(arguments) == 1: # 没有输入,对应的是之前的默认情况,即 NMSEproblem345 + uniqueLabel = "NMSEproblem345" + + inputFile = uniqueLabel + "_errPerfPareto.csv" + outputFile = uniqueLabel + "_errPerfParetoSorted.csv" + sort_column = int(4) # 说明表达式中有2个函数,故第5列才是平均误差 + func1 = "sin" + func2 = "tan" + + sort_csv_by_column(inputFile, outputFile, sort_column, func1, func2) \ No newline at end of file -- Gitee From 92de2f78db627a556e7edbc0c0f6f9b0064e43c8 Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 19 Sep 2023 09:00:07 +0800 Subject: [PATCH 41/54] Improve pareto taking NMSEexample34 as example. --- srcTest/combine_2.py | 15 ++++++++++ srcTest/exprMap.sh | 3 ++ srcTest/getOriginErrCost.sh | 15 ++++++++++ srcTest/getRealErrCost.sh | 58 +++++++++++++++++++++++++++++++++++-- srcTest/pareto_all.sh | 20 +++++++++---- srcTest/pareto_all_1.sh | 1 + srcTest/pareto_twoFunc.py | 18 ++++++++++-- srcTest/sortData.py | 14 +++++++-- 8 files changed, 131 insertions(+), 13 deletions(-) create mode 100755 srcTest/getOriginErrCost.sh diff --git a/srcTest/combine_2.py b/srcTest/combine_2.py index 63a6961..97029fa 100644 --- a/srcTest/combine_2.py +++ b/srcTest/combine_2.py @@ -1,4 +1,5 @@ import pandas as pd +import sys import itertools import math @@ -86,5 +87,19 @@ if __name__ == '__main__': func2OutputFile = func2 + "Output.csv" uniqueLabel = "NMSEproblem345" outputFile = uniqueLabel + "Output.csv" + # 读取命令行参数 + arguments = sys.argv + # 检查是否传递了参数 + if len(arguments) > 4: + print("please input only 2 paremeters or none paremeter!") + sys.exit(1) + elif len(arguments) == 4: + uniqueLabel = arguments[1] + func1 = arguments[2] # arguments[2] 为 sin, 即优化函数 + func2 = arguments[3] # arguments[3] 为 cos, 即优化函数 + func1OutputFile = func1 + "Output.csv" + func2OutputFile = func2 + "Output.csv" + outputFile = uniqueLabel + "Output.csv" + input_points = geneData(func1OutputFile, func2OutputFile) writeToFile(input_points, outputFile) \ No newline at end of file diff --git a/srcTest/exprMap.sh b/srcTest/exprMap.sh index 044632e..5148e77 100644 --- a/srcTest/exprMap.sh +++ b/srcTest/exprMap.sh @@ -4,14 +4,17 @@ declare -A x0Starts=( ["NMSEproblem345"]=0.01 ["exp1x"]=0.01 + ["NMSEexample34"]=0.01 ) declare -A x0Ends=( ["NMSEproblem345"]=100 ["exp1x"]=0.5 + ["NMSEexample34"]=3 ) declare -A stepX0s=( ["NMSEproblem345"]=0.00019998 ["exp1x"]=9.8e-07 + ["NMSEexample34"]=5.98e-06 ) \ No newline at end of file diff --git a/srcTest/getOriginErrCost.sh b/srcTest/getOriginErrCost.sh new file mode 100755 index 0000000..a3f008e --- /dev/null +++ b/srcTest/getOriginErrCost.sh @@ -0,0 +1,15 @@ +cd .. +./detectErrorOneFPEDParallel.sh NMSEproblem345 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem345 0.01_100_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEproblem345 origin 0.01 100 + +cd .. +./detectErrorOneFPEDParallel.sh exp1x 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x 0.01_0.5_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh exp1x origin 0.01 0.5 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEexample34 0.01 3 500000 0 0.01 5.98e-06 expr_NMSEexample34 0.01_3_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEexample34 origin 0.01 3 + diff --git a/srcTest/getRealErrCost.sh b/srcTest/getRealErrCost.sh index 73d8f30..805e2d3 100755 --- a/srcTest/getRealErrCost.sh +++ b/srcTest/getRealErrCost.sh @@ -14,10 +14,64 @@ # init for mix-precision source funcMap.sh -source init.sh +source exprMap.sh +# source init.sh + +# init for error detection and performance detection +if [ $# == 3 ]; then + uniqueLabel=${1} + x0Start=${x0Starts[${uniqueLabel}]} + x0End=${x0Ends[${uniqueLabel}]} + stepX0=${stepX0s[${uniqueLabel}]} + + func1=${2} + func2=${3} +elif [ $# == 1 ]; then + uniqueLabel=${1} + x0Start=${x0Starts[${uniqueLabel}]} + x0End=${x0Ends[${uniqueLabel}]} + stepX0=${stepX0s[${uniqueLabel}]} + + func1=sin + func2=tan +else + uniqueLabel="NMSEproblem345" + x0Start=0.01 + x0End=100 + stepX0=0.00019998 + + func1=sin + func2=tan +fi + +x0Size=500000 +x0startNowIdx=0 +x0startOriginInterval=${x0Start} +prefix=expr_${uniqueLabel} +middle=${x0Start} +suffix=origin +errfile=0 + +# init for TGen +path_TGen=/home/xyy/helloBro/TGen +path_func1=${path_TGen}/${func1}_gen +path_func2=${path_TGen}/${func2}_gen + +# init for the expression code file +expr_file=${uniqueLabel}/${prefix}_${suffix}.c +expr_bkp_file=${uniqueLabel}/${prefix}_${suffix}_bkp.c +if [ -f "${expr_bkp_file}" ]; then + cp ${expr_bkp_file} ${expr_file} +else + echo "ERROR: no ${expr_bkp_file}" + exit +fi +sed -i "1a\#include \"${func1}_gen.c\"" ${expr_file} +sed -i "2a\#include \"${func2}_gen.c\"" ${expr_file} +sed -i "s@${func1}(@${func1}_gen(@g" ${expr_file} +sed -i "s@${func2}(@${func2}_gen(@g" ${expr_file} # 读取CSV文件,保存到数组 -uniqueLabel="NMSEproblem345" csv_file="${uniqueLabel}Output.csv" data_array=() diff --git a/srcTest/pareto_all.sh b/srcTest/pareto_all.sh index a5d18f8..671e882 100755 --- a/srcTest/pareto_all.sh +++ b/srcTest/pareto_all.sh @@ -1,7 +1,15 @@ # !!! 缺少对函数input.csv 的预处理,即去除低精度代码 -python3 pareto_singleFunc.py sin -python3 pareto_singleFunc.py tan -python3 combine_2.py -./getRealErrCost.sh -python3 pareto_twoFunc.py -python3 sortData.py \ No newline at end of file + +uniqueLabel=NMSEexample34 +x0Start=0.01 +x0End=3 +func1=sin +func2=cos + +# NMSEexample34 +python3 pareto_singleFunc.py ${func1}_gen_${x0Start}-${x0End} +python3 pareto_singleFunc.py ${func2}_gen_${x0Start}-${x0End} +python3 combine_2.py ${uniqueLabel} ${func1}_gen_${x0Start}-${x0End} ${func2}_gen_${x0Start}-${x0End} +./getRealErrCost.sh ${uniqueLabel} ${func1} ${func2} +python3 pareto_twoFunc.py ${uniqueLabel} ${func1} ${func2} +python3 sortData.py ${uniqueLabel} ${func1} ${func2} \ No newline at end of file diff --git a/srcTest/pareto_all_1.sh b/srcTest/pareto_all_1.sh index 0bd9bc3..105fde6 100755 --- a/srcTest/pareto_all_1.sh +++ b/srcTest/pareto_all_1.sh @@ -3,6 +3,7 @@ set -x # !!! 缺少对函数input.csv 的预处理,即去除低精度代码 python3 pareto_singleFunc.py exp_gen_0.01-0.5 +cp exp_gen_0.01-0.5Output.csv exp1xOutput.csv ./getRealErrCost_1.sh exp1x exp python3 pareto_singleFunc.py exp1x exp python3 sortData.py exp1x exp \ No newline at end of file diff --git a/srcTest/pareto_twoFunc.py b/srcTest/pareto_twoFunc.py index bbe0990..7ba06db 100644 --- a/srcTest/pareto_twoFunc.py +++ b/srcTest/pareto_twoFunc.py @@ -1,4 +1,5 @@ import pandas as pd +import sys def geneData(file1): data = pd.read_csv(file1, sep='\t') @@ -40,11 +41,22 @@ def writeToFile(data, file_path, func1, func2): # 默认读取1个文件:func1.csv,存储的是函数的误差-开销信息 if __name__ == '__main__': - expr = "NMSEproblem345" - inputFile = expr + "_errPerf.csv" - outputFile = expr + "_errPerfPareto.csv" + uniqueLabel = "NMSEproblem345" func1 = "sin" func2 = "tan" + # 读取命令行参数, 并检查是否传递了参数 + arguments = sys.argv + if len(arguments) > 4: + print("please input only 2 or 3 paremeters or none paremeter!") + sys.exit(1) + elif len(arguments) == 4: # 表达式中只有一个函数。用于实测性能误差后的对表达式的帕累托优化 + uniqueLabel = arguments[1] # arguments[2] 为 NMSEexample34, 即优化表达式 + + func1 = arguments[2] # arguments[1] 为 sin, 即优化函数 + func2 = arguments[3] # arguments[2] 为 cos, 即优化函数 + + inputFile = uniqueLabel + "_errPerf.csv" + outputFile = uniqueLabel + "_errPerfPareto.csv" input_points = geneData(inputFile) pareto_result = pareto_optimal(input_points) diff --git a/srcTest/sortData.py b/srcTest/sortData.py index 3e5ee11..ae92961 100644 --- a/srcTest/sortData.py +++ b/srcTest/sortData.py @@ -59,9 +59,19 @@ if __name__ == '__main__': arguments = sys.argv # 检查是否传递了参数 - if len(arguments) > 3: - print("please input only 2 paremeters or none paremeter!") + if len(arguments) > 4: + print("please input only 2 or 3 paremeters or none paremeter!") sys.exit(1) + elif len(arguments) == 4: # 表达式中只有一个函数。用于实测性能误差后的对表达式的帕累托优化 + uniqueLabel = arguments[1] # arguments[2] 为 NMSEexample34, 即优化表达式 + + inputFile = uniqueLabel + "_errPerfPareto.csv" + outputFile = uniqueLabel + "_errPerfParetoSorted.csv" + sort_column = int(2) # 说明表达式中有1个函数,故第3列才是平均误差 + func1 = arguments[2] # arguments[1] 为 sin, 即优化函数 + func2 = arguments[3] # arguments[2] 为 cos, 即优化函数 + + sort_csv_by_column(inputFile, outputFile, sort_column, func1, func2) elif len(arguments) == 3: # 表达式中只有一个函数。用于实测性能误差后的对表达式的帕累托优化 uniqueLabel = arguments[1] # arguments[2] 为 exp1x, 即优化表达式 -- Gitee From 32438a72473c9391ccfc3fe8bacef59f57035bc6 Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 19 Sep 2023 17:51:50 +0800 Subject: [PATCH 42/54] Improve pareto. Details: Add more examples; config pareto_all scripts. --- srcTest/exprMap.sh | 38 +++++++++++++++++++++++++--- srcTest/getOriginErrCost.sh | 28 +++++++++++++++++++-- srcTest/getRealErrCost_1.sh | 2 +- srcTest/pareto_all.sh | 50 +++++++++++++++++++++++++++++++------ srcTest/pareto_all_1.sh | 32 +++++++++++++++++++----- srcTest/pareto_all_list.sh | 39 +++++++++++++++++++++++++++++ 6 files changed, 169 insertions(+), 20 deletions(-) create mode 100644 srcTest/pareto_all_list.sh diff --git a/srcTest/exprMap.sh b/srcTest/exprMap.sh index 5148e77..5b5b405 100644 --- a/srcTest/exprMap.sh +++ b/srcTest/exprMap.sh @@ -3,18 +3,50 @@ # 定义关联数组,模拟map declare -A x0Starts=( ["NMSEproblem345"]=0.01 - ["exp1x"]=0.01 ["NMSEexample34"]=0.01 + ["logexp"]=-8 + ["NMSEproblem343"]=-1 + ["exp1x"]=0.01 + ["NMSEexample37"]=0.01 + ["NMSEexample39"]=0.01 + ["NMSEproblem341"]=0.01 ) declare -A x0Ends=( ["NMSEproblem345"]=100 - ["exp1x"]=0.5 ["NMSEexample34"]=3 + ["logexp"]=8 + ["NMSEproblem343"]=1 + ["exp1x"]=0.5 + ["NMSEexample37"]=100 + ["NMSEexample39"]=1 + ["NMSEproblem341"]=100 ) declare -A stepX0s=( ["NMSEproblem345"]=0.00019998 - ["exp1x"]=9.8e-07 ["NMSEexample34"]=5.98e-06 + ["logexp"]=3.2e-05 + ["NMSEproblem343"]=4e-06 + ["exp1x"]=9.8e-07 + ["NMSEexample37"]=0.00019998 + ["NMSEexample39"]=1.98e-06 + ["NMSEproblem341"]=0.00019998 +) + +declare -A func1s=( + ["NMSEproblem345"]=sin + ["NMSEexample34"]=cos + ["logexp"]=exp + ["NMSEproblem343"]=log + ["exp1x"]=exp + ["NMSEexample37"]=exp + ["NMSEexample39"]=tan + ["NMSEproblem341"]=cos +) + +declare -A func2s=( + ["NMSEproblem345"]=tan + ["NMSEexample34"]=sin + ["logexp"]=log ) \ No newline at end of file diff --git a/srcTest/getOriginErrCost.sh b/srcTest/getOriginErrCost.sh index a3f008e..2610e0b 100755 --- a/srcTest/getOriginErrCost.sh +++ b/srcTest/getOriginErrCost.sh @@ -3,13 +3,37 @@ cd .. cd - >/dev/null ./testPerformanceOneManual.sh NMSEproblem345 origin 0.01 100 +cd .. +./detectErrorOneFPEDParallel.sh NMSEexample34 0.01 3 500000 0 0.01 5.98e-06 expr_NMSEexample34 0.01_3_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEexample34 origin 0.01 3 + +cd .. +./detectErrorOneFPEDParallel.sh logexp -8 8 500000 0 -8 3.2e-05 expr_logexp -8_8_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh logexp origin -8 8 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEproblem343 -1 1 500000 0 -1 4e-06 expr_NMSEproblem343 -1_1_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEproblem343 origin -1 1 + cd .. ./detectErrorOneFPEDParallel.sh exp1x 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x 0.01_0.5_500000 origin 0 cd - >/dev/null ./testPerformanceOneManual.sh exp1x origin 0.01 0.5 cd .. -./detectErrorOneFPEDParallel.sh NMSEexample34 0.01 3 500000 0 0.01 5.98e-06 expr_NMSEexample34 0.01_3_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEexample37 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample37 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEexample34 origin 0.01 3 +./testPerformanceOneManual.sh NMSEexample37 origin 0.01 100 +cd .. +./detectErrorOneFPEDParallel.sh NMSEexample39 0.01 1 500000 0 0.01 1.98e-06 expr_NMSEexample39 0.01_1_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEexample39 origin 0.01 1 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEproblem341 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem341 0.01_100_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEproblem341 origin 0.01 100 diff --git a/srcTest/getRealErrCost_1.sh b/srcTest/getRealErrCost_1.sh index 13303fd..de81c24 100755 --- a/srcTest/getRealErrCost_1.sh +++ b/srcTest/getRealErrCost_1.sh @@ -56,7 +56,7 @@ expr_bkp_file=${uniqueLabel}/${prefix}_${suffix}_bkp.c if [ -f "${expr_bkp_file}" ]; then cp ${expr_bkp_file} ${expr_file} else - echo "ERROR" + echo "ERROR: fail to open ${expr_bkp_file}" exit fi sed -i "1a\#include \"${func1}_gen.c\"" ${expr_file} diff --git a/srcTest/pareto_all.sh b/srcTest/pareto_all.sh index 671e882..bd8edcd 100755 --- a/srcTest/pareto_all.sh +++ b/srcTest/pareto_all.sh @@ -1,15 +1,49 @@ +#!/bin/bash # !!! 缺少对函数input.csv 的预处理,即去除低精度代码 +# set -x +source exprMap.sh -uniqueLabel=NMSEexample34 -x0Start=0.01 -x0End=3 -func1=sin -func2=cos +# init for error detection and performance detection +if [ $# == 5 ]; then + uniqueLabel=${1} + x0Start=${2} + x0End=${3} + x0Start_2=${4} + x0End_2=${5} + func1=${func1s[${uniqueLabel}]} + func2=${func2s[${uniqueLabel}]} + f1=${func1}_gen_${x0Start}-${x0End} + f2=${func2}_gen_${x0Start_2}-${x0End_2} +elif [ $# == 3 ]; then + uniqueLabel=${1} + x0Start=${2} + x0End=${3} + func1=${func1s[${uniqueLabel}]} + func2=${func2s[${uniqueLabel}]} + f1=${func1}_gen_${x0Start}-${x0End} + f2=${func2}_gen_${x0Start}-${x0End} +elif [ $# == 1 ]; then + uniqueLabel=${1} + x0Start=${x0Starts[${uniqueLabel}]} + x0End=${x0Ends[${uniqueLabel}]} + func1=${func1s[${uniqueLabel}]} + func2=${func2s[${uniqueLabel}]} + f1=${func1}_gen_${x0Start}-${x0End} + f2=${func2}_gen_${x0Start}-${x0End} +else + uniqueLabel=NMSEexample34 + x0Start=0.01 + x0End=3 + func1=sin + func2=cos + f1=${func1}_gen_${x0Start}-${x0End} + f2=${func2}_gen_${x0Start}-${x0End} +fi # NMSEexample34 -python3 pareto_singleFunc.py ${func1}_gen_${x0Start}-${x0End} -python3 pareto_singleFunc.py ${func2}_gen_${x0Start}-${x0End} -python3 combine_2.py ${uniqueLabel} ${func1}_gen_${x0Start}-${x0End} ${func2}_gen_${x0Start}-${x0End} +python3 pareto_singleFunc.py ${f1} +python3 pareto_singleFunc.py ${f2} +python3 combine_2.py ${uniqueLabel} ${f1} ${f2} ./getRealErrCost.sh ${uniqueLabel} ${func1} ${func2} python3 pareto_twoFunc.py ${uniqueLabel} ${func1} ${func2} python3 sortData.py ${uniqueLabel} ${func1} ${func2} \ No newline at end of file diff --git a/srcTest/pareto_all_1.sh b/srcTest/pareto_all_1.sh index 105fde6..ad4d5ae 100755 --- a/srcTest/pareto_all_1.sh +++ b/srcTest/pareto_all_1.sh @@ -1,9 +1,29 @@ #!/bin/bash -set -x +# set -x # !!! 缺少对函数input.csv 的预处理,即去除低精度代码 +source exprMap.sh -python3 pareto_singleFunc.py exp_gen_0.01-0.5 -cp exp_gen_0.01-0.5Output.csv exp1xOutput.csv -./getRealErrCost_1.sh exp1x exp -python3 pareto_singleFunc.py exp1x exp -python3 sortData.py exp1x exp \ No newline at end of file +# init for error detection and performance detection +if [ $# == 3 ]; then + uniqueLabel=${1} + x0Start=${2} + x0End=${3} + func1=${func1s[${uniqueLabel}]} +elif [ $# == 1 ]; then + uniqueLabel=${1} + x0Start=${x0Starts[${uniqueLabel}]} + x0End=${x0Ends[${uniqueLabel}]} + func1=${func1s[${uniqueLabel}]} +else + uniqueLabel="exp1x" + x0Start=0.01 + x0End=0.5 + func1=exp +fi +f1=${func1}_gen_${x0Start}-${x0End} + +python3 pareto_singleFunc.py ${f1} +cp ${f1}Output.csv ${uniqueLabel}Output.csv +./getRealErrCost_1.sh ${uniqueLabel} ${func1} +python3 pareto_singleFunc.py ${uniqueLabel} ${func1} +python3 sortData.py ${uniqueLabel} ${func1} \ No newline at end of file diff --git a/srcTest/pareto_all_list.sh b/srcTest/pareto_all_list.sh new file mode 100644 index 0000000..3fda9f2 --- /dev/null +++ b/srcTest/pareto_all_list.sh @@ -0,0 +1,39 @@ +# NMSEproblem345 := (/ (- x (sin x)) (- x (tan x))) +# sin: [0.01, 100] +# tan: [0.01, 100] +taskset -c 0 ./pareto_all.sh NMSEproblem345 + +# NMSEexample34: (/ (- 1 (cos x)) (sin x)) +# sin: [0.01, 100] +# cos: [0.01, 100] +taskset -c 0 ./pareto_all.sh NMSEexample34 + +# logexp := log (+ 1 (exp x)) +# exp: [-8, 8] +# log: [1 + exp(-8), 1 + exp(8)] = [1.000335, 2,981.957987] \approx [1, 2982] +taskset -c 0 ./pareto_all.sh logexp -8 8 1 2982 + +# !!!!!! +# NMSEproblem343 := (log (/ (- 1 eps) (+ 1 eps))) +# eps: [-1, 1] +# log: (0, +infty) +taskset -c 0 ./pareto_all_1.sh exp1x 0.5 1 +# eps: [-1/2, 1/2] +# log: (1/3, 3) +taskset -c 0 ./pareto_all_1.sh exp1x 0.333333 3 + +# exp1x := (exp(x) - 1) / x +# exp: [0.01, 0.5] +taskset -c 0 ./pareto_all_1.sh exp1x + +# NMSEexample37 := exp(x) - 1 +# exp: [0.01, 100] +taskset -c 0 ./pareto_all_1.sh NMSEexample37 + +# NMSEexample39 := (- (/ 1 x) (/ 1 (tan x))) +# tan: [0.01, 1] +taskset -c 0 ./pareto_all_1.sh NMSEexample39 + +# NMSEproblem341 := (/ (- 1 (cos x)) (* x x)) +# cos: [0.01, 100] +taskset -c 0 ./pareto_all_1.sh NMSEproblem341 \ No newline at end of file -- Gitee From 368782fcfbadbb5a40dbaaf2e33193f421df49ef Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 19 Sep 2023 23:03:42 +0800 Subject: [PATCH 43/54] Improve pareto by adding more examples --- srcTest/exprMap.sh | 34 +++++++++++++++++++++++++--- srcTest/getOriginErrCost.sh | 43 ++++++++++++++++++++++++++++++++++-- srcTest/pareto_all_list.sh | 44 ++++++++++++++++++++++++++++++++++--- 3 files changed, 113 insertions(+), 8 deletions(-) diff --git a/srcTest/exprMap.sh b/srcTest/exprMap.sh index 5b5b405..46c24ab 100644 --- a/srcTest/exprMap.sh +++ b/srcTest/exprMap.sh @@ -5,33 +5,54 @@ declare -A x0Starts=( ["NMSEproblem345"]=0.01 ["NMSEexample34"]=0.01 ["logexp"]=-8 - ["NMSEproblem343"]=-1 + ["NMSEproblem343"]=-0.5 # -1 ["exp1x"]=0.01 ["NMSEexample37"]=0.01 ["NMSEexample39"]=0.01 ["NMSEproblem341"]=0.01 + ["NMSEexample310"]=-0.5 # -1 + ["NMSEexample35"]=0.01 + ["NMSEexample38"]=0.01 + ["NMSEproblem336"]=0.01 + ["NMSEproblem337"]=0.01 + ["NMSEproblem344"]=0.01 + ["NMSEsection311"]=0.01 ) declare -A x0Ends=( ["NMSEproblem345"]=100 ["NMSEexample34"]=3 ["logexp"]=8 - ["NMSEproblem343"]=1 + ["NMSEproblem343"]=0.5 # 1 ["exp1x"]=0.5 ["NMSEexample37"]=100 ["NMSEexample39"]=1 ["NMSEproblem341"]=100 + ["NMSEexample310"]=0.5 # 1 + ["NMSEexample35"]=100 + ["NMSEexample38"]=100 + ["NMSEproblem336"]=100 + ["NMSEproblem337"]=100 + ["NMSEproblem344"]=100 + ["NMSEsection311"]=100 ) declare -A stepX0s=( ["NMSEproblem345"]=0.00019998 ["NMSEexample34"]=5.98e-06 ["logexp"]=3.2e-05 - ["NMSEproblem343"]=4e-06 + ["NMSEproblem343"]=2e-06 # 4e-06 ["exp1x"]=9.8e-07 ["NMSEexample37"]=0.00019998 ["NMSEexample39"]=1.98e-06 ["NMSEproblem341"]=0.00019998 + ["NMSEexample310"]=2e-06 # 4e-06 + ["NMSEexample35"]=0.00019998 + ["NMSEexample38"]=0.00019998 + ["NMSEproblem336"]=0.00019998 + ["NMSEproblem337"]=0.00019998 + ["NMSEproblem344"]=0.00019998 + ["NMSEsection311"]=0.00019998 ) declare -A func1s=( @@ -43,6 +64,13 @@ declare -A func1s=( ["NMSEexample37"]=exp ["NMSEexample39"]=tan ["NMSEproblem341"]=cos + ["NMSEexample310"]=log + ["NMSEexample35"]=atan + ["NMSEexample38"]=log + ["NMSEproblem336"]=log + ["NMSEproblem337"]=exp + ["NMSEproblem344"]=exp + ["NMSEsection311"]=exp ) declare -A func2s=( diff --git a/srcTest/getOriginErrCost.sh b/srcTest/getOriginErrCost.sh index 2610e0b..d66707c 100755 --- a/srcTest/getOriginErrCost.sh +++ b/srcTest/getOriginErrCost.sh @@ -14,9 +14,11 @@ cd - >/dev/null ./testPerformanceOneManual.sh logexp origin -8 8 cd .. -./detectErrorOneFPEDParallel.sh NMSEproblem343 -1 1 500000 0 -1 4e-06 expr_NMSEproblem343 -1_1_500000 origin 0 +# ./detectErrorOneFPEDParallel.sh NMSEproblem343 -1 1 500000 0 -1 4e-06 expr_NMSEproblem343 -1_1_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEproblem343 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEproblem343 -0.5_0.5_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEproblem343 origin -1 1 +# ./testPerformanceOneManual.sh NMSEproblem343 origin -1 1 +./testPerformanceOneManual.sh NMSEproblem343 origin -0.5 0.5 cd .. ./detectErrorOneFPEDParallel.sh exp1x 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x 0.01_0.5_500000 origin 0 @@ -37,3 +39,40 @@ cd .. ./detectErrorOneFPEDParallel.sh NMSEproblem341 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem341 0.01_100_500000 origin 0 cd - >/dev/null ./testPerformanceOneManual.sh NMSEproblem341 origin 0.01 100 + +cd .. +# ./detectErrorOneFPEDParallel.sh NMSEexample310 -1 1 500000 0 -1 4e-06 expr_NMSEexample310 -1_1_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEexample310 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEexample310 -0.5_0.5_500000 origin 0 +cd - >/dev/null +# ./testPerformanceOneManual.sh NMSEexample310 -1 1 +./testPerformanceOneManual.sh NMSEexample310 -0.5 0.5 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEexample35 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample35 0.01_100_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEexample35 0.01 100 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEexample38 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample38 0.01_100_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEexample38 0.01 100 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEproblem336 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem336 0.01_100_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEproblem336 0.01 100 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEproblem337 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem337 0.01_100_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEproblem337 0.01 100 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEproblem344 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem344 0.01_100_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEproblem344 0.01 100 + +cd .. +./detectErrorOneFPEDParallel.sh NMSEsection311 0.01 100 500000 0 0.01 0.00019998 expr_NMSEsection311 0.01_100_500000 origin 0 +cd - >/dev/null +./testPerformanceOneManual.sh NMSEsection311 0.01 100 \ No newline at end of file diff --git a/srcTest/pareto_all_list.sh b/srcTest/pareto_all_list.sh index 3fda9f2..8150dfa 100644 --- a/srcTest/pareto_all_list.sh +++ b/srcTest/pareto_all_list.sh @@ -17,10 +17,10 @@ taskset -c 0 ./pareto_all.sh logexp -8 8 1 2982 # NMSEproblem343 := (log (/ (- 1 eps) (+ 1 eps))) # eps: [-1, 1] # log: (0, +infty) -taskset -c 0 ./pareto_all_1.sh exp1x 0.5 1 +taskset -c 0 ./pareto_all_1.sh NMSEproblem343 0.5 1 # eps: [-1/2, 1/2] # log: (1/3, 3) -taskset -c 0 ./pareto_all_1.sh exp1x 0.333333 3 +taskset -c 0 ./pareto_all_1.sh NMSEproblem343 0.3 3 # exp1x := (exp(x) - 1) / x # exp: [0.01, 0.5] @@ -36,4 +36,42 @@ taskset -c 0 ./pareto_all_1.sh NMSEexample39 # NMSEproblem341 := (/ (- 1 (cos x)) (* x x)) # cos: [0.01, 100] -taskset -c 0 ./pareto_all_1.sh NMSEproblem341 \ No newline at end of file +taskset -c 0 ./pareto_all_1.sh NMSEproblem341 + +# NMSEexample310 := (log((1.0 - x)) / log((1.0 + x))) +# x: -1, 1 +# log: (0, 2) +taskset -c 0 ./pareto_all_1.sh NMSEexample310 0 2 +# x: -1/2, 1/2 +# log: [1/2, 3/2] +taskset -c 0 ./pareto_all_1.sh NMSEexample310 0.5 1.5 + +# NMSEexample35 := (atan((x + 1.0)) - atan(x)) +# x: [0.01, 100] +# atan: [0.01, 101] +taskset -c 0 ./pareto_all_1.sh NMSEexample35 0.01 101 + +# NMSEexample38 := ((((x + 1.0) * log((x + 1.0))) - (x * log(x))) - 1.0) +# x: [0.01, 100] +# log: [0.01, 101] +taskset -c 0 ./pareto_all_1.sh NMSEexample38 0.01 101 + +# NMSEproblem336 := (log((x + 1.0)) - log(x)) +# x: [0.01, 100] +# log: [0.01, 101] +taskset -c 0 ./pareto_all_1.sh NMSEproblem336 0.01 101 + +# NMSEproblem337 := ((exp(x) + (-1.0 * 2.0)) + exp((-1.0 * x))) +# x: [0.01, 100] +# log: [-100, -0.01] & [0.01, 100] +taskset -c 0 ./pareto_all_1.sh NMSEproblem337 -100 100 + +# NMSEproblem344 := (exp(x) / (exp(x) - 1.0)) +# x: [0.01, 100] +# exp: [0.01, 100] +taskset -c 0 ./pareto_all_1.sh NMSEproblem344 + +# NMSEsection311 := sqrt(((exp((2.0 * x)) - 1.0) / (exp(x) - 1.0))) +# x: [0.01, 100] +# exp: [0.01, 200] +taskset -c 0 ./pareto_all_1.sh NMSEsection311 0.01 200 \ No newline at end of file -- Gitee From 4cd952f3bb6c18b604c56791d451448680b59cb9 Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 20 Sep 2023 00:45:05 +0800 Subject: [PATCH 44/54] Improve pareto by running all examples --- srcTest/getOriginErrCost.sh | 34 +++++++++++++++++----------------- srcTest/pareto_all_list.sh | 2 +- srcTest/sortData.py | 16 +++++++--------- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/srcTest/getOriginErrCost.sh b/srcTest/getOriginErrCost.sh index d66707c..2823ad7 100755 --- a/srcTest/getOriginErrCost.sh +++ b/srcTest/getOriginErrCost.sh @@ -1,78 +1,78 @@ cd .. ./detectErrorOneFPEDParallel.sh NMSEproblem345 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem345 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEproblem345 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem345 origin 0.01 100 cd .. ./detectErrorOneFPEDParallel.sh NMSEexample34 0.01 3 500000 0 0.01 5.98e-06 expr_NMSEexample34 0.01_3_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEexample34 origin 0.01 3 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample34 origin 0.01 3 cd .. ./detectErrorOneFPEDParallel.sh logexp -8 8 500000 0 -8 3.2e-05 expr_logexp -8_8_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh logexp origin -8 8 +taskset -c 0 ./testPerformanceOneManual.sh logexp origin -8 8 cd .. # ./detectErrorOneFPEDParallel.sh NMSEproblem343 -1 1 500000 0 -1 4e-06 expr_NMSEproblem343 -1_1_500000 origin 0 ./detectErrorOneFPEDParallel.sh NMSEproblem343 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEproblem343 -0.5_0.5_500000 origin 0 cd - >/dev/null -# ./testPerformanceOneManual.sh NMSEproblem343 origin -1 1 -./testPerformanceOneManual.sh NMSEproblem343 origin -0.5 0.5 +# taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem343 origin -1 1 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem343 origin -0.5 0.5 cd .. ./detectErrorOneFPEDParallel.sh exp1x 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x 0.01_0.5_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh exp1x origin 0.01 0.5 +taskset -c 0 ./testPerformanceOneManual.sh exp1x origin 0.01 0.5 cd .. ./detectErrorOneFPEDParallel.sh NMSEexample37 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample37 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEexample37 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample37 origin 0.01 100 cd .. ./detectErrorOneFPEDParallel.sh NMSEexample39 0.01 1 500000 0 0.01 1.98e-06 expr_NMSEexample39 0.01_1_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEexample39 origin 0.01 1 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample39 origin 0.01 1 cd .. ./detectErrorOneFPEDParallel.sh NMSEproblem341 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem341 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEproblem341 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem341 origin 0.01 100 cd .. # ./detectErrorOneFPEDParallel.sh NMSEexample310 -1 1 500000 0 -1 4e-06 expr_NMSEexample310 -1_1_500000 origin 0 ./detectErrorOneFPEDParallel.sh NMSEexample310 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEexample310 -0.5_0.5_500000 origin 0 cd - >/dev/null -# ./testPerformanceOneManual.sh NMSEexample310 -1 1 -./testPerformanceOneManual.sh NMSEexample310 -0.5 0.5 +# taskset -c 0 ./testPerformanceOneManual.sh NMSEexample310 -1 1 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample310 origin -0.5 0.5 cd .. ./detectErrorOneFPEDParallel.sh NMSEexample35 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample35 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEexample35 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample35 origin 0.01 100 cd .. ./detectErrorOneFPEDParallel.sh NMSEexample38 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample38 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEexample38 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample38 origin 0.01 100 cd .. ./detectErrorOneFPEDParallel.sh NMSEproblem336 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem336 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEproblem336 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem336 origin 0.01 100 cd .. ./detectErrorOneFPEDParallel.sh NMSEproblem337 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem337 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEproblem337 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem337 origin 0.01 100 cd .. ./detectErrorOneFPEDParallel.sh NMSEproblem344 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem344 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEproblem344 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem344 origin 0.01 100 cd .. ./detectErrorOneFPEDParallel.sh NMSEsection311 0.01 100 500000 0 0.01 0.00019998 expr_NMSEsection311 0.01_100_500000 origin 0 cd - >/dev/null -./testPerformanceOneManual.sh NMSEsection311 0.01 100 \ No newline at end of file +taskset -c 0 ./testPerformanceOneManual.sh NMSEsection311 origin 0.01 100 \ No newline at end of file diff --git a/srcTest/pareto_all_list.sh b/srcTest/pareto_all_list.sh index 8150dfa..076b06e 100644 --- a/srcTest/pareto_all_list.sh +++ b/srcTest/pareto_all_list.sh @@ -63,7 +63,7 @@ taskset -c 0 ./pareto_all_1.sh NMSEproblem336 0.01 101 # NMSEproblem337 := ((exp(x) + (-1.0 * 2.0)) + exp((-1.0 * x))) # x: [0.01, 100] -# log: [-100, -0.01] & [0.01, 100] +# exp: [-100, -0.01] & [0.01, 100] taskset -c 0 ./pareto_all_1.sh NMSEproblem337 -100 100 # NMSEproblem344 := (exp(x) / (exp(x) - 1.0)) diff --git a/srcTest/sortData.py b/srcTest/sortData.py index ae92961..0c9d758 100644 --- a/srcTest/sortData.py +++ b/srcTest/sortData.py @@ -55,30 +55,28 @@ def sort_csv_by_column_1(csv_file, output_file, sort_column, func1): # 按照第 sort_column 列数据对 inputFile 文件进行排序,结果写入 outputFile 文件 if __name__ == '__main__': - # 读取命令行参数 + # 读取命令行参数, 并检查是否传递了参数 arguments = sys.argv - - # 检查是否传递了参数 if len(arguments) > 4: print("please input only 2 or 3 paremeters or none paremeter!") sys.exit(1) - elif len(arguments) == 4: # 表达式中只有一个函数。用于实测性能误差后的对表达式的帕累托优化 + elif len(arguments) == 4: # 表达式中有 2 个函数。 uniqueLabel = arguments[1] # arguments[2] 为 NMSEexample34, 即优化表达式 inputFile = uniqueLabel + "_errPerfPareto.csv" outputFile = uniqueLabel + "_errPerfParetoSorted.csv" - sort_column = int(2) # 说明表达式中有1个函数,故第3列才是平均误差 - func1 = arguments[2] # arguments[1] 为 sin, 即优化函数 - func2 = arguments[3] # arguments[2] 为 cos, 即优化函数 + sort_column = int(4) # 说明表达式中有2个函数,故第5列才是平均误差 + func1 = arguments[2] + func2 = arguments[3] sort_csv_by_column(inputFile, outputFile, sort_column, func1, func2) - elif len(arguments) == 3: # 表达式中只有一个函数。用于实测性能误差后的对表达式的帕累托优化 + elif len(arguments) == 3: # 表达式中只有 1 个函数。 uniqueLabel = arguments[1] # arguments[2] 为 exp1x, 即优化表达式 inputFile = uniqueLabel + "_errPerfPareto.csv" outputFile = uniqueLabel + "_errPerfParetoSorted.csv" sort_column = int(2) # 说明表达式中有1个函数,故第3列才是平均误差 - func1 = arguments[2] # arguments[1] 为 exp, 即优化函数 + func1 = arguments[2] sort_csv_by_column_1(inputFile, outputFile, sort_column, func1) elif len(arguments) == 1: # 没有输入,对应的是之前的默认情况,即 NMSEproblem345 -- Gitee From 1959ade9035bc09acc6a50db1cc795964ddbea78 Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 20 Sep 2023 20:28:59 +0800 Subject: [PATCH 45/54] add -mfam to test scripts for one paremeter --- detectErrorOneFPEDParallel.sh | 2 +- srcTest/testPerformanceOneManual.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/detectErrorOneFPEDParallel.sh b/detectErrorOneFPEDParallel.sh index e2564b9..dd535a3 100755 --- a/detectErrorOneFPEDParallel.sh +++ b/detectErrorOneFPEDParallel.sh @@ -50,7 +50,7 @@ sourceFile=${prefix}_${suffix} fileNameKernel=${prefix}__${middle}_${suffix} # echo "${CC} ${testFileName}.c ${sourceFile}.c ${prefix}_mpfr.c computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -O3 -o ${testFileName}.exe" -${CC} ./srcTest/${testFileName}.c ${directory}/${sourceFile}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -DERRFILE=${errfile} -D${ERRORMODEL} -Llibs -lTGen -lmpfr -lm -lqd -o ${testFileName}.exe +${CC} ./srcTest/${testFileName}.c ${directory}/${sourceFile}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -DERRFILE=${errfile} -D${ERRORMODEL} -Llibs -lTGen -lmpfr -lm -lqd -mfma -o ${testFileName}.exe # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${fileNameKernel}" mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${fileNameKernel} ${uniqueLabel} # mv outputs/${fileNameKernel}_error.txt ./outputs/${uniqueLabel}/${fileNameKernel}_error.txt diff --git a/srcTest/testPerformanceOneManual.sh b/srcTest/testPerformanceOneManual.sh index 27961dc..56adc75 100755 --- a/srcTest/testPerformanceOneManual.sh +++ b/srcTest/testPerformanceOneManual.sh @@ -31,7 +31,7 @@ funcName=expr_${uniqueLabel}_${suffix} # make testPerformanceOne.o -s CFLAGS="-DFUNCNAME=${funcName} -DRUNTIME=${runtime}" gcc testPerformanceOne.c -DFUNCNAME=${funcName} -DRUNTIME=${runtime} -I../includeTEST -c -O3 make binary.o -s # gcc binary.c -I../includeTEST -c -O3 -gcc ${uniqueLabel}/${funcName}.c -I../includeDD -c -O3 +gcc ${uniqueLabel}/${funcName}.c -I../includeDD -c -O3 -mfma gcc testPerformanceOne.o binary.o ${funcName}.o ../libs/libTGen.so -lmpfr -lm -lqd -o testPerformanceOne_${uniqueLabel}.exe -O3 ./testPerformanceOne_${uniqueLabel}.exe ${resultFileName} ${start} ${end} # rm -rf testPerformanceOne_${uniqueLabel}.exe -- Gitee From d5ba08932d542548fc1ae405b3930b3ead2ac287 Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 20 Sep 2023 20:29:10 +0800 Subject: [PATCH 46/54] update gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 3b424da..71b7138 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,6 @@ expr_*.c run.log includeTEST/mine.h *.csv +*.log +srcTest/*/*_gen.c +srcTest/*/myhead.h \ No newline at end of file -- Gitee From 890bb41dbabb22ac760178f708489347b9e570ad Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 20 Sep 2023 20:29:52 +0800 Subject: [PATCH 47/54] Add a python script to convert the csv files to a excel file --- srcTest/convertCSV_TO_EXCEL.py | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 srcTest/convertCSV_TO_EXCEL.py diff --git a/srcTest/convertCSV_TO_EXCEL.py b/srcTest/convertCSV_TO_EXCEL.py new file mode 100644 index 0000000..f7b214e --- /dev/null +++ b/srcTest/convertCSV_TO_EXCEL.py @@ -0,0 +1,47 @@ +import pandas as pd +import glob + +# 查找所有带有 "Sorted.csv" 后缀的文件 +csv_files = glob.glob('*Sorted.csv') + +# 创建一个 Excel Writer 对象,用于写入 Excel 文件 +excel_writer = pd.ExcelWriter('output.xlsx', engine='openpyxl') + +# 定义空白行数和起始列数 +num_blank_rows = 3 +start_rows = num_blank_rows +start_col = 3 + + +# 遍历 CSV 文件列表 +for csv_file in csv_files: + # 读取 CSV 文件 + df = pd.read_csv(csv_file, sep='\t') + + # 提取文件名作为工作表名称 + sheet_name = csv_file[:-24] # 去除文件扩展名和后缀 + + # 在左侧的一个单元格内写入文件名 + df.insert(0, sheet_name, '') + + # 将当前文件的数据写入 Excel 表格,追加到同一个工作表中,并添加空白行和起始列 + df.to_excel(excel_writer, sheet_name='Combined', startrow=start_rows, startcol=start_col, index=False, header=True) + + # 计算下一个文件的起始行数 + start_rows += df.shape[0] + 4 # 添加间隔行 + + +# 遍历 CSV 文件列表 +for csv_file in csv_files: + # 读取 CSV 文件 + df = pd.read_csv(csv_file, sep='\t') + + # 提取文件名作为工作表名称 + sheet_name = csv_file[:-24] # 去除文件扩展名和后缀 + + # 将当前文件的数据写入 Excel 表格,每个文件写入一个新的工作表 + df.to_excel(excel_writer, sheet_name=sheet_name, startrow=num_blank_rows, startcol=start_col, index=False, header=True) + + +# 关闭 Excel Writer 对象 +excel_writer.save() -- Gitee From ab390dd3f426010ee7f4dd317b4b6d769fab901a Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 20 Sep 2023 20:30:36 +0800 Subject: [PATCH 48/54] update parato_all_list.sh --- srcTest/pareto_all_list.sh | 44 +++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) mode change 100644 => 100755 srcTest/pareto_all_list.sh diff --git a/srcTest/pareto_all_list.sh b/srcTest/pareto_all_list.sh old mode 100644 new mode 100755 index 076b06e..5773541 --- a/srcTest/pareto_all_list.sh +++ b/srcTest/pareto_all_list.sh @@ -1,77 +1,111 @@ +#!/bin/bash # NMSEproblem345 := (/ (- x (sin x)) (- x (tan x))) # sin: [0.01, 100] # tan: [0.01, 100] taskset -c 0 ./pareto_all.sh NMSEproblem345 +## TGen +# taskset -c 0 python3 per_allversion.py sin 0.01 100 +# taskset -c 0 python3 per_allversion.py tan 0.01 100 # NMSEexample34: (/ (- 1 (cos x)) (sin x)) -# sin: [0.01, 100] -# cos: [0.01, 100] +# sin: [0.01, 3] +# cos: [0.01, 3] taskset -c 0 ./pareto_all.sh NMSEexample34 +## TGen +# taskset -c 0 python3 per_allversion.py sin 0.01 3 +# taskset -c 0 python3 per_allversion.py cos 0.01 3 # logexp := log (+ 1 (exp x)) # exp: [-8, 8] # log: [1 + exp(-8), 1 + exp(8)] = [1.000335, 2,981.957987] \approx [1, 2982] taskset -c 0 ./pareto_all.sh logexp -8 8 1 2982 +## TGen +# taskset -c 0 python3 per_allversion.py exp -8 8 +# taskset -c 0 python3 per_allversion.py log 1 2982 # !!!!!! # NMSEproblem343 := (log (/ (- 1 eps) (+ 1 eps))) # eps: [-1, 1] # log: (0, +infty) -taskset -c 0 ./pareto_all_1.sh NMSEproblem343 0.5 1 +# taskset -c 0 ./pareto_all_1.sh NMSEproblem343 0.5 1 # eps: [-1/2, 1/2] # log: (1/3, 3) taskset -c 0 ./pareto_all_1.sh NMSEproblem343 0.3 3 +## TGen +# taskset -c 0 python3 per_allversion.py log 0.3 3 # exp1x := (exp(x) - 1) / x # exp: [0.01, 0.5] taskset -c 0 ./pareto_all_1.sh exp1x +## TGen +# taskset -c 0 python3 per_allversion.py exp 0.01 0.5 # NMSEexample37 := exp(x) - 1 # exp: [0.01, 100] taskset -c 0 ./pareto_all_1.sh NMSEexample37 +## TGen +# taskset -c 0 python3 per_allversion.py exp 0.01 100 # NMSEexample39 := (- (/ 1 x) (/ 1 (tan x))) # tan: [0.01, 1] taskset -c 0 ./pareto_all_1.sh NMSEexample39 +## TGen +# taskset -c 0 python3 per_allversion.py tan 0.01 1 # NMSEproblem341 := (/ (- 1 (cos x)) (* x x)) # cos: [0.01, 100] taskset -c 0 ./pareto_all_1.sh NMSEproblem341 +## TGen +# taskset -c 0 python3 per_allversion.py cos 0.01 100 # NMSEexample310 := (log((1.0 - x)) / log((1.0 + x))) # x: -1, 1 # log: (0, 2) -taskset -c 0 ./pareto_all_1.sh NMSEexample310 0 2 +# taskset -c 0 ./pareto_all_1.sh NMSEexample310 0 2 # x: -1/2, 1/2 # log: [1/2, 3/2] taskset -c 0 ./pareto_all_1.sh NMSEexample310 0.5 1.5 +## TGen +# taskset -c 0 python3 per_allversion.py log 0.5 1.5 # NMSEexample35 := (atan((x + 1.0)) - atan(x)) # x: [0.01, 100] # atan: [0.01, 101] taskset -c 0 ./pareto_all_1.sh NMSEexample35 0.01 101 +## TGen +# taskset -c 0 python3 per_allversion.py atan 0.01 101 # NMSEexample38 := ((((x + 1.0) * log((x + 1.0))) - (x * log(x))) - 1.0) # x: [0.01, 100] # log: [0.01, 101] taskset -c 0 ./pareto_all_1.sh NMSEexample38 0.01 101 +## TGen +# taskset -c 0 python3 per_allversion.py log 0.01 101 # NMSEproblem336 := (log((x + 1.0)) - log(x)) # x: [0.01, 100] # log: [0.01, 101] taskset -c 0 ./pareto_all_1.sh NMSEproblem336 0.01 101 +## TGen +# taskset -c 0 python3 per_allversion.py log 0.01 101 # NMSEproblem337 := ((exp(x) + (-1.0 * 2.0)) + exp((-1.0 * x))) # x: [0.01, 100] # exp: [-100, -0.01] & [0.01, 100] taskset -c 0 ./pareto_all_1.sh NMSEproblem337 -100 100 +## TGen +# taskset -c 0 python3 per_allversion.py exp -100 100 # NMSEproblem344 := (exp(x) / (exp(x) - 1.0)) # x: [0.01, 100] # exp: [0.01, 100] taskset -c 0 ./pareto_all_1.sh NMSEproblem344 +## TGen +# taskset -c 0 python3 per_allversion.py exp 0.01 100 # NMSEsection311 := sqrt(((exp((2.0 * x)) - 1.0) / (exp(x) - 1.0))) # x: [0.01, 100] # exp: [0.01, 200] -taskset -c 0 ./pareto_all_1.sh NMSEsection311 0.01 200 \ No newline at end of file +taskset -c 0 ./pareto_all_1.sh NMSEsection311 0.01 200 +## TGen +# taskset -c 0 python3 per_allversion.py exp 0 200 \ No newline at end of file -- Gitee From 071f8c72199bff5e5b3295d6b80da70ad8b1b928 Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 20 Sep 2023 22:50:50 +0800 Subject: [PATCH 49/54] Fix bug abot headline of uniqueLabelOutput.csv --- srcTest/combine_2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcTest/combine_2.py b/srcTest/combine_2.py index 97029fa..fcacc04 100644 --- a/srcTest/combine_2.py +++ b/srcTest/combine_2.py @@ -39,7 +39,7 @@ def geneData(file1, file2): # errorSum = error1[i] + error2[j] # !!! 这里是关键,关键在于要不要从error变成epsilon。 errorSum = error1[i] * condNumSin + error2[j] * condNumTan # !!! 这里是关键,关键在于要不要从error变成epsilon。 perfSum = perf1[i] + perf2[j] - pair = (regime1[i], degree1[i], degree1[j], degree2[j], errorSum, perfSum) + pair = (regime1[i], degree1[i], regime2[j], degree2[j], errorSum, perfSum) result.append(pair) return result -- Gitee From cfe7e04bf2df9edc458fb39ab0e18dd3ce0a7375 Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 20 Sep 2023 22:53:47 +0800 Subject: [PATCH 50/54] Add pareto support to 2-param expressions --- srcTest/exprMap.sh | 29 ++++++++++++++++ srcTest/getOriginErrCost.sh | 17 +++++++++- srcTest/getRealErrCost.sh | 41 ++++++++++++++++++++--- srcTest/getRealErrCost_1.sh | 40 +++++++++++++++++++--- srcTest/pareto_all_list.sh | 28 +++++++++++++++- srcTest/test2paramFPEDParallel.c | 4 +-- srcTest/testPerformanceTwo.c | 2 +- srcTest/testPerformanceTwoManual.sh | 52 +++++++++++++++++++++++++++++ 8 files changed, 199 insertions(+), 14 deletions(-) create mode 100755 srcTest/testPerformanceTwoManual.sh diff --git a/srcTest/exprMap.sh b/srcTest/exprMap.sh index 46c24ab..08eb4c4 100644 --- a/srcTest/exprMap.sh +++ b/srcTest/exprMap.sh @@ -5,6 +5,7 @@ declare -A x0Starts=( ["NMSEproblem345"]=0.01 ["NMSEexample34"]=0.01 ["logexp"]=-8 + ["exp1x_log"]=0.01 ["NMSEproblem343"]=-0.5 # -1 ["exp1x"]=0.01 ["NMSEexample37"]=0.01 @@ -17,12 +18,15 @@ declare -A x0Starts=( ["NMSEproblem337"]=0.01 ["NMSEproblem344"]=0.01 ["NMSEsection311"]=0.01 + ["theta"]=1 + ["ComplexSinCos"]=0 ) declare -A x0Ends=( ["NMSEproblem345"]=100 ["NMSEexample34"]=3 ["logexp"]=8 + ["exp1x_log"]=0.5 ["NMSEproblem343"]=0.5 # 1 ["exp1x"]=0.5 ["NMSEexample37"]=100 @@ -35,12 +39,15 @@ declare -A x0Ends=( ["NMSEproblem337"]=100 ["NMSEproblem344"]=100 ["NMSEsection311"]=100 + ["theta"]=100 + ["ComplexSinCos"]=1 ) declare -A stepX0s=( ["NMSEproblem345"]=0.00019998 ["NMSEexample34"]=5.98e-06 ["logexp"]=3.2e-05 + ["exp1x_log"]=9.8e-07 ["NMSEproblem343"]=2e-06 # 4e-06 ["exp1x"]=9.8e-07 ["NMSEexample37"]=0.00019998 @@ -53,12 +60,30 @@ declare -A stepX0s=( ["NMSEproblem337"]=0.00019998 ["NMSEproblem344"]=0.00019998 ["NMSEsection311"]=0.00019998 + ["theta"]=0.0966796875 + ["ComplexSinCos"]=0.0009765625 +) + +declare -A x1Starts=( + ["theta"]=1 + ["ComplexSinCos"]=0 +) + +declare -A x1Ends=( + ["theta"]=100 + ["ComplexSinCos"]=1 +) + +declare -A stepX1s=( + ["theta"]=0.0966796875 + ["ComplexSinCos"]=0.0009765625 ) declare -A func1s=( ["NMSEproblem345"]=sin ["NMSEexample34"]=cos ["logexp"]=exp + ["exp1x_log"]=exp ["NMSEproblem343"]=log ["exp1x"]=exp ["NMSEexample37"]=exp @@ -71,10 +96,14 @@ declare -A func1s=( ["NMSEproblem337"]=exp ["NMSEproblem344"]=exp ["NMSEsection311"]=exp + ["theta"]=atan + ["ComplexSinCos"]=exp ) declare -A func2s=( ["NMSEproblem345"]=tan ["NMSEexample34"]=sin ["logexp"]=log + ["exp1x_log"]=log + ["ComplexSinCos"]=sin ) \ No newline at end of file diff --git a/srcTest/getOriginErrCost.sh b/srcTest/getOriginErrCost.sh index 2823ad7..73b2def 100755 --- a/srcTest/getOriginErrCost.sh +++ b/srcTest/getOriginErrCost.sh @@ -13,6 +13,11 @@ cd .. cd - >/dev/null taskset -c 0 ./testPerformanceOneManual.sh logexp origin -8 8 +cd .. +./detectErrorOneFPEDParallel.sh exp1x_log 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x_log 0.01_0.5_500000 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceOneManual.sh exp1x_log origin 0.01 0.5 + cd .. # ./detectErrorOneFPEDParallel.sh NMSEproblem343 -1 1 500000 0 -1 4e-06 expr_NMSEproblem343 -1_1_500000 origin 0 ./detectErrorOneFPEDParallel.sh NMSEproblem343 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEproblem343 -0.5_0.5_500000 origin 0 @@ -75,4 +80,14 @@ taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem344 origin 0.01 100 cd .. ./detectErrorOneFPEDParallel.sh NMSEsection311 0.01 100 500000 0 0.01 0.00019998 expr_NMSEsection311 0.01_100_500000 origin 0 cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEsection311 origin 0.01 100 \ No newline at end of file +taskset -c 0 ./testPerformanceOneManual.sh NMSEsection311 origin 0.01 100 + +cd .. +./detectErrorTwoFPEDParallel.sh theta 1 100 1 100 1024 1024 0 0 1 1 0.0966796875 0.0966796875 expr_theta 1_100_1_100_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh theta origin 1 100 1 100 + +cd .. +./detectErrorTwoFPEDParallel.sh ComplexSinCos 0 1 0 1 1024 1024 0 0 0 0 0.0009765625 0.0009765625 expr_ComplexSinCos 0_1_0_1_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh ComplexSinCos origin 0 1 0 1 \ No newline at end of file diff --git a/srcTest/getRealErrCost.sh b/srcTest/getRealErrCost.sh index 805e2d3..1381ed5 100755 --- a/srcTest/getRealErrCost.sh +++ b/srcTest/getRealErrCost.sh @@ -1,6 +1,7 @@ #!/bin/bash # set -x +# !!!仅有两个函数 # 多精度版本函数的路径是TGen的路径,特定于北京服务器的固定路径。 # NMSEproblem345的双参特供版,能修改其中的tan, sin函数的精度版本,用来测试使用不同函数的表达式的性能和精度 # getRealErrCost脚本的测试对象是帕累托优化得到的所有混合精度方案,用来验证帕累托优化效果 @@ -15,15 +16,20 @@ # init for mix-precision source funcMap.sh source exprMap.sh -# source init.sh # init for error detection and performance detection +inputNum="One" if [ $# == 3 ]; then uniqueLabel=${1} x0Start=${x0Starts[${uniqueLabel}]} x0End=${x0Ends[${uniqueLabel}]} stepX0=${stepX0s[${uniqueLabel}]} - + x1Start=${x1Starts[${uniqueLabel}]} + if [ -n "${x1Start}" ]; then + inputNum="Two" + x1End=${x1Ends[${uniqueLabel}]} + stepX1=${stepX1s[${uniqueLabel}]} + fi func1=${2} func2=${3} elif [ $# == 1 ]; then @@ -31,7 +37,12 @@ elif [ $# == 1 ]; then x0Start=${x0Starts[${uniqueLabel}]} x0End=${x0Ends[${uniqueLabel}]} stepX0=${stepX0s[${uniqueLabel}]} - + x1Start=${x1Starts[${uniqueLabel}]} + if [ -n "${x1Start}" ]; then + inputNum="Two" + x1End=${x1Ends[${uniqueLabel}]} + stepX1=${stepX1s[${uniqueLabel}]} + fi func1=sin func2=tan else @@ -47,6 +58,18 @@ fi x0Size=500000 x0startNowIdx=0 x0startOriginInterval=${x0Start} + +if [ ${inputNum} == "Two" ]; then + x0Size=1024 + x1Size=1024 + x1startNowIdx=0 + x1startOriginInterval=${x1Start} + echo "x1Start is ${x1Start}, not empty" + echo "x1End is ${x1End}, not empty" + echo "stepX1 is ${stepX1}, not empty" + echo "x1startOriginInterval is ${x1startOriginInterval}, not empty" +fi + prefix=expr_${uniqueLabel} middle=${x0Start} suffix=origin @@ -109,9 +132,17 @@ do echo "${func1}: bit = ${bit1} degree = ${degree1}; ${func2}: bit2 = ${bit2} degree = ${degree2}" echo -e "${bit1}\t${degree1}\t${bit2}\t${degree2}" > ${temp_file} cd .. - ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + if [ ${inputNum} = "One" ]; then + ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + elif [ ${inputNum} = "Two" ]; then + ./detectErrorTwoFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x1Start} ${x1End} ${x0Size} ${x1Size} ${x0startNowIdx} ${x1startNowIdx} ${x0startOriginInterval} ${x1startOriginInterval} ${stepX0} ${stepX1} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + fi cd - >/dev/null - taskset -c 0 ./testPerformanceOneManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} | tee -a ${temp_file} + if [ ${inputNum} = "One" ]; then + taskset -c 0 ./testPerformanceOneManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} | tee -a ${temp_file} + elif [ ${inputNum} = "Two" ]; then + taskset -c 0 ./testPerformanceTwoManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} ${x1Start} ${x1End} | tee -a ${temp_file} + fi awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} echo done diff --git a/srcTest/getRealErrCost_1.sh b/srcTest/getRealErrCost_1.sh index de81c24..ccc92b5 100755 --- a/srcTest/getRealErrCost_1.sh +++ b/srcTest/getRealErrCost_1.sh @@ -1,6 +1,7 @@ #!/bin/bash # set -x +# !!!仅有一个函数 # 多精度版本函数的路径是TGen的路径,特定于北京服务器的固定路径。 # getRealErrCost_1 脚本的测试对象是帕累托优化得到的所有混合精度方案,用来验证帕累托优化效果 # getRealErrCost_1 脚本从 funcOutput.csv 中读取数据。该数据是利用 pareto_singleFunc.py 生成的。 @@ -15,19 +16,30 @@ source funcMap.sh source exprMap.sh # init for error detection and performance detection +inputNum="One" if [ $# == 2 ]; then uniqueLabel=${1} x0Start=${x0Starts[${uniqueLabel}]} x0End=${x0Ends[${uniqueLabel}]} stepX0=${stepX0s[${uniqueLabel}]} - + x1Start=${x1Starts[${uniqueLabel}]} + if [ -n "${x1Start}" ]; then + inputNum="Two" + x1End=${x1Ends[${uniqueLabel}]} + stepX1=${stepX1s[${uniqueLabel}]} + fi func1=${2} elif [ $# == 1 ]; then uniqueLabel=${1} x0Start=${x0Starts[${uniqueLabel}]} x0End=${x0Ends[${uniqueLabel}]} stepX0=${stepX0s[${uniqueLabel}]} - + x1Start=${x1Starts[${uniqueLabel}]} + if [ -n "${x1Start}" ]; then + inputNum="Two" + x1End=${x1Ends[${uniqueLabel}]} + stepX1=${stepX1s[${uniqueLabel}]} + fi func1=sin else uniqueLabel="NMSEproblem345" @@ -41,6 +53,18 @@ fi x0Size=500000 x0startNowIdx=0 x0startOriginInterval=${x0Start} + +if [ ${inputNum} == "Two" ]; then + x0Size=1024 + x1Size=1024 + x1startNowIdx=0 + x1startOriginInterval=${x1Start} + echo "x1Start is ${x1Start}, not empty" + echo "x1End is ${x1End}, not empty" + echo "stepX1 is ${stepX1}, not empty" + echo "x1startOriginInterval is ${x1startOriginInterval}, not empty" +fi + prefix=expr_${uniqueLabel} middle=${x0Start} suffix=origin @@ -98,9 +122,17 @@ do echo "${func1}: bit = ${bit1} degree = ${degree1}" echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. - ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + if [ ${inputNum} = "One" ]; then + ./detectErrorOneFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + elif [ ${inputNum} = "Two" ]; then + ./detectErrorTwoFPEDParallel.sh ${uniqueLabel} ${x0Start} ${x0End} ${x1Start} ${x1End} ${x0Size} ${x1Size} ${x0startNowIdx} ${x1startNowIdx} ${x0startOriginInterval} ${x1startOriginInterval} ${stepX0} ${stepX1} ${prefix} ${middle} ${suffix} ${errfile} | tee -a ${temp_file} + fi cd - >/dev/null - taskset -c 0 ./testPerformanceOneManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} | tee -a ${temp_file} + if [ ${inputNum} = "One" ]; then + taskset -c 0 ./testPerformanceOneManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} | tee -a ${temp_file} + elif [ ${inputNum} = "Two" ]; then + taskset -c 0 ./testPerformanceTwoManual.sh ${uniqueLabel} ${suffix} ${x0Start} ${x0End} ${x1Start} ${x1End} | tee -a ${temp_file} + fi awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} echo done diff --git a/srcTest/pareto_all_list.sh b/srcTest/pareto_all_list.sh index 5773541..d4c32b5 100755 --- a/srcTest/pareto_all_list.sh +++ b/srcTest/pareto_all_list.sh @@ -23,6 +23,14 @@ taskset -c 0 ./pareto_all.sh logexp -8 8 1 2982 # taskset -c 0 python3 per_allversion.py exp -8 8 # taskset -c 0 python3 per_allversion.py log 1 2982 +# exp1x_log := ((exp(x) - 1.0) / log(exp(x))) +# exp: [0.01, 0.5] +# log: [e^0.01, e^0.5] \approx [1, 1.65] +taskset -c 0 ./pareto_all.sh exp1x_log 0.01 0.5 1 1.65 +## TGen +# taskset -c 0 python3 per_allversion.py exp 0.01 0.5 +# taskset -c 0 python3 per_allversion.py log 1 1.65 + # !!!!!! # NMSEproblem343 := (log (/ (- 1 eps) (+ 1 eps))) # eps: [-1, 1] @@ -108,4 +116,22 @@ taskset -c 0 ./pareto_all_1.sh NMSEproblem344 # exp: [0.01, 200] taskset -c 0 ./pareto_all_1.sh NMSEsection311 0.01 200 ## TGen -# taskset -c 0 python3 per_allversion.py exp 0 200 \ No newline at end of file +# taskset -c 0 python3 per_allversion.py exp 0 200 + +# theta := (atan((x2 / x1)) * 57.29577951307855) +# x: [1, 100] +# y: [1, 100] +# atan: [0.01, 100] +taskset -c 0 ./pareto_all_1.sh theta 0.01 100 +## TGen +# taskset -c 0 python3 per_allversion.py atan 0.01 100 + +# ComplexSinCos := (((1.0 / 2.0) * sin(r)) * (exp((-1.0 * i)) - exp(i))) +# x: [0, 1] +# y: [0, 1] +# sin: [0, 1] +# exp: [-1, 1] +taskset -c 0 ./pareto_all_1.sh ComplexSinCos -1 1 0 1 +## TGen +# taskset -c 0 python3 per_allversion.py exp -1 1 +# taskset -c 0 python3 per_allversion.py sin 0 1 \ No newline at end of file diff --git a/srcTest/test2paramFPEDParallel.c b/srcTest/test2paramFPEDParallel.c index e618f47..c3d57b3 100644 --- a/srcTest/test2paramFPEDParallel.c +++ b/srcTest/test2paramFPEDParallel.c @@ -287,8 +287,8 @@ int main(int argc, char **argv) printf("Error opening file %s.\n", fileNameErr); exit(0); } - // printf("average ulp\tmax ulp\n"); - // printf("%.16Le\t%.16le\n", aveError, maxError); + printf("average ulp\tmax ulp\n"); + printf("%.16Le\t%.16le\n", aveError, maxError); // printf("\naveReUlp = %Lg\nmaxInputX0 = 0x%016lx %lg, maxInputX1 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxInputX1.l, maxInputX1.d, maxError); fprintf(fErr, "average ulp\tmax ulp\n"); fprintf(fErr, "%.16Le\t%.16le\n", aveError, maxError); diff --git a/srcTest/testPerformanceTwo.c b/srcTest/testPerformanceTwo.c index 6c4ce2e..1981848 100644 --- a/srcTest/testPerformanceTwo.c +++ b/srcTest/testPerformanceTwo.c @@ -94,7 +94,7 @@ int main(int argc, char *argv[]) sumResult = sumResult + result[i]; } sum = sum / RUNTIME; - printf("sumResult is %f\n", sumResult); + // printf("sumResult is %f\n", sumResult); // printf("the performance result to be clean: %lu\n", sum); if(fclose(stream_time) == EOF) { diff --git a/srcTest/testPerformanceTwoManual.sh b/srcTest/testPerformanceTwoManual.sh new file mode 100755 index 0000000..a569cb1 --- /dev/null +++ b/srcTest/testPerformanceTwoManual.sh @@ -0,0 +1,52 @@ +#!/bin/bash +#example: cd path/to/srcTest; taskset -c 0 ./testPerformanceTwoManual.sh i6 origin 0 100 0 100 + +if [ $# == 1 ]; then + uniqueLabel=${1} + suffix=origin + x0Start=0.01 + x0End=100 + x1Start=0.01 + x1End=100 + runtime=10000 +elif [ $# == 6 ]; then + uniqueLabel=${1} + suffix=${2} + x0Start=${3} + x0End=${4} + x1Start=${5} + x1End=${6} + runtime=10000 +elif [ $# == 7 ]; then + uniqueLabel=${1} + suffix=${2} + x0Start=${3} + x0End=${4} + x1Start=${5} + x1End=${6} + runtime=${7} +else + echo "please input 1, 6 or 7 parameters" + exit +fi + +resultFileName=result_${uniqueLabel}_${x0Start}_${x0End}_${x1Start}_${x1End}.txt +funcName=expr_${uniqueLabel}_${suffix} + +# gcc testPerformanceTwo.c binary.c ${uniqueLabel}/${funcName}.c -DFUNCNAME=${funcName} -DRUNTIME=${runtime} -I../includeTEST -lm -o testPerformanceTwo_${uniqueLabel}.exe -O3 + +# make testPerformanceTwo.o -s CFLAGS="-DFUNCNAME=${funcName} -DRUNTIME=${runtime}" +gcc testPerformanceTwo.c -DFUNCNAME=${funcName} -DRUNTIME=${runtime} -I../includeTEST -c -O3 +# gcc ${uniqueLabel}/expr_${uniqueLabel}_mpfr.c -c +make binary.o -s # gcc binary.c -I../includeTEST -c -O3 +gcc ${uniqueLabel}/${funcName}.c -I../includeTEST -I../includeDD -c -O3 -mfma +gcc testPerformanceTwo.o binary.o ${funcName}.o -lm -lqd -lmpfr -o testPerformanceTwo_${uniqueLabel}.exe -O3 +./testPerformanceTwo_${uniqueLabel}.exe ${resultFileName} ${x0Start} ${x0End} ${x1Start} ${x1End} +# rm -rf testPerformanceTwo_${uniqueLabel}.exe + +### compute the cycles of the function ${uniqueLabel} +make dataClean.exe -s CFLAGS="-DRUNTIME=${runtime}" # gcc dataClean.c -DRUNTIME=${runtime} -o dataClean.exe +sort -n ${resultFileName} > ${resultFileName}.sort +./dataClean.exe ${resultFileName}.sort +rm -rf ${resultFileName} ${resultFileName}.sort +# rm dataClean.exe -- Gitee From 4adf2e0ab8ca1ca4f67042315831930b39aa9a20 Mon Sep 17 00:00:00 2001 From: hjw Date: Thu, 21 Sep 2023 00:29:27 +0800 Subject: [PATCH 51/54] Improve pareto by adding more 2-param expression, almost all. --- srcTest/exprMap.sh | 49 ++++++++++++++++++++++++++++++ srcTest/getOriginErrCost.sh | 37 ++++++++++++++++++++++- srcTest/pareto_all_list.sh | 60 +++++++++++++++++++++++++++++++++++-- srcTest/prepare.sh | 5 ++++ 4 files changed, 148 insertions(+), 3 deletions(-) create mode 100755 srcTest/prepare.sh diff --git a/srcTest/exprMap.sh b/srcTest/exprMap.sh index 08eb4c4..ce0c294 100644 --- a/srcTest/exprMap.sh +++ b/srcTest/exprMap.sh @@ -20,6 +20,13 @@ declare -A x0Starts=( ["NMSEsection311"]=0.01 ["theta"]=1 ["ComplexSinCos"]=0 + ["NMSEexample33"]=0.01 + ["NMSEproblem332"]=0.01 + ["NMSEproblem335"]=0.01 + ["NMSEsection35"]=0 + ["polarToCarthesianX"]=1 + ["polarToCarthesianY"]=1 + ["i6"]=0.1 ) declare -A x0Ends=( @@ -41,6 +48,13 @@ declare -A x0Ends=( ["NMSEsection311"]=100 ["theta"]=100 ["ComplexSinCos"]=1 + ["NMSEexample33"]=1 + ["NMSEproblem332"]=1 + ["NMSEproblem335"]=1 + ["NMSEsection35"]=1 + ["polarToCarthesianX"]=10 + ["polarToCarthesianY"]=10 + ["i6"]=10 ) declare -A stepX0s=( @@ -62,21 +76,49 @@ declare -A stepX0s=( ["NMSEsection311"]=0.00019998 ["theta"]=0.0966796875 ["ComplexSinCos"]=0.0009765625 + ["NMSEexample33"]=0.000966796875 + ["NMSEproblem332"]=0.000966796875 + ["NMSEproblem335"]=0.000966796875 + ["NMSEsection35"]=0.0009765625 + ["polarToCarthesianX"]=0.0087890625 + ["polarToCarthesianY"]=0.0087890625 + ["i6"]=0.00966796875 ) declare -A x1Starts=( ["theta"]=1 ["ComplexSinCos"]=0 + ["NMSEexample33"]=0 + ["NMSEproblem332"]=0 + ["NMSEproblem335"]=0 + ["NMSEsection35"]=0 + ["polarToCarthesianX"]=0 + ["polarToCarthesianY"]=0 + ["i6"]=-5 ) declare -A x1Ends=( ["theta"]=100 ["ComplexSinCos"]=1 + ["NMSEexample33"]=100 + ["NMSEproblem332"]=100 + ["NMSEproblem335"]=100 + ["NMSEsection35"]=1 + ["polarToCarthesianX"]=360 + ["polarToCarthesianY"]=360 + ["i6"]=5 ) declare -A stepX1s=( ["theta"]=0.0966796875 ["ComplexSinCos"]=0.0009765625 + ["NMSEexample33"]=0.0009765625 + ["NMSEproblem332"]=0.0009765625 + ["NMSEproblem335"]=0.0009765625 + ["NMSEsection35"]=0.0009765625 + ["polarToCarthesianX"]=0.3515625 + ["polarToCarthesianY"]=0.3515625 + ["i6"]=0.009765625 ) declare -A func1s=( @@ -98,6 +140,13 @@ declare -A func1s=( ["NMSEsection311"]=exp ["theta"]=atan ["ComplexSinCos"]=exp + ["NMSEexample33"]=sin + ["NMSEproblem332"]=tan + ["NMSEproblem335"]=cos + ["NMSEsection35"]=exp + ["polarToCarthesianX"]=cos + ["polarToCarthesianY"]=sin + ["i6"]=sin ) declare -A func2s=( diff --git a/srcTest/getOriginErrCost.sh b/srcTest/getOriginErrCost.sh index 73b2def..c30b041 100755 --- a/srcTest/getOriginErrCost.sh +++ b/srcTest/getOriginErrCost.sh @@ -90,4 +90,39 @@ taskset -c 0 ./testPerformanceTwoManual.sh theta origin 1 100 1 100 cd .. ./detectErrorTwoFPEDParallel.sh ComplexSinCos 0 1 0 1 1024 1024 0 0 0 0 0.0009765625 0.0009765625 expr_ComplexSinCos 0_1_0_1_1024_1024 origin 0 cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh ComplexSinCos origin 0 1 0 1 \ No newline at end of file +taskset -c 0 ./testPerformanceTwoManual.sh ComplexSinCos origin 0 1 0 1 + +cd .. +./detectErrorTwoFPEDParallel.sh NMSEexample33 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEexample33 0.01_1_0_100_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh NMSEexample33 origin 0.01 1 0 100 + +cd .. +./detectErrorTwoFPEDParallel.sh NMSEproblem332 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEproblem332 0.01_1_0_100_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh NMSEproblem332 origin 0.01 1 0 100 + +cd .. +./detectErrorTwoFPEDParallel.sh NMSEproblem335 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEproblem335 0.01_1_0_100_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh NMSEproblem335 origin 0.01 1 0 100 + +cd .. +./detectErrorTwoFPEDParallel.sh NMSEsection35 0 1 0 1 1024 1024 0 0 0 0 0.0009765625 0.0009765625 expr_NMSEsection35 0_1_0_1_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh NMSEsection35 origin 0 1 0 1 + +cd .. +./detectErrorTwoFPEDParallel.sh polarToCarthesianX 1 10 0 360 1024 1024 0 0 1 0 0.0087890625 0.3515625 expr_polarToCarthesianX 1_10_0_360_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh polarToCarthesianX origin 1 10 0 360 + +cd .. +./detectErrorTwoFPEDParallel.sh polarToCarthesianY 1 10 0 360 1024 1024 0 0 1 0 0.0087890625 0.3515625 expr_polarToCarthesianY 1_10_0_360_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh polarToCarthesianY origin 1 10 0 360 + +cd .. +./detectErrorTwoFPEDParallel.sh i6 0.1 10 -5 5 1024 1024 0 0 0.1 -5 0.00966796875 0.009765625 expr_i6 0.1_10_-5_5_1024_1024 origin 0 +cd - >/dev/null +taskset -c 0 ./testPerformanceTwoManual.sh i6 origin 0.1 10 -5 5 \ No newline at end of file diff --git a/srcTest/pareto_all_list.sh b/srcTest/pareto_all_list.sh index d4c32b5..30e068a 100755 --- a/srcTest/pareto_all_list.sh +++ b/srcTest/pareto_all_list.sh @@ -131,7 +131,63 @@ taskset -c 0 ./pareto_all_1.sh theta 0.01 100 # y: [0, 1] # sin: [0, 1] # exp: [-1, 1] -taskset -c 0 ./pareto_all_1.sh ComplexSinCos -1 1 0 1 +taskset -c 0 ./pareto_all.sh ComplexSinCos -1 1 0 1 ## TGen # taskset -c 0 python3 per_allversion.py exp -1 1 -# taskset -c 0 python3 per_allversion.py sin 0 1 \ No newline at end of file +# taskset -c 0 python3 per_allversion.py sin 0 1 + +# NMSEexample33 := (sin((x + eps)) - sin(x)) +# eps: [0.01, 1] +# x: [0, 100] +# sin: [0, 101] +taskset -c 0 ./pareto_all_1.sh NMSEexample33 0 101 +## TGen +# taskset -c 0 python3 per_allversion.py sin 0 101 + +# NMSEproblem332 := (tan((x + eps)) - tan(x)) +# eps: [0.01, 1] +# x: [0, 100] +# tan: [0, 101] +taskset -c 0 ./pareto_all_1.sh NMSEproblem332 0 101 +## TGen +# taskset -c 0 python3 per_allversion.py tan 0 101 + +# NMSEproblem335 := (cos((x + eps)) - cos(x)) +# eps: [0.01, 1] +# x: [0, 100] +# cos: [0, 101] +taskset -c 0 ./pareto_all_1.sh NMSEproblem335 0 101 +## TGen +# taskset -c 0 python3 per_allversion.py cos 0 101 + +# NMSEsection35 := (exp((a * x)) - 1.0) +# a: [0, 1] +# x: [0, 1] +# exp: [0, 1] +taskset -c 0 ./pareto_all_1.sh NMSEsection35 +## TGen +# taskset -c 0 python3 per_allversion.py exp 0 1 + +# polarToCarthesianX := (radius * cos((0.017453292519944444 * theta))) +# radius: [1, 10] +# theta: [0, 360] +# cos: [0, 2pi] \approx [0, 6.2832] +taskset -c 0 ./pareto_all_1.sh polarToCarthesianX 0 6.2832 +## TGen +# taskset -c 0 python3 per_allversion.py cos 0 6.2832 + +# polarToCarthesianY := (radius * sin((0.017453292519944444 * theta))) +# radius: [1, 10] +# theta: [0, 360] +# sin: [0, 2pi] \approx [0, 6.2832] +taskset -c 0 ./pareto_all_1.sh polarToCarthesianY +## TGen +# taskset -c 0 python3 per_allversion.py sin 0 6.2832 + +# i6 := sin((x * y)) +# x: [0.1, 10] +# y: [-5, 5] +# sin: [-50, 50] +taskset -c 0 ./pareto_all_1.sh i6 -50 50 +## TGen +# taskset -c 0 python3 per_allversion.py sin -50 50 \ No newline at end of file diff --git a/srcTest/prepare.sh b/srcTest/prepare.sh new file mode 100755 index 0000000..48d0ccd --- /dev/null +++ b/srcTest/prepare.sh @@ -0,0 +1,5 @@ +#/bin/bash +set -x +uniqueLabel=${1} +cp ${uniqueLabel}/expr_${uniqueLabel}_origin.c ${uniqueLabel}/expr_${uniqueLabel}_origin_bkp.c +cp exp1x/myhead.h ${uniqueLabel}/ \ No newline at end of file -- Gitee From e47d935557d7e9b443de3ad2c6c761101ef2b5a7 Mon Sep 17 00:00:00 2001 From: hjw Date: Fri, 22 Sep 2023 21:27:20 +0800 Subject: [PATCH 52/54] Add origin error and performance information to CSV files --- srcTest/getOriginErrCost.sh | 264 +++++++++++++++++++++++++++++------- 1 file changed, 212 insertions(+), 52 deletions(-) diff --git a/srcTest/getOriginErrCost.sh b/srcTest/getOriginErrCost.sh index c30b041..bc4a6b8 100755 --- a/srcTest/getOriginErrCost.sh +++ b/srcTest/getOriginErrCost.sh @@ -1,128 +1,288 @@ +#!/bin/bash +# init for current path +path_current=`pwd` +temp_file=${path_current}/temp.log # 临时文件,在循环中被刷新 +suffix=errPerfParetoSorted +bit1=-1 +degree1=-1 +bit2=-1 +degree2=-1 + +echo +uniqueLabel=NMSEproblem345 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}\t${bit2}\t${degree2}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEproblem345 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem345 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEproblem345 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem345 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem345 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem345 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEexample34 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}\t${bit2}\t${degree2}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEexample34 0.01 3 500000 0 0.01 5.98e-06 expr_NMSEexample34 0.01_3_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEexample34 0.01 3 500000 0 0.01 5.98e-06 expr_NMSEexample34 0.01_3_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEexample34 origin 0.01 3 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample34 origin 0.01 3 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=logexp +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}\t${bit2}\t${degree2}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh logexp -8 8 500000 0 -8 3.2e-05 expr_logexp -8_8_500000 origin 0 +./detectErrorOneFPEDParallel.sh logexp -8 8 500000 0 -8 3.2e-05 expr_logexp -8_8_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh logexp origin -8 8 +taskset -c 0 ./testPerformanceOneManual.sh logexp origin -8 8 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=exp1x_log +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}\t${bit2}\t${degree2}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh exp1x_log 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x_log 0.01_0.5_500000 origin 0 +./detectErrorOneFPEDParallel.sh exp1x_log 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x_log 0.01_0.5_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh exp1x_log origin 0.01 0.5 +taskset -c 0 ./testPerformanceOneManual.sh exp1x_log origin 0.01 0.5 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEproblem343 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -# ./detectErrorOneFPEDParallel.sh NMSEproblem343 -1 1 500000 0 -1 4e-06 expr_NMSEproblem343 -1_1_500000 origin 0 -./detectErrorOneFPEDParallel.sh NMSEproblem343 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEproblem343 -0.5_0.5_500000 origin 0 +# ./detectErrorOneFPEDParallel.sh NMSEproblem343 -1 1 500000 0 -1 4e-06 expr_NMSEproblem343 -1_1_500000 origin 0 | tee -a ${temp_file} +./detectErrorOneFPEDParallel.sh NMSEproblem343 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEproblem343 -0.5_0.5_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null # taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem343 origin -1 1 -taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem343 origin -0.5 0.5 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem343 origin -0.5 0.5 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=exp1x +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh exp1x 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x 0.01_0.5_500000 origin 0 +./detectErrorOneFPEDParallel.sh exp1x 0.01 0.5 500000 0 0.01 9.8e-07 expr_exp1x 0.01_0.5_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh exp1x origin 0.01 0.5 +taskset -c 0 ./testPerformanceOneManual.sh exp1x origin 0.01 0.5 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEexample37 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEexample37 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample37 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEexample37 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample37 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEexample37 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample37 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEexample39 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEexample39 0.01 1 500000 0 0.01 1.98e-06 expr_NMSEexample39 0.01_1_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEexample39 0.01 1 500000 0 0.01 1.98e-06 expr_NMSEexample39 0.01_1_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEexample39 origin 0.01 1 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample39 origin 0.01 1 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEproblem341 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEproblem341 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem341 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEproblem341 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem341 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem341 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem341 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEexample310 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -# ./detectErrorOneFPEDParallel.sh NMSEexample310 -1 1 500000 0 -1 4e-06 expr_NMSEexample310 -1_1_500000 origin 0 -./detectErrorOneFPEDParallel.sh NMSEexample310 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEexample310 -0.5_0.5_500000 origin 0 +# ./detectErrorOneFPEDParallel.sh NMSEexample310 -1 1 500000 0 -1 4e-06 expr_NMSEexample310 -1_1_500000 origin 0 | tee -a ${temp_file} +./detectErrorOneFPEDParallel.sh NMSEexample310 -0.5 0.5 500000 0 -0.5 2e-06 expr_NMSEexample310 -0.5_0.5_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null # taskset -c 0 ./testPerformanceOneManual.sh NMSEexample310 -1 1 -taskset -c 0 ./testPerformanceOneManual.sh NMSEexample310 origin -0.5 0.5 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample310 origin -0.5 0.5 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEexample35 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEexample35 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample35 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEexample35 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample35 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEexample35 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample35 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEexample38 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEexample38 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample38 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEexample38 0.01 100 500000 0 0.01 0.00019998 expr_NMSEexample38 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEexample38 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEexample38 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEproblem336 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEproblem336 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem336 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEproblem336 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem336 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem336 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem336 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEproblem337 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEproblem337 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem337 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEproblem337 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem337 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem337 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem337 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEproblem344 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEproblem344 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem344 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEproblem344 0.01 100 500000 0 0.01 0.00019998 expr_NMSEproblem344 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem344 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEproblem344 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEsection311 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorOneFPEDParallel.sh NMSEsection311 0.01 100 500000 0 0.01 0.00019998 expr_NMSEsection311 0.01_100_500000 origin 0 +./detectErrorOneFPEDParallel.sh NMSEsection311 0.01 100 500000 0 0.01 0.00019998 expr_NMSEsection311 0.01_100_500000 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceOneManual.sh NMSEsection311 origin 0.01 100 +taskset -c 0 ./testPerformanceOneManual.sh NMSEsection311 origin 0.01 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=theta +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh theta 1 100 1 100 1024 1024 0 0 1 1 0.0966796875 0.0966796875 expr_theta 1_100_1_100_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh theta 1 100 1 100 1024 1024 0 0 1 1 0.0966796875 0.0966796875 expr_theta 1_100_1_100_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh theta origin 1 100 1 100 +taskset -c 0 ./testPerformanceTwoManual.sh theta origin 1 100 1 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=ComplexSinCos +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}\t${bit2}\t${degree2}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh ComplexSinCos 0 1 0 1 1024 1024 0 0 0 0 0.0009765625 0.0009765625 expr_ComplexSinCos 0_1_0_1_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh ComplexSinCos 0 1 0 1 1024 1024 0 0 0 0 0.0009765625 0.0009765625 expr_ComplexSinCos 0_1_0_1_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh ComplexSinCos origin 0 1 0 1 +taskset -c 0 ./testPerformanceTwoManual.sh ComplexSinCos origin 0 1 0 1 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEexample33 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh NMSEexample33 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEexample33 0.01_1_0_100_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh NMSEexample33 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEexample33 0.01_1_0_100_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh NMSEexample33 origin 0.01 1 0 100 +taskset -c 0 ./testPerformanceTwoManual.sh NMSEexample33 origin 0.01 1 0 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEproblem332 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh NMSEproblem332 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEproblem332 0.01_1_0_100_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh NMSEproblem332 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEproblem332 0.01_1_0_100_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh NMSEproblem332 origin 0.01 1 0 100 +taskset -c 0 ./testPerformanceTwoManual.sh NMSEproblem332 origin 0.01 1 0 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEproblem335 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh NMSEproblem335 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEproblem335 0.01_1_0_100_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh NMSEproblem335 0.01 1 0 100 1024 1024 0 0 0.01 0 0.000966796875 0.09765625 expr_NMSEproblem335 0.01_1_0_100_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh NMSEproblem335 origin 0.01 1 0 100 +taskset -c 0 ./testPerformanceTwoManual.sh NMSEproblem335 origin 0.01 1 0 100 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=NMSEsection35 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh NMSEsection35 0 1 0 1 1024 1024 0 0 0 0 0.0009765625 0.0009765625 expr_NMSEsection35 0_1_0_1_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh NMSEsection35 0 1 0 1 1024 1024 0 0 0 0 0.0009765625 0.0009765625 expr_NMSEsection35 0_1_0_1_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh NMSEsection35 origin 0 1 0 1 +taskset -c 0 ./testPerformanceTwoManual.sh NMSEsection35 origin 0 1 0 1 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=polarToCarthesianX +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh polarToCarthesianX 1 10 0 360 1024 1024 0 0 1 0 0.0087890625 0.3515625 expr_polarToCarthesianX 1_10_0_360_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh polarToCarthesianX 1 10 0 360 1024 1024 0 0 1 0 0.0087890625 0.3515625 expr_polarToCarthesianX 1_10_0_360_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh polarToCarthesianX origin 1 10 0 360 +taskset -c 0 ./testPerformanceTwoManual.sh polarToCarthesianX origin 1 10 0 360 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=polarToCarthesianY +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh polarToCarthesianY 1 10 0 360 1024 1024 0 0 1 0 0.0087890625 0.3515625 expr_polarToCarthesianY 1_10_0_360_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh polarToCarthesianY 1 10 0 360 1024 1024 0 0 1 0 0.0087890625 0.3515625 expr_polarToCarthesianY 1_10_0_360_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh polarToCarthesianY origin 1 10 0 360 +taskset -c 0 ./testPerformanceTwoManual.sh polarToCarthesianY origin 1 10 0 360 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} +echo +uniqueLabel=i6 +echo ${uniqueLabel} +log_file=${path_current}/${uniqueLabel}_${suffix}.csv # 其中依次记录的是: 函数名, bit, degree, 平均误差, 最大误差, 性能节拍 +echo -e "${bit1}\t${degree1}" > ${temp_file} cd .. -./detectErrorTwoFPEDParallel.sh i6 0.1 10 -5 5 1024 1024 0 0 0.1 -5 0.00966796875 0.009765625 expr_i6 0.1_10_-5_5_1024_1024 origin 0 +./detectErrorTwoFPEDParallel.sh i6 0.1 10 -5 5 1024 1024 0 0 0.1 -5 0.00966796875 0.009765625 expr_i6 0.1_10_-5_5_1024_1024 origin 0 | tee -a ${temp_file} cd - >/dev/null -taskset -c 0 ./testPerformanceTwoManual.sh i6 origin 0.1 10 -5 5 \ No newline at end of file +taskset -c 0 ./testPerformanceTwoManual.sh i6 origin 0.1 10 -5 5 | tee -a ${temp_file} +awk 'NR == 1 { printf "%s\t", $0 }; NR == 3 { printf "%s\t", $1 }; NR == 5 { print $0 }' ${temp_file} >> ${log_file} \ No newline at end of file -- Gitee From 846ef76ec7d07c4a90e2c7ccdc497e9d1ae3bbc4 Mon Sep 17 00:00:00 2001 From: hjw Date: Fri, 22 Sep 2023 21:27:56 +0800 Subject: [PATCH 53/54] Fix number error --- srcTest/pareto_all_list.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcTest/pareto_all_list.sh b/srcTest/pareto_all_list.sh index 30e068a..a98219b 100755 --- a/srcTest/pareto_all_list.sh +++ b/srcTest/pareto_all_list.sh @@ -180,7 +180,7 @@ taskset -c 0 ./pareto_all_1.sh polarToCarthesianX 0 6.2832 # radius: [1, 10] # theta: [0, 360] # sin: [0, 2pi] \approx [0, 6.2832] -taskset -c 0 ./pareto_all_1.sh polarToCarthesianY +taskset -c 0 ./pareto_all_1.sh polarToCarthesianY 0 6.2832 ## TGen # taskset -c 0 python3 per_allversion.py sin 0 6.2832 -- Gitee From 0ff605d8c621d4113d72c5848a896b0aa636c04d Mon Sep 17 00:00:00 2001 From: hjw Date: Sat, 30 Sep 2023 17:13:46 +0800 Subject: [PATCH 54/54] Complete cost time test --- srcTest/pareto_all_list.sh | 125 +++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/srcTest/pareto_all_list.sh b/srcTest/pareto_all_list.sh index a98219b..75579f1 100755 --- a/srcTest/pareto_all_list.sh +++ b/srcTest/pareto_all_list.sh @@ -2,7 +2,12 @@ # NMSEproblem345 := (/ (- x (sin x)) (- x (tan x))) # sin: [0.01, 100] # tan: [0.01, 100] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all.sh NMSEproblem345 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEproblem345 time is ${duration} s." +echo "NMSEproblem345 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py sin 0.01 100 # taskset -c 0 python3 per_allversion.py tan 0.01 100 @@ -10,7 +15,12 @@ taskset -c 0 ./pareto_all.sh NMSEproblem345 # NMSEexample34: (/ (- 1 (cos x)) (sin x)) # sin: [0.01, 3] # cos: [0.01, 3] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all.sh NMSEexample34 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEexample34 time is ${duration} s." +echo "NMSEexample34 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py sin 0.01 3 # taskset -c 0 python3 per_allversion.py cos 0.01 3 @@ -18,7 +28,12 @@ taskset -c 0 ./pareto_all.sh NMSEexample34 # logexp := log (+ 1 (exp x)) # exp: [-8, 8] # log: [1 + exp(-8), 1 + exp(8)] = [1.000335, 2,981.957987] \approx [1, 2982] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all.sh logexp -8 8 1 2982 +end_time=$(date +%s.%n) +duration=$(echo "$end_time - $start_time" | bc) +echo "logexp time is ${duration} s." +echo "logexp time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp -8 8 # taskset -c 0 python3 per_allversion.py log 1 2982 @@ -26,7 +41,12 @@ taskset -c 0 ./pareto_all.sh logexp -8 8 1 2982 # exp1x_log := ((exp(x) - 1.0) / log(exp(x))) # exp: [0.01, 0.5] # log: [e^0.01, e^0.5] \approx [1, 1.65] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all.sh exp1x_log 0.01 0.5 1 1.65 +end_time=$(date +%s.%n) +duration=$(echo "$end_time - $start_time" | bc) +echo "exp1x_log time is ${duration} s." +echo "exp1x_log time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp 0.01 0.5 # taskset -c 0 python3 per_allversion.py log 1 1.65 @@ -38,31 +58,56 @@ taskset -c 0 ./pareto_all.sh exp1x_log 0.01 0.5 1 1.65 # taskset -c 0 ./pareto_all_1.sh NMSEproblem343 0.5 1 # eps: [-1/2, 1/2] # log: (1/3, 3) +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEproblem343 0.3 3 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEproblem343 time is ${duration} s." +echo "NMSEproblem343 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py log 0.3 3 # exp1x := (exp(x) - 1) / x # exp: [0.01, 0.5] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh exp1x +end_time=$(date +%s.%n) +duration=$(echo "$end_time - $start_time" | bc) +echo "exp1x time is ${duration} s." +echo "exp1x time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp 0.01 0.5 # NMSEexample37 := exp(x) - 1 # exp: [0.01, 100] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEexample37 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEexample37 time is ${duration} s." +echo "NMSEexample37 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp 0.01 100 # NMSEexample39 := (- (/ 1 x) (/ 1 (tan x))) # tan: [0.01, 1] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEexample39 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEexample39 time is ${duration} s." +echo "NMSEexample39 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py tan 0.01 1 # NMSEproblem341 := (/ (- 1 (cos x)) (* x x)) # cos: [0.01, 100] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEproblem341 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEproblem341 time is ${duration} s." +echo "NMSEproblem341 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py cos 0.01 100 @@ -72,49 +117,84 @@ taskset -c 0 ./pareto_all_1.sh NMSEproblem341 # taskset -c 0 ./pareto_all_1.sh NMSEexample310 0 2 # x: -1/2, 1/2 # log: [1/2, 3/2] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEexample310 0.5 1.5 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEexample310 time is ${duration} s." +echo "NMSEexample310 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py log 0.5 1.5 # NMSEexample35 := (atan((x + 1.0)) - atan(x)) # x: [0.01, 100] # atan: [0.01, 101] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEexample35 0.01 101 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEexample35 time is ${duration} s." +echo "NMSEexample35 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py atan 0.01 101 # NMSEexample38 := ((((x + 1.0) * log((x + 1.0))) - (x * log(x))) - 1.0) # x: [0.01, 100] # log: [0.01, 101] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEexample38 0.01 101 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEexample38 time is ${duration} s." +echo "NMSEexample38 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py log 0.01 101 # NMSEproblem336 := (log((x + 1.0)) - log(x)) # x: [0.01, 100] # log: [0.01, 101] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEproblem336 0.01 101 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEproblem336 time is ${duration} s." +echo "NMSEproblem336 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py log 0.01 101 # NMSEproblem337 := ((exp(x) + (-1.0 * 2.0)) + exp((-1.0 * x))) # x: [0.01, 100] # exp: [-100, -0.01] & [0.01, 100] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEproblem337 -100 100 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEproblem337 time is ${duration} s." +echo "NMSEproblem337 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp -100 100 # NMSEproblem344 := (exp(x) / (exp(x) - 1.0)) # x: [0.01, 100] # exp: [0.01, 100] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEproblem344 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEproblem344 time is ${duration} s." +echo "NMSEproblem344 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp 0.01 100 # NMSEsection311 := sqrt(((exp((2.0 * x)) - 1.0) / (exp(x) - 1.0))) # x: [0.01, 100] # exp: [0.01, 200] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEsection311 0.01 200 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEsection311 time is ${duration} s." +echo "NMSEsection311 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp 0 200 @@ -122,7 +202,12 @@ taskset -c 0 ./pareto_all_1.sh NMSEsection311 0.01 200 # x: [1, 100] # y: [1, 100] # atan: [0.01, 100] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh theta 0.01 100 +end_time=$(date +%s.%n) +duration=$(echo "$end_time - $start_time" | bc) +echo "theta time is ${duration} s." +echo "theta time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py atan 0.01 100 @@ -131,7 +216,12 @@ taskset -c 0 ./pareto_all_1.sh theta 0.01 100 # y: [0, 1] # sin: [0, 1] # exp: [-1, 1] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all.sh ComplexSinCos -1 1 0 1 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "ComplexSinCos time is ${duration} s." +echo "ComplexSinCos time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp -1 1 # taskset -c 0 python3 per_allversion.py sin 0 1 @@ -140,7 +230,12 @@ taskset -c 0 ./pareto_all.sh ComplexSinCos -1 1 0 1 # eps: [0.01, 1] # x: [0, 100] # sin: [0, 101] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEexample33 0 101 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEexample33 time is ${duration} s." +echo "NMSEexample33 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py sin 0 101 @@ -148,7 +243,12 @@ taskset -c 0 ./pareto_all_1.sh NMSEexample33 0 101 # eps: [0.01, 1] # x: [0, 100] # tan: [0, 101] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEproblem332 0 101 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEproblem332 time is ${duration} s." +echo "NMSEproblem332 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py tan 0 101 @@ -156,7 +256,12 @@ taskset -c 0 ./pareto_all_1.sh NMSEproblem332 0 101 # eps: [0.01, 1] # x: [0, 100] # cos: [0, 101] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEproblem335 0 101 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEproblem335 time is ${duration} s." +echo "NMSEproblem335 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py cos 0 101 @@ -164,7 +269,12 @@ taskset -c 0 ./pareto_all_1.sh NMSEproblem335 0 101 # a: [0, 1] # x: [0, 1] # exp: [0, 1] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh NMSEsection35 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "NMSEsection35 time is ${duration} s." +echo "NMSEsection35 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py exp 0 1 @@ -172,7 +282,12 @@ taskset -c 0 ./pareto_all_1.sh NMSEsection35 # radius: [1, 10] # theta: [0, 360] # cos: [0, 2pi] \approx [0, 6.2832] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh polarToCarthesianX 0 6.2832 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "polarToCarthesianX time is ${duration} s." +echo "polarToCarthesianX time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py cos 0 6.2832 @@ -180,7 +295,12 @@ taskset -c 0 ./pareto_all_1.sh polarToCarthesianX 0 6.2832 # radius: [1, 10] # theta: [0, 360] # sin: [0, 2pi] \approx [0, 6.2832] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh polarToCarthesianY 0 6.2832 +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc) +echo "polarToCarthesianY time is ${duration} s." +echo "polarToCarthesianY time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py sin 0 6.2832 @@ -188,6 +308,11 @@ taskset -c 0 ./pareto_all_1.sh polarToCarthesianY 0 6.2832 # x: [0.1, 10] # y: [-5, 5] # sin: [-50, 50] +start_time=$(date +%s.%n) taskset -c 0 ./pareto_all_1.sh i6 -50 50 +end_time=$(date +%s.%n) +duration=$(echo "$end_time - $start_time" | bc) +echo "i6 time is ${duration} s." +echo "i6 time is ${duration} s." >> hjwTime.log ## TGen # taskset -c 0 python3 per_allversion.py sin -50 50 \ No newline at end of file -- Gitee