diff --git a/.gitignore b/.gitignore index cbef0f1540b7e0af86f51284794eb78cab722a0a..5927ad71ba4600f15491964985d39d09d823e3c8 100644 --- a/.gitignore +++ b/.gitignore @@ -36,9 +36,11 @@ .history/ build/ srcGen/ +libs/ main *.txt __pycache__/ expr_*.c run.log -includeTEST/mine.h \ No newline at end of file +includeTEST/mine.h +*.csv diff --git a/benchMark.txt b/benchMark.txt index f2f0ea3e95d31e77465e25bd60bbbd478b91f648..17ccd1f199480eb076a75ce87c7ce44f987d2591 100644 --- a/benchMark.txt +++ b/benchMark.txt @@ -35,8 +35,8 @@ 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+ 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)) hypot32 sqrt(x1*x1+x2*x2) -i4 sqrt(x+y*y) -i6 sin(x*y) +i4 sqrtf(x+y*y) +i6 sinf(x*y) NMSEexample33 sin(x+eps) - sin(x) NMSEproblem332 tan(x+eps) - tan(x) NMSEproblem335 cos(x+eps) - cos(x) @@ -85,4 +85,16 @@ coshTaylorPoly7 1 + 0.5 * x * x + 1.0 / 24.0 * x * x * x * x + 1.0 / 720.0 * x tanhTaylorPoly7 x + -1.0 / 3.0 * x * x * x + 2.0 / 15.0 * x * x * x * x * x + -17.0 / 315.0 * x * x * x * x * x * x * x asinhTaylorPoly7 x + -1.0 / 6.0 * x * x * x + 3.0 / 40.0 * x * x * x * x * x + -5.0 / 112.0 * x * x * x * x * x * x * x acoshTaylorPoly7 -10.93051753399604 + 29.957916712389473 * x + -35.58080559049901 * x * x +25.219476933674876 * x * x * x + -11.066799860894648 * x * x * x * x + 2.970361895278266 * x * x * x * x * x + -0.44893622077214135 * x * x * x * x * x * x + 0.029376877759354054 * x * x * x * x * x * x * x -atanhTaylorPoly7 x + 1.0 / 3.0 * (x * x) * x + 1.0 / 5.0 * (x * x) * x * x * x + 1.0 / 7.0 * (x * x) * x * x * x * x * x \ No newline at end of file +atanhTaylorPoly7 x + 1.0 / 3.0 * (x * x) * x + 1.0 / 5.0 * (x * x) * x * x * x + 1.0 / 7.0 * (x * x) * x * x * x * x * x +squareRoot3_1 1 + 0.5 * x +squareRoot3_2 sqrt(1 + x) +squareRoot3Invalid_1 1 + 0.5 * x +squareRoot3Invalid_2 sqrt(1 + x) +cav10_1 x / 10.0 +cav10_2 x * x + 2 +gustafsonExample_1 1 +gustafsonExample_2 (exp(((fabs((x - sqrt(((x * x) + 1.0)))) - (1.0 / (x + sqrt(((x * x) + 1.0))))) * (fabs((x - sqrt(((x * x) + 1.0)))) - (1.0 / (x + sqrt(((x * x) + 1.0))))))) - 1.0) / x +smartRoot_1 (c * 2.0) / (-3.5 - sqrt(((3.5 * 3.5) - ((3.0 * c) * 4.0)))) +smartRoot_2 (-3.5 + sqrt(((3.5 * 3.5) - ((3.0 * c) * 4.0)))) / (3.0 * 2.0) +triangleSorted_1 sqrt(((((c + (b + a)) * (a - (c - b))) * (a + (c - b))) * (c + (b - a)))) / 4.0 +triangleSorted_2 sqrt(((((c + (a + b)) * (b - (c - a))) * (b + (c - a))) * (c + (a - b)))) / 4.0; \ No newline at end of file diff --git a/benchMarkInterval.txt b/benchMarkInterval.txt index 0715ee06c51ecf68ca8cc7ca826f1e55e5423968..7dcf73b039f4dbc3841db40716791c95e0b51380 100644 --- a/benchMarkInterval.txt +++ b/benchMarkInterval.txt @@ -4,7 +4,7 @@ 0 999 -8 8 0.01 100 --0.5 0.5 +-1 1 0.01 3 0.01 100 0.01 100 @@ -85,4 +85,16 @@ 0 1 0 1 2 3 -0 1 \ No newline at end of file +0 1 +0 0.00001 +0.00001 10 +0 0.0001 +0.0001 10 +0 10 +0 10 +0 100 +0 100 +-2 2 +-2 2 +1 9 1 9 1 9 +1 9 1 9 1 9 \ No newline at end of file diff --git a/detectErrorOneFPEDParallel.sh b/detectErrorOneFPEDParallel.sh index d799fb35d8028bc89f600d7a9ca6e64dc273eb1d..140564f60bb9f4c74ee150c8a31d3565c566ad72 100755 --- a/detectErrorOneFPEDParallel.sh +++ b/detectErrorOneFPEDParallel.sh @@ -8,23 +8,32 @@ CC=mpicc uniqueLabel=${1} # unique number x0Start=${2} x0End=${3} -if [ $# -eq 8 ]; then +if [ $# -eq 11 ]; then x0Size=${4} - prefix=${5} # expr_${uniqueLabel}. Eg: expr_20221030155958 - middle=${6} # intervalsInfo_sizes. Eg: 3.8_7.8_500000 - suffix=${7} # different version. Eg: herbie daisy origin temp_0_3 final - errfile=${8} # 1 or 0: TRUE or False -elif [ $# -eq 7 ]; then + x0startNowIdx=${5} # the index of the start point of the current interval. + x0startOriginInterval=${6} # the value of the start point of the origin interval. + stepX0=${7} # the step for sampling points. + prefix=${8} # expr_${uniqueLabel}. Eg: expr_20221030155958 + middle=${9} # intervalsInfo_sizes. Eg: 3.8_7.8_500000 + suffix=${10} # different version. Eg: herbie daisy origin temp_0_3 final + errfile=${11} # 1 or 0: TRUE or False +elif [ $# -eq 10 ]; then x0Size=${4} - prefix=${5} # expr_${uniqueLabel}. Eg: expr_20221030155958 - middle=${6} # intervalsInfo_sizes. Eg: 3.8_7.8_500000 - suffix=${7} # different version. Eg: herbie daisy origin temp_0_3 final + x0startNowIdx=${5} # the index of the start point of the current interval. + x0startOriginInterval=${6} # the value of the start point of the origin interval. + stepX0=${7} # the step for sampling points. + prefix=${8} # expr_${uniqueLabel}. Eg: expr_20221030155958 + middle=${9} # intervalsInfo_sizes. Eg: 3.8_7.8_500000 + suffix=${10} # different version. Eg: herbie daisy origin temp_0_3 final errfile=0 -elif [ $# -eq 6 ]; then +elif [ $# -eq 9 ]; then x0Size=500000 - prefix=${4} - middle=${5} - suffix=${6} + x0startNowIdx=${5} # the index of the start point of the current interval. + x0startOriginInterval=${6} # the value of the start point of the origin interval. + stepX0=${7} # the step for sampling points. + prefix=${8} + middle=${9} + suffix=${10} errfile=0 else echo "detectErrorOneFPEDParallel: Invalid input parameters" @@ -42,7 +51,7 @@ 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 # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${fileNameKernel}" -mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${fileNameKernel} ${uniqueLabel} +mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${x0startNowIdx} ${x0startOriginInterval} ${stepX0} ${fileNameKernel} ${uniqueLabel} # mv outputs/${fileNameKernel}_error.txt ./outputs/${uniqueLabel}/${fileNameKernel}_error.txt rm ${testFileName}.exe diff --git a/detectErrorThreeFPEDParallel.sh b/detectErrorThreeFPEDParallel.sh index acf2e5bfe77b05e7e6e4735096b66e4070be8f2c..84957689675d7302a8423778f4f2cd7636729cd4 100755 --- a/detectErrorThreeFPEDParallel.sh +++ b/detectErrorThreeFPEDParallel.sh @@ -12,29 +12,56 @@ x1Start=${4} x1End=${5} x2Start=${6} x2End=${7} -if [ $# -eq 14 ]; then +if [ $# -eq 23 ]; then x0Size=${8} x1Size=${9} x2Size=${10} - prefix=${11} # expr_${uniqueLabel}. Eg: expr_20221030155958 - middle=${12} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 - suffix=${13} # different version. Eg: herbie daisy origin temp_0_3 final - errfile=${14} # 1 or 0: TRUE or False -elif [ $# -eq 13 ]; then + x0startNowIdx=${11} # the index of the start point of the current interval. + x1startNowIdx=${12} + x2startNowIdx=${13} + x0startOriginInterval=${14} # the value of the start point of the origin interval. + x1startOriginInterval=${15} + x2startOriginInterval=${16} + stepX0=${17} # the step for sampling points. + stepX1=${18} + stepX2=${19} + prefix=${20} # expr_${uniqueLabel}. Eg: expr_20221030155958 + middle=${21} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 + suffix=${22} # different version. Eg: herbie daisy origin temp_0_3 final + errfile=${23} # 1 or 0: TRUE or False +elif [ $# -eq 22 ]; then x0Size=${8} x1Size=${9} x2Size=${10} - prefix=${11} # expr_${uniqueLabel}. Eg: expr_20221030155958 - middle=${12} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 - suffix=${13} # different version. Eg: herbie daisy origin temp_0_3 final + x0startNowIdx=${11} # the index of the start point of the current interval. + x1startNowIdx=${12} + x2startNowIdx=${13} + x0startOriginInterval=${14} # the value of the start point of the origin interval. + x1startOriginInterval=${15} + x2startOriginInterval=${16} + stepX0=${17} # the step for sampling points. + stepX1=${18} + stepX2=${19} + prefix=${20} # expr_${uniqueLabel}. Eg: expr_20221030155958 + middle=${21} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 + suffix=${22} # different version. Eg: herbie daisy origin temp_0_3 final errfile=0 # 1 or 0: TRUE or False -elif [ $# -eq 10 ]; then +elif [ $# -eq 19 ]; then x0Size=256 x1Size=256 x2Size=256 - prefix=${8} - middle=${9} - suffix=${10} + x0startNowIdx=${8} # the index of the start point of the current interval. + x1startNowIdx=${9} + x2startNowIdx=${10} + x0startOriginInterval=${11} # the value of the start point of the origin interval. + x1startOriginInterval=${12} + x2startOriginInterval=${13} + stepX0=${14} # the step for sampling points. + stepX1=${15} + stepX2=${16} + prefix=${17} # expr_${uniqueLabel}. Eg: expr_20221030155958 + middle=${18} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 + suffix=${19} # different version. Eg: herbie daisy origin temp_0_3 final errfile=0 # 1 or 0: TRUE or False else echo "detectErrorThreeParallel: Invalid input parameters" @@ -51,7 +78,7 @@ 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 # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${fileNameKernel}" -mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${fileNameKernel} ${uniqueLabel} +mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${x0startNowIdx} ${x1startNowIdx} ${x2startNowIdx} ${x0startOriginInterval} ${x1startOriginInterval} ${x2startOriginInterval} ${stepX0} ${stepX1} ${stepX2} ${fileNameKernel} ${uniqueLabel} rm ${testFileName}.exe # combine files diff --git a/detectErrorTwoFPEDParallel.sh b/detectErrorTwoFPEDParallel.sh index 29ee6cbdf4396dfc8d48a906adab144838a57949..e78b686d802c2460fc4dbf49288020a55fc2fe33 100755 --- a/detectErrorTwoFPEDParallel.sh +++ b/detectErrorTwoFPEDParallel.sh @@ -11,26 +11,44 @@ x0End=${3} x1Start=${4} x1End=${5} -if [ $# -eq 11 ]; then +if [ $# -eq 17 ]; then x0Size=${6} x1Size=${7} - prefix=${8} # expr_${uniqueLabel}. Eg: expr_20221030155958 - middle=${9} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 - suffix=${10} # different version. Eg: herbie daisy origin temp_0_3 final - errfile=${11} # 1 or 0: TRUE or False -elif [ $# -eq 10 ]; then + x0startNowIdx=${8} # the index of the start point of the current interval. + x1startNowIdx=${9} + x0startOriginInterval=${10} # the value of the start point of the origin interval. + x1startOriginInterval=${11} + stepX0=${12} # the step for sampling points. + stepX1=${13} + prefix=${14} # expr_${uniqueLabel}. Eg: expr_20221030155958 + middle=${15} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 + suffix=${16} # different version. Eg: herbie daisy origin temp_0_3 final + errfile=${17} # 1 or 0: TRUE or False +elif [ $# -eq 16 ]; then x0Size=${6} x1Size=${7} - prefix=${8} # expr_${uniqueLabel}. Eg: expr_20221030155958 - middle=${9} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 - suffix=${10} # different version. Eg: herbie daisy origin temp_0_3 final + x0startNowIdx=${8} # the index of the start point of the current interval. + x1startNowIdx=${9} + x0startOriginInterval=${10} # the value of the start point of the origin interval. + x1startOriginInterval=${11} + stepX0=${12} # the step for sampling points. + stepX1=${13} + prefix=${14} # expr_${uniqueLabel}. Eg: expr_20221030155958 + middle=${15} # intervalsInfo_sizes. Eg: 3.8_7.8_-4.5_-0.3_0.4_0.9_256_256_256 + suffix=${16} # different version. Eg: herbie daisy origin temp_0_3 final errfile=0 # 1 or 0: TRUE or False -elif [ $# -eq 8 ]; then +elif [ $# -eq 14 ]; then x0Size=1024 x1Size=1024 - prefix=${6} - middle=${7} - suffix=${8} + x0startNowIdx=${6} # the index of the start point of the current interval. + x1startNowIdx=${7} + x0startOriginInterval=${8} # the value of the start point of the origin interval. + x1startOriginInterval=${9} + stepX0=${10} # the step for sampling points. + stepX1=${11} + prefix=${12} + middle=${13} + suffix=${14} errfile=0 # 1 or 0: TRUE or False else echo "detectErrorTwoFPEDParallel: Invalid input parameters" @@ -49,7 +67,7 @@ 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=${suffixClean} -DERRFILE=${errfile} -Llibs -lTGen -lmpfr -lm -lqd -o ${testFileName}.exe # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${fileNameKernel}" -mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x0Size} ${x1Size} ${fileNameKernel} ${uniqueLabel} +mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x0Size} ${x1Size} ${x0startNowIdx} ${x1startNowIdx} ${x0startOriginInterval} ${x1startOriginInterval} ${stepX0} ${stepX1} ${fileNameKernel} ${uniqueLabel} rm ${testFileName}.exe # TODO: 进一步配适多参采样测试 diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 39e399e7a507aa3b9c69e156a72bed4f35dab9f9..66dfb90e9deed3fb3c82e4367687fad597a926a0 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -29,7 +29,7 @@ void geneHerbieCode(string exprstr, vector cs, string exprname, double v string geneHerbieCode(string uniqueLabel); -void geneDaisyCode(string exprStr); +string geneDaisyCode(string uniqueLabel); string geneMpfrCode(const ast_ptr &exprAst, const string uniqueLabel, vector vars); diff --git a/include/mathfuncRewrite.hpp b/include/mathfuncRewrite.hpp index a9355d542cece872f17f5ec7b3944bed23cabb9c..bf355ab3217f19001b4202d0f075e4a73bd845c0 100644 --- a/include/mathfuncRewrite.hpp +++ b/include/mathfuncRewrite.hpp @@ -38,4 +38,14 @@ ast_ptr toPow(const ast_ptr &expr); ast_ptr sumToProduct(const ast_ptr &expr); +ast_ptr fmaToMulAndAdd(const ast_ptr &expr); + +vector powCombine(const ast_ptr& expr); + +vector sqrtCombine(const ast_ptr& expr); + +ast_ptr powToMul(const ast_ptr& expr); + +ast_ptr expToCosh(const ast_ptr& expr); + #endif diff --git a/include/tools.hpp b/include/tools.hpp index 234fe935405a22997368ecb8e49cd22d193fe575..3da62f359013e2b331d2a8b4f03b80bb3e76fdd7 100644 --- a/include/tools.hpp +++ b/include/tools.hpp @@ -16,9 +16,9 @@ public: string suffix; string exprStr; double error; - double aveError; - double maxError; - double performance; + double aveError = -1; + double maxError = -1; + double performance = -1; size_t rewriteID; }; @@ -30,7 +30,7 @@ vector getScales(string scale, const char *split); void sampleError(string uniqueLabel, string suffix, const vector &intervals, const vector &scales); -exprInfo testError(string uniqueLabel, string suffix, const vector &intervals, const vector &scales, bool errfile = false); +exprInfo testError(string uniqueLabel, string suffix, const vector &intervals, const vector &scales, const vector &startNowIdxs, const vector &startOriginIntervals, const vector &steps, bool errfile = false); exprInfo testError(string uniqueLabel, string suffix, double x0Start, double x0End, int scale); diff --git a/src/basic.cpp b/src/basic.cpp index 53e83aa18c026e4d91ca6382930d0248874c04f2..417766b6136a1678ab3a587bd32a4ed2b0c2eec1 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -752,7 +752,10 @@ void write_to_file(const string &uniqueLabel, const string &exprOriginBest, cons outputFile << exprOriginBest << ", "; for (const auto &val : data) { - outputFile << val << ", "; + if(int(val) - val == 0) + outputFile << fmt::format("{}", val) << ", "; + else + outputFile << fmt::format("{:.6e}", val) << ", "; } outputFile << std::endl; outputFile.close(); diff --git a/src/exprAuto.cpp b/src/exprAuto.cpp index f3a39a6a6866c0d182582b3f6eee2722f18b22be..86b58d5356dfdae7d1e6cc1c5cbe07a0b6bdd6ce 100644 --- a/src/exprAuto.cpp +++ b/src/exprAuto.cpp @@ -281,6 +281,15 @@ ast_ptr dealWithCallsKernel(const ast_ptr &expr, const string callee) // cout << "dealWithCallsKernel: That is " << callee << endl; result = sqrtTohypot(expr); } + else if(callee == "fma") + { + // cout << "dealWithCallsKernel: That is " << callee << endl; + result = fmaToMulAndAdd(expr); + } + else if (callee == "pow") + { + result = powToMul(expr); + } else { // cout << "dealWithCallsKernel: default: That is " << callee << endl; @@ -456,6 +465,18 @@ vector dealWithBinOpKernel(const ast_ptr &expr, const char &op) auto tmps = exprAutoNew(result1, false); mineAppend(results, tmps); } + auto result2 = expToCosh(expr); + if(result2 != nullptr) + { + results.push_back(std::move(result2)); + } + } + else if(op == '*') + { + auto tmps = powCombine(expr); + mineAppend(results, tmps); + auto tmps1 = sqrtCombine(expr); + mineAppend(results, tmps1); } else { @@ -506,6 +527,69 @@ vector dealWithBinOp(vector &exprs, const char &op) return results; } +vector mathfuncRewriteNew(const ast_ptr &expr) +{ + static size_t callCount = 0; + callCount++; + callLevel++; + string prompt(callLevel * promtTimes, callLevelChar); + prompt.append(callCount, callCountChar); + prompt += "mathfuncRewriteNew: "; + // if(callCount == 1) cout << prompt << "start--------" << endl; + + vector exprsFinal; + if(expr == nullptr) + { + cerr << "ERROR: mathfuncRewriteNew: empty" << endl; + exit(EXIT_FAILURE); + } + if(expr->type() != "Binary") // May be variable or number + { + callCount--; + callLevel--; + return exprsFinal; + } + + BinaryExprAST *binOpPtr = dynamic_cast(expr.get()); + char op = binOpPtr->getOp(); + auto &lhs = binOpPtr->getLHS(); + auto &rhs = binOpPtr->getRHS(); + auto lhsNewASTsInit = mathfuncRewrite(lhs, false); + vector lhsNewASTs; + for(size_t i = 0; i < lhsNewASTsInit.size(); i++) + { + auto &lhsNewAST = lhsNewASTsInit.at(i); + if(!isEqual(lhsNewAST, lhs)) + lhsNewASTs.push_back(std::move(lhsNewAST)); + } + + auto rhsNewASTsInit = mathfuncRewrite(rhs, false); + vector rhsNewASTs; + for(size_t i = 0; i < rhsNewASTsInit.size(); i++) + { + auto &rhsNewAST = rhsNewASTsInit.at(i); + if(!isEqual(rhsNewAST, rhs)) + rhsNewASTs.push_back(std::move(rhsNewAST)); + } + if(lhsNewASTs.size() == 0) + { + lhsNewASTs.push_back(lhs->Clone()); + } + if(rhsNewASTs.size() == 0) + { + rhsNewASTs.push_back(rhs->Clone()); + } + auto newASTs = createAllBinary(lhsNewASTs, rhsNewASTs, op); + deleteTheSame(newASTs); + newASTs = dealWithBinOp(newASTs, op); + exprsFinal.insert(exprsFinal.end(), std::make_move_iterator(newASTs.begin()), std::make_move_iterator(newASTs.end())); + deleteTheSame(exprsFinal); + + callCount--; + callLevel--; + return exprsFinal; +} + vector mathfuncRewrite(const ast_ptr &expr, bool addSelf) { static size_t callCount = 0; @@ -519,7 +603,7 @@ vector mathfuncRewrite(const ast_ptr &expr, bool addSelf) // fprintf(stderr, "\tmathfuncRewrite: start--------\n"); if(expr == nullptr) { - cerr << prompt << "ERROR: empty" << endl; + cerr << prompt << "ERROR: mathfuncRewrite: empty" << endl; exit(EXIT_FAILURE); } // printExpr(expr, "\tmathfuncRewrite: at the beginning: "); @@ -534,7 +618,28 @@ vector mathfuncRewrite(const ast_ptr &expr, bool addSelf) { // printExpr(expr, prompt + "before dealWithCalls: newexpr = "); auto newASTs = dealWithCalls(newexpr); - exprsFinal.insert(exprsFinal.end(), std::make_move_iterator(newASTs.begin()), std::make_move_iterator(newASTs.end())); + if(callCount == 1) printExprs(newASTs, "\tmathfuncRewrite: newASTs = "); + vector tmps1; + for(auto &newAST : newASTs) + { + auto tmps = mathfuncRewriteNew(newAST); + mineAppend(tmps1, tmps); + } + exprsFinal.insert(exprsFinal.end(), std::make_move_iterator(newASTs.begin()), std::make_move_iterator(newASTs.end())); + while(tmps1.size() != 0) + { + vector tmps3; + for(auto &tmp1 : tmps1) + { + auto tmps2 = mathfuncRewriteNew(tmp1); + if(!(tmps2.size() == 1 && isEqual(tmps2.at(0), tmp1))) + mineAppend(tmps3, tmps2); + } + exprsFinal.insert(exprsFinal.end(), std::make_move_iterator(tmps1.begin()), std::make_move_iterator(tmps1.end())); + tmps1.clear(); + tmps1.insert(tmps1.end(), std::make_move_iterator(tmps3.begin()), std::make_move_iterator(tmps3.end())); + } + if(callCount == 1) deleteTheSame(exprsFinal); // if(callCount == 1) printExprs(exprsFinal, "\tmathfuncRewrite: "); // if(callCount == 1) cout << prompt << "end--------" << endl; @@ -924,8 +1029,9 @@ vector tryRewrite(ast_ptr expr, bool addSelf) cerr << prompt << "we can not handle this situation!" << endl; exit(EXIT_FAILURE); } - // if(callCount == 1) printExpr(exprNew, prompt + "tryRewrites: before mathfuncRewrite: "); + if(callCount == 1) printExpr(exprNew, prompt + "tryRewrites: before mathfuncRewrite: "); auto middles = mathfuncRewrite(exprNew, addSelf); + if(callCount == 1) printExpr(exprNew, prompt + "tryRewrites: after mathfuncRewrite: "); vector results; size_t index = 0; for(const auto &middle : middles) @@ -1018,6 +1124,19 @@ exprInfo &pickTheBest(const string &uniqueLabel, vector testSet, vector< { isSingleParam = false; } + int dimension = scales.size(); + 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 (size_t i = 0; i < testSet.size(); i++) { auto &exprInfoTmp = initExprInfos.at(i); @@ -1025,7 +1144,7 @@ exprInfo &pickTheBest(const string &uniqueLabel, vector testSet, vector< cout << "*-*-*-pickTheBest: for item No." << i << ": type = " << suffixTmp << endl; // generate function code and test error - exprInfoTmp = testError(uniqueLabel, suffixTmp, intervals, scales, isSingleParam); + exprInfoTmp = testError(uniqueLabel, suffixTmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, isSingleParam); // cout << "pickTheBest: for item No." << i << ": maxError: " << exprInfoTmp.maxError << "\n"; // cout << "pickTheBest: for item No." << i << ": aveError: " << exprInfoTmp.aveError << "\n"; if ((exprInfoTmp.maxError < maxError) || ((exprInfoTmp.maxError == maxError) && (exprInfoTmp.aveError < aveError))) @@ -1051,13 +1170,26 @@ exprInfo pickTheBest(string uniqueLabel, vector testSet, vector { isSingleParam = false; } + int dimension = scales.size(); + 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 (size_t i = 0; i < testSet.size(); i++) { string suffixTmp = testSet.at(i); cout << "*-*-*-pickTheBest: for item No." << i << ": type = " << suffixTmp << endl; // generate function code and test error - auto tempError = testError(uniqueLabel, suffixTmp, intervals, scales, isSingleParam); + auto tempError = testError(uniqueLabel, suffixTmp, intervals, scales, startNowIdxs, startOriginIntervals, steps, isSingleParam); // cout << "pickTheBest: for item No." << i << ": maxError: " << tempError.maxError << "\n"; // cout << "pickTheBest: for item No." << i << ": aveError: " << tempError.aveError << "\n"; @@ -1106,6 +1238,19 @@ size_t pickTheBest(vector &items, ast_ptr &originExpr) double aveError = 0; size_t maxIdx = -1; size_t iEnd = min(items.size(), size_t(100000)); + + vector startNowIdxs(dimension, 0); + vector startOriginIntervals; + vector steps; + for (size_t i = 0; i < dimension; i++) + { + auto &startOriginInterval = intervalTmp.at(i * 2); + auto &endOriginInterval = intervalTmp.at(i * 2 + 1); + startOriginIntervals.push_back(startOriginInterval); + double width = endOriginInterval - startOriginInterval; + double step = width / (double)scales.at(i); + steps.push_back(step); + } for (size_t i = 0; i < iEnd; i++) { string item = PrintExpression(items.at(i)); @@ -1115,7 +1260,7 @@ size_t pickTheBest(vector &items, ast_ptr &originExpr) string suffixTmp = suffix + std::to_string(i); geneExprCodeKernel(item, vars, uniqueLabel, suffixTmp); // auto timeTmp1 = std::chrono::high_resolution_clock::now(); - auto tempError = testError(uniqueLabel, suffixTmp, intervalTmp, scales); + auto tempError = testError(uniqueLabel, suffixTmp, intervalTmp, scales, startNowIdxs, startOriginIntervals, steps); // auto timeTmp2 = std::chrono::high_resolution_clock::now(); // std::chrono::duration testError_seconds = timeTmp2 - timeTmp1; // cout << BLUE << "rewrite: For NO." << i << ": testError time: " << testError_seconds.count() << " s" << RESET << endl; @@ -1285,6 +1430,74 @@ vector tryRewriteRandom(ast_ptr expr) return results; } +ast_ptr moveDivForWard(const ast_ptr &expr, const ast_ptr &denominator) +{ + auto type = expr->type(); + if(type == "Binary") + { + BinaryExprAST* exprPtr = dynamic_cast(expr.get()); + auto opType = exprPtr->getOp(); + if(opType == '*') + { + auto &lhs = exprPtr->getLHS(); + auto &rhs = exprPtr->getRHS(); + auto newL = divExpr(lhs, denominator); + auto newExpr = mulExpr(newL, rhs); + return newExpr; + } + } + return nullptr; +} + +vector changeMulToDiv(const ast_ptr &numerator, const ast_ptr &denominator) +{ + vector results; + BinaryExprAST* denominatorPtr = dynamic_cast(denominator.get()); + auto opType = denominatorPtr->getOp(); + if(opType == '*') + { + auto &lhs = denominatorPtr->getLHS(); + auto &rhs = denominatorPtr->getRHS(); + auto lType = lhs->type(); + auto rType = rhs->type(); + if(lType == "Variable") + { + auto newNumerator = divExpr(numerator, lhs); + auto newExpr = divExpr(newNumerator, rhs); + if(newExpr != nullptr) + results.push_back(std::move(newExpr)); + + auto tmp = moveDivForWard(numerator, lhs); + if(tmp != nullptr) + { + auto newExpr1 = divExpr(tmp, rhs); + if(newExpr1 != nullptr) + results.push_back(std::move(newExpr1)); + } + } + if(!isEqual(lhs, rhs)) + { + if(rType == "Variable") + { + auto newNumerator = divExpr(numerator, rhs); + auto newExpr = divExpr(newNumerator, lhs); + if(newExpr != nullptr) + results.push_back(std::move(newExpr)); + + auto tmp = moveDivForWard(numerator, rhs); + if(tmp != nullptr) + { + auto newExpr1 = divExpr(tmp, lhs); + if(newExpr1 != nullptr) + results.push_back(std::move(newExpr1)); + } + } + } + } + if(results.size() != 0) deleteTheSame(results); + return results; +} + vector createAll(vector &numerators, vector &denominators) { ast_ptr resultsTemp; @@ -1308,6 +1521,13 @@ vector createAll(vector &numerators, vector &denomina { resultsTemp = divExpr(numerator, denominator); results.push_back(std::move(resultsTemp)); + auto type = denominator->type(); + if(type == "Binary") + { + auto tmps = changeMulToDiv(numerator, denominator); + if(tmps.size() != 0) + mineAppend(results, tmps); + } } } } @@ -1386,6 +1606,7 @@ vector exprAutoNew(const ast_ptr &expr, bool addSelf) else { results = createAll(numerators, denominators); + } } else @@ -1403,91 +1624,189 @@ vector exprAutoNew(const ast_ptr &expr, bool addSelf) return results; } +// TODO: the variable name vector exprAutoWrapper(ast_ptr &expr, const std::vector &intervals, const std::vector &scales) { cout << "\n>exprAutoWrapper: start-----------" << endl; - expr = minusRewrite(expr); + sortExpr(expr); + auto exprOrigin = expr->Clone(); + printExpr(exprOrigin, "exprAutoWrapper: after parse, exprOrigin = ", DOUBLE_PRECISION); combineConstant(expr); - printExpr(expr, "exprAutoWrapper: after parse, expr = ", DOUBLE_PRECISION); - auto expr0 = combineConstant1(expr); - sortExpr(expr0); - printExpr(expr0, "exprAutoWrapper: after some prepare, expr = ", DOUBLE_PRECISION); + expr = combineConstant1(expr); + sortExpr(expr); + printExpr(expr, "exprAutoWrapper: after some prepare, expr = ", DOUBLE_PRECISION); ast_ptr expr1 = simplifyExpr(expr); // Python SymPy simplify + expr1 = minusRewrite(expr1); combineConstant(expr1); sortExpr(expr1); - printExpr(expr1, "\nexprAutoWrapper: after SymPy's simplify, expr = ", DOUBLE_PRECISION); + printExpr(expr1, "\nexprAutoWrapper: after SymPy's simplify, expr1 = ", DOUBLE_PRECISION); cout << endl; - vector results; - if(isEqual(expr, expr1)) + + // pick one from origin, origin1, sympy + string uniqueLabel = "pickBetter"; + string mkdirCommand = "mkdir -p srcTest/" + uniqueLabel + " outputs/" + uniqueLabel; + system(mkdirCommand.c_str()); + vector vars; + getVariablesFromExpr(expr, vars); + + auto exprOriginStr = PrintExpression(exprOrigin); + geneExprCodeKernel(exprOriginStr, vars, uniqueLabel, "origin"); + auto exprStr = PrintExpression(expr); + geneExprCodeKernel(exprStr, vars, uniqueLabel, "origin1"); + auto expr1Str = PrintExpression(expr1); + geneExprCodeKernel(expr1Str, vars, uniqueLabel, "sympy"); + geneMpfrCode(exprStr, uniqueLabel, vars); + std::map rewriteOrigins = { + {"origin", 0}, + {"origin1", 1}, + {"sympy", 2}, + }; + + int dimension = scales.size(); + vector startNowIdxs(dimension, 0); + vector startOriginIntervals; + vector steps; + for (int i = 0; i < dimension; i++) { - cout << YELLOW << "-------------------------------------origin rewrite-------------------------------------" << RESET << endl; - results = exprAutoNew(expr); - } - else + 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); + } + double maxError = std::numeric_limits::max(); + double aveError = std::numeric_limits::max(); + string bestOne; + bool allIsEqual = false; + bool keepEqual = true; + double lastMaxError, lastAveError; + int idxPickTheBestOrigin = 0; + for(auto& rewriteOrigin : rewriteOrigins) { - bool pickOne = true; - if(pickOne) + auto &currrentOne = rewriteOrigin.first; + auto info = testError(uniqueLabel, currrentOne, intervals, scales, startNowIdxs, startOriginIntervals, steps); + auto &currrentMaxError = info.maxError; + auto &currrentAveError = info.aveError; + if(idxPickTheBestOrigin != 0) { - // pick the better one from expr and expr1 - string uniqueLabel = "pickBetter"; - string mkdirCommand = "mkdir -p srcTest/" + uniqueLabel + " outputs/" + uniqueLabel; - system(mkdirCommand.c_str()); - vector vars; - getVariablesFromExpr(expr, vars); - - auto exprStr = PrintExpression(expr); - auto funcNameOrigin = geneExprCodeKernel(exprStr, vars, uniqueLabel, "origin"); - auto expr1Str = PrintExpression(expr1); - auto funcNameSympy = geneExprCodeKernel(expr1Str, vars, uniqueLabel, "sympy"); - auto funcNameMpfr = geneMpfrCode(exprStr, uniqueLabel, vars); - - // int scale = 256; - // turbine1 - // auto info = testError(uniqueLabel, "origin", 3.8, 7.8, -4.5, -0.3, 0.4, 0.9, scale, scale, scale); - // auto info1 = testError(uniqueLabel, "sympy", 3.8, 7.8, -4.5, -0.3, 0.4, 0.9, scale, scale, scale); - // doppler1 - // auto info = testError(uniqueLabel, "origin", -30, 50, -100, 100, 20, 20000, scale, scale, scale); - // auto info1 = testError(uniqueLabel, "sympy", -30, 50, -100, 100, 20, 20000, scale, scale, scale); - // int scale = 500000; - // sine - // auto info = testError(uniqueLabel, "origin", -1.57079632679, 1.57079632679, scale); - // auto info1 = testError(uniqueLabel, "sympy", -1.57079632679, 1.57079632679, scale); - // sqroot - // auto info = testError(uniqueLabel, "origin", 0, 1, scale); - // auto info1 = testError(uniqueLabel, "sympy", 0, 1, scale); - - auto info = testError(uniqueLabel, "origin", intervals, scales); - auto info1 = testError(uniqueLabel, "sympy", intervals, scales); - auto maxError = info.maxError; - auto maxError1 = info1.maxError; - - if(maxError < maxError1) - { - cout << YELLOW << "-------------------------------------origin rewrite is better-------------------------------------" << RESET << endl; - results = exprAutoNew(expr); + if(keepEqual == true) + { + if((currrentMaxError == lastMaxError) && (currrentAveError == lastAveError)) + { + allIsEqual = true; + } + else + { + keepEqual = false; + allIsEqual = false; + } + } } - else + if(currrentMaxError < maxError) { - cout << YELLOW << "-------------------------------------sympy rewrite is better-------------------------------------" << RESET << endl; - results = exprAutoNew(expr1); - } + maxError = currrentMaxError; + aveError = currrentAveError; + bestOne = currrentOne; } - else + else if(currrentMaxError == maxError) { - cout << YELLOW << "-------------------------------------origin rewrite-------------------------------------" << RESET << endl; - results = exprAutoNew(expr); - cout << YELLOW << "-------------------------------------sympy rewrite-------------------------------------" << RESET << endl; - vector results1 = exprAutoNew(expr1); - mineAppend(results, results1); + if(currrentAveError < aveError) + { + maxError = currrentMaxError; + aveError = currrentAveError; + bestOne = currrentOne; + } } + lastMaxError = currrentMaxError; + lastAveError = currrentAveError; + idxPickTheBestOrigin++; + } + cout << "exprAutoWrapper: the rewrite object is " << (rewriteOrigins.find(bestOne))->first << endl; + auto idx = (rewriteOrigins.find(bestOne))->second; + vector origins; + if(allIsEqual == false) + { + origins.push_back(std::move(exprOrigin)); + origins.push_back(expr->Clone()); + origins.push_back(expr1->Clone()); } + else + { + origins.push_back(std::move(exprOrigin)); + } + auto &rewriteOrigin = origins.at(idx); + auto results = exprAutoNew(rewriteOrigin); + + // if(isEqual(expr, expr1)) + // { + // cout << YELLOW << "-------------------------------------origin rewrite-------------------------------------" << RESET << endl; + // results = exprAutoNew(expr); + // } + // else + // { + // bool pickOne = true; + // if(pickOne) + // { + // // pick the better one from expr and expr1 + // string uniqueLabel = "pickBetter"; + // string mkdirCommand = "mkdir -p srcTest/" + uniqueLabel + " outputs/" + uniqueLabel; + // system(mkdirCommand.c_str()); + // vector vars; + // getVariablesFromExpr(expr, vars); + + // auto exprStr = PrintExpression(expr); + // auto funcNameOrigin = geneExprCodeKernel(exprStr, vars, uniqueLabel, "origin"); + // auto expr1Str = PrintExpression(expr1); + // auto funcNameSympy = geneExprCodeKernel(expr1Str, vars, uniqueLabel, "sympy"); + // auto funcNameMpfr = geneMpfrCode(exprStr, uniqueLabel, vars); + + // int dimension = scales.size(); + // 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 info = testError(uniqueLabel, "origin", intervals, scales, startNowIdxs, startOriginIntervals, steps); + // auto info1 = testError(uniqueLabel, "sympy", intervals, scales, startNowIdxs, startOriginIntervals, steps); + // auto maxError = info.maxError; + // auto maxError1 = info1.maxError; + + // if(maxError < maxError1) + // { + // cout << YELLOW << "-------------------------------------origin rewrite is better-------------------------------------" << RESET << endl; + // results = exprAutoNew(expr); + // } + // else + // { + // cout << YELLOW << "-------------------------------------sympy rewrite is better-------------------------------------" << RESET << endl; + // results = exprAutoNew(expr1); + // } + // } + // else + // { + // cout << YELLOW << "-------------------------------------origin rewrite-------------------------------------" << RESET << endl; + // results = exprAutoNew(expr); + // cout << YELLOW << "-------------------------------------sympy rewrite-------------------------------------" << RESET << endl; + // vector results1 = exprAutoNew(expr1); + // mineAppend(results, results1); + // } + // } for(auto& result : results) { sortExpr(result); } - results.push_back(expr->Clone()); - deleteTheSame(results); + mineAppend(results, origins); + if(results.size() != 0) deleteTheSame(results); cout << YELLOW << "-------------------------------------final results-------------------------------------" << RESET << endl; printExprs(results, BLUE "exprAutoWrapper: after exprAutoNew: " RESET, false, DOUBLE_PRECISION); diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 71c9b485faca23e04ce8b9362d8852ffdb3afa5c..a34527951c09c71265c0d243282c8c93f7cefa3e 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -269,25 +269,37 @@ string geneHerbieCode(string uniqueLabel) {"test05_nonlin1_r4", "exp(-log1p(x))"}, // warning, the origin is (x - 1)/(x*x - 1) {"test05_nonlin1_test2", "exp(-log1p(x))"}, // warning, the origin is 1.0/(1+x) {"verhulst", "pow(log1p(expm1((64.0 * pow((x / fma(x, 0.9009009009009009, 1.0)), 3.0)))), 0.3333333333333333)"}, // warning, the origin is (4*x)/(1+x/1.11) - {"ComplexSinCos", "sin(x1) * ((pow(x2, 3.0) * -0.16666666666666666) - x2)"}, + {"ComplexSinCos", "sin(r) * ((pow(i, 3.0) * -0.16666666666666666) - i)"}, {"ComplexSquareRoot", "0.5 * sqrt((2.0 * (x1 + hypot(x1, x2))))"}, - {"doppler1", "(fma(x2, -0.6, -331.4) / pow((331.4 + fma(0.6, x2, x0)), 2.0)) * x1"}, // warning, the origin is ((-(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", ""}, // warning, the origin is ((-(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", ""}, // warning, the origin is ((-(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", "(fma(T, -0.6, -331.4) / pow((331.4 + fma(0.6, T, u)), 2.0)) * v"}, // warning, the origin is ((-(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", "v * (fma(T, -0.6, -331.4) / fma(u, (u + fma(1.2, T, 662.8)), pow(fma(T, 0.6, 331.4), 2.0)));"}, // warning, the origin is ((-(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", "(fma(T, -0.6, -331.4) / pow((331.4 + fma(0.6, T, u)), 2.0)) * v"}, // warning, the origin is ((-(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)) {"hypot32", "hypotf(x1, x2)"}, // single precision {"i4", "sqrtf(fmaf(f2, f2, f1))"}, // single precision {"i6", "sinf((f1 * f2))"}, // single precision - {"NMSEexample33", "fma(x1, fma((x1 * -0.5), sin(x2), (cos(x2) + -1.0)), sin(x2))"}, - {"NMSEproblem332", "fma(sin(x2) / cos(x2), (x1 * (x1 + (pow(sin(x2), 2.0) / (pow(cos(x2), 2.0) / x1)))), fma((pow(sin(x2), 2.0) / pow(cos(x2), 2.0)), x1, sin(x2) / cos(x2)))"}, // double t_0 = sin(x2) / cos(x2); double t_1 = pow(sin(x2), 2.0); double t_2 = pow(cos(x2), 2.0); *resultPtr = fma(t_0, (x1 * (x1 + (t_1 / (t_2 / x1)))), fma((t_1 / t_2), x1, t_0)); - {"NMSEproblem335", "-2.0 * (sin(((x2 + (x1 - x1)) * 0.5)) * sin((0.5 * fma(x1, 2.0, x2))))"}, - {"NMSEproblem346", ""}, // expm1(log1p((exp((log1p(x1) / x2)) - pow(x1, (1.0 / x2))))) + {"NMSEexample33", "fma(x, fma((x * -0.5), sin(eps), (cos(eps) + -1.0)), sin(eps))"}, + {"NMSEproblem332", "fma(sin(eps) / cos(eps), (x * (x + (pow(sin(eps), 2.0) / (pow(cos(eps), 2.0) / x)))), fma((pow(sin(eps), 2.0) / pow(cos(eps), 2.0)), x, sin(eps) / cos(eps)))"}, // double t_0 = sin(x2) / cos(x2); double t_1 = pow(sin(x2), 2.0); double t_2 = pow(cos(x2), 2.0); *resultPtr = fma(t_0, (x1 * (x1 + (t_1 / (t_2 / x1)))), fma((t_1 / t_2), x1, t_0)); + {"NMSEproblem335", "-2.0 * (sin(((eps + (x - x)) * 0.5)) * sin((0.5 * fma(x, 2.0, eps))))"}, + {"NMSEproblem346", "expm1(log1p((exp((log1p(x) / n)) - pow(x, (1.0 / n)))))"}, {"NMSEsection35", "expm1((a * x))"}, {"polarToCarthesianX", "x1 * cos(log((pow(sqrt(exp(0.017453292519944444)), x2) * fma(0.5, (pow(log(sqrt(exp(0.017453292519944444))), 2.0) * (x2 * x2)), fma(log(sqrt(exp(0.017453292519944444))), x2, fma(pow(x2, 3.0), (0.16666666666666666 * pow(log(sqrt(exp(0.017453292519944444))), 3.0)), 1.0))))))"}, // double t_1 = sqrt(exp(0.017453292519944444)); double t_2 = log(t_1); *resultPtr = x1 * cos(log((pow(t_1, x2) * fma(0.5, (pow(t_2, 2.0) * (x2 * x2)), fma(t_2, x2, fma(pow(x2, 3.0), (0.16666666666666666 * pow(t_2, 3.0)), 1.0)))))); {"polarToCarthesianY", "exp((((log(0.017453292519944444) * log(0.017453292519944444)) + (0.0 - pow(pow(log((x1 * x2)), 6.0), 0.3333333333333333))) / (log(0.017453292519944444) - log((x1 * x2)))))"}, // double t_1 = log((x1 * x2)); *resultPtr = exp((((log(0.017453292519944444) * log(0.017453292519944444)) + (0.0 - pow(pow(t_1, 6.0), 0.3333333333333333))) / (log(0.017453292519944444) - t_1))); {"sec4example", "pow(fma(x1, x2, 1.0), -1.0)"}, // warning, the origin is ((x1*x2) - 1)/((x1*x2)*(x1*x2) - 1) - {"test03_nonlin2", ""}, // for test03_nonlin2, herbie is the same to origin + {"test03_nonlin2", "(x + y)/(x - y)"}, // for test03_nonlin2, herbie is the same to origin {"theta", "(pow(pow(cbrt(cbrt(cbrt(cbrt((atan((x2 / x1)) * 57.29577951307855))))), 2.0), 18.0) * pow(cbrt(cbrt(cbrt(cbrt((atan((x2 / x1)) * 57.29577951307855))))), 18.0)) * pow(cbrt(cbrt(cbrt((atan((x2 / x1)) * 57.29577951307855)))), 9.0)"}, // double t_0 = cbrt(cbrt(cbrt((atan((x2 / x1)) * 57.29577951307855)))); double t_1 = cbrt(t_0); *resultPtr = (pow(pow(t_1, 2.0), 18.0) * pow(t_1, 18.0)) * pow(t_0, 9.0) {"turbine1", "cbrt(pow((2.0 * pow(x2, -2.0)), 3.0)) - fma(fma(x0, -0.25, 0.375), ((x2 / (1.0 - x0)) * (x2 * pow(x1, 2.0))), 1.5)"}, // warning, the origin is (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 + {"squareRoot3_1", ""}, + {"squareRoot3_2", ""}, + {"squareRoot3Invalid_1", ""}, + {"squareRoot3Invalid_2", ""}, + {"cav10_1", ""}, + {"cav10_2", ""}, + {"gustafsonExample_1", ""}, + {"gustafsonExample_2", ""}, + {"smartRoot_1", ""}, + {"smartRoot_2", ""}, + {"triangleSorted_1", ""}, + {"triangleSorted_2", ""}, }; auto pos = benchmarkHerbie.find(uniqueLabel); @@ -309,9 +321,90 @@ string geneHerbieCode(string uniqueLabel) exit(EXIT_FAILURE); } -void geneDaisyCode(string exprStr) +string geneDaisyCode(string uniqueLabel) { - cout << exprStr << endl; + map benchmarkDaisy = { + {"Bsplines3", ""}, + {"exp1x", ""}, + {"exp1x_log", ""}, + {"intro_example", ""}, + {"logexp", ""}, + {"NMSEexample31", ""}, + {"NMSEexample310", ""}, + {"NMSEexample34", ""}, + {"NMSEexample35", ""}, + {"NMSEexample36", ""}, + {"NMSEexample37", ""}, + {"NMSEexample38", "(((log((1.0 + x)) * x) + (log((x + 1.0)) - 1.0)) - (x * log(x)))"}, + {"NMSEexample39", ""}, + {"NMSEproblem331", ""}, + {"NMSEproblem333", ""}, + {"NMSEproblem334", ""}, + {"NMSEproblem336", ""}, + {"NMSEproblem337", ""}, + {"NMSEproblem341", ""}, + {"NMSEproblem343", ""}, + {"NMSEproblem344", ""}, + {"NMSEproblem345", ""}, + {"NMSEsection311", ""}, + {"predatorPrey", ""}, + {"sine", ""}, + {"sineorder3", ""}, + {"sqroot", ""}, + {"sqrt_add", ""}, + {"test05_nonlin1_r4", ""}, + {"test05_nonlin1_test2", ""}, + {"verhulst", ""}, + {"ComplexSinCos", ""}, + {"ComplexSquareRoot", ""}, + {"doppler1", ""}, + {"doppler2", ""}, + {"doppler3", ""}, + {"hypot32", ""}, + {"i4", ""}, + {"i6", ""}, + {"NMSEexample33", ""}, + {"NMSEproblem332", ""}, + {"NMSEproblem335", ""}, + {"NMSEproblem346", ""}, + {"NMSEsection35", ""}, + {"polarToCarthesianX", "radius * cos(theta * 0.017453292519944444)"}, + {"polarToCarthesianY", "radius * sin(theta * 0.017453292519944444)"}, + {"sec4example", ""}, + {"test03_nonlin2", ""}, + {"theta", "atan((x2 / x1)) * 57.29577951307855"}, + {"turbine1", ""}, + {"squareRoot3_1", ""}, + {"squareRoot3_2", ""}, + {"squareRoot3Invalid_1", ""}, + {"squareRoot3Invalid_2", ""}, + {"cav10_1", ""}, + {"cav10_2", ""}, + {"gustafsonExample_1", ""}, + {"gustafsonExample_2", ""}, + {"smartRoot_1", ""}, + {"smartRoot_2", ""}, + {"triangleSorted_1", ""}, + {"triangleSorted_2", ""}, + }; + + auto pos = benchmarkDaisy.find(uniqueLabel); + if (pos != benchmarkDaisy.end()) + { + string daisyExpr = pos->second; + if(daisyExpr != "") + { + geneExprCode(daisyExpr, uniqueLabel, "daisy"); + } + else + { + fprintf(stderr, "ERROR: geneDaisyCode: daisy's rewrite result for %s can not be used.\n", uniqueLabel.c_str()); + // TODO: just write the if-else result to file. + } + return daisyExpr; + } + fprintf(stderr, "ERROR: geneDaisyCode: we can not support %s now\n", uniqueLabel.c_str()); + exit(EXIT_FAILURE); } string geneMpfrCode(const ast_ptr &exprAst, const string uniqueLabel, vector vars) @@ -328,12 +421,15 @@ string geneMpfrCode(const ast_ptr &exprAst, const string uniqueLabel, vector vars; // getVariablesFromExpr(exprAst, vars); diff --git a/src/main.cpp b/src/main.cpp index 691f89a97f2935db671e6d1e6dba67afe21ea2d4..5a8416310a7ccb42bc3a95d7956e69afaedb72cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -75,8 +75,69 @@ map> benchmarkThresholds = { {"test03_nonlin2", {1.375, 1.25}}, {"theta", {2, 2}}, {"turbine1", {3.002278, 2.831004, 2.847586}}, + {"squareRoot3_1", {2}}, + {"squareRoot3_2", {2}}, + {"squareRoot3Invalid_1", {2}}, + {"squareRoot3Invalid_2", {2}}, + {"cav10_1", {2}}, + {"cav10_2", {2}}, + {"gustafsonExample_1", {2}}, + {"gustafsonExample_2", {2}}, + {"smartRoot_1", {2}}, + {"smartRoot_2", {2}}, + {"triangleSorted_1", {2, 2, 2}}, + {"triangleSorted_2", {2, 2, 2}}, }; +// write to file +void write_to_file_wrapper(string uniqueLabel, string exprOriginBest, int dimension, int numIntervalsBefore, double numOfIntervals, 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) +{ + vector summaryData; + summaryData.push_back(dimension); + summaryData.push_back(numIntervalsBefore); + summaryData.push_back(numOfIntervals); + summaryData.push_back(double(numOfExprs)); + if (thresholds.size() == 1) + { + summaryData.push_back(thresholds.at(0)); + summaryData.push_back(-1); + summaryData.push_back(-1); + } + else if (thresholds.size() == 2) + { + summaryData.push_back(thresholds.at(0)); + summaryData.push_back(thresholds.at(1)); + summaryData.push_back(-1); + } + else if (thresholds.size() == 3) + { + summaryData.push_back(thresholds.at(0)); + summaryData.push_back(thresholds.at(1)); + summaryData.push_back(thresholds.at(2)); + } + else + { + fprintf(stderr, "ERROR: we can not support %ld demision now.\n", thresholds.size()); + exit(EXIT_FAILURE); + } + summaryData.push_back(originExprInfo.aveError); + summaryData.push_back(originExprInfo.maxError); + summaryData.push_back(herbieExprInfo.aveError); + summaryData.push_back(herbieExprInfo.maxError); + summaryData.push_back(finalInfo.aveError); + summaryData.push_back(finalInfo.maxError); + summaryData.push_back(originPerformance); + summaryData.push_back(finalInfo.performance); + summaryData.push_back(elapsed_seconds); + summaryData.push_back(init_seconds); + summaryData.push_back(matlab_seconds); + summaryData.push_back(regime_seconds); + summaryData.push_back(rewrite_seconds); + summaryData.push_back(final_seconds); + summaryData.push_back(matlabKernelTime); + write_to_file(uniqueLabel, exprOriginBest, summaryData, "runlog.csv"); +} + //===----------------------------------------------------------------------===// // Main driver code. //===----------------------------------------------------------------------===// @@ -105,8 +166,8 @@ int main() fprintf(stderr, GREEN "ready> " RESET); string inputStr = ""; - while (getline(infile, inputStr)) // read line from file's input - // while (getline(cin, inputStr)) // read line from keyboard input + // while (getline(infile, inputStr)) // read line from file's input + while (getline(cin, inputStr)) // read line from keyboard input { // only rewrite // getlineCount++; @@ -202,11 +263,12 @@ int main() // ready for writing to file string exprOriginBest = ""; double originPerformance = -1; + double herbiePerformance = -1; int numIntervalsBefore = -1; double numOfIntervals = -1; int numOfExprs = -1; exprInfo finalInfo; // ave err, max err, performance - std::chrono::duration init_seconds, matlab_seconds, regime_seconds, rewrite_seconds, final_seconds,elapsed_seconds; + std::chrono::duration init_seconds{0}, matlab_seconds{0}, regime_seconds{0}, rewrite_seconds{0}, final_seconds{0}, elapsed_seconds{0}; double matlabKernelTime = -1; vector initExprInfos; exprInfo tempExprInfo; @@ -214,10 +276,11 @@ int main() initExprInfos.push_back(tempExprInfo); tempExprInfo.suffix = "herbie"; initExprInfos.push_back(tempExprInfo); + tempExprInfo.suffix = "daisy"; + initExprInfos.push_back(tempExprInfo); auto &originExprInfo = initExprInfos.at(0); auto &herbieExprInfo = initExprInfos.at(1); - herbieExprInfo.aveError = -1; - herbieExprInfo.maxError = -1; + auto &daisyExprInfo = initExprInfos.at(2); if (runAllFlag) { // the whole process if (!isBenchMark) @@ -233,13 +296,29 @@ int main() // auto funcNameOrigin = geneExprCode(inputStr, uniqueLabel, "origin"); // auto funcNameHerbie = geneHerbieCode(inputStr, uniqueLabel, "herbie"); auto exprHerbie = geneHerbieCode(uniqueLabel); - // auto exprDaisy = geneDaisyCode(inputStr, uniqueLabel, "daisy"); + auto exprDaisy = geneDaisyCode(uniqueLabel); auto funcNameMpfr = geneMpfrCode(inputStr, uniqueLabel, vars); - originPerformance = testPerformance(uniqueLabel, "origin", intervals); - cout << "origin performance: " << originPerformance << "\n\n"; + if(exprOrigin != "") + { + originPerformance = testPerformance(uniqueLabel, "origin", intervals); + cout << "origin performance: " << originPerformance << "\n\n"; + } + else + { + fprintf(stderr, "exprOrigin is null!\n"); + exit(EXIT_FAILURE); + } + if(exprHerbie != "") + { + herbiePerformance = testPerformance(uniqueLabel, "herbie", intervals); + cout << "origin performance: " << originPerformance << "\n\n"; + } + else + { + fprintf(stderr, "exprHerbie is null!\n"); + } - // TODO: improve pickTheBest to support more suffix vector suffixSet = {"origin"}; if (exprHerbie != "") { @@ -247,7 +326,15 @@ int main() } else { - fprintf(stderr, "For exprOrigin, Herbie's rewrite results can not be used.\nSo, we just pick origin as the best.\n"); + fprintf(stderr, "For exprOrigin, Herbie's rewrite results can not be used.\n"); + } + if (exprDaisy != "") + { + suffixSet.push_back("daisy"); + } + else + { + fprintf(stderr, "For exprOrigin, Daisy's rewrite results can not be used.\n"); } auto &initExprInfo = pickTheBest(uniqueLabel, suffixSet, initExprInfos, intervals, scales); @@ -261,6 +348,10 @@ int main() { inputStr = exprHerbie; } + else if (exprOriginBest == "daisy") + { + inputStr = exprDaisy; + } else { fprintf(stderr, "ERROR: main: we do not support the suffix %s now\n", exprOriginBest.c_str()); @@ -274,6 +365,12 @@ int main() if (initExprMaxError <= 0.5) { fprintf(stderr, "the error of %s is no bigger than 0.5, so do not need precision improvement.\n", inputStr.c_str()); + // TODO: write + auto timeEnd = std::chrono::high_resolution_clock::now(); + elapsed_seconds = timeEnd - timeStart; + cout << BLUE << "the whole time: " << elapsed_seconds.count() << " s" << RESET << endl; + + write_to_file_wrapper(uniqueLabel, exprOriginBest, dimension, numIntervalsBefore, numOfIntervals, numOfExprs, thresholds, originExprInfo, herbieExprInfo, finalInfo, originPerformance, elapsed_seconds.count(), init_seconds.count(), matlab_seconds.count(), regime_seconds.count(), rewrite_seconds.count(), final_seconds.count(), matlabKernelTime); fprintf(stderr, GREEN "ready> " RESET); continue; } @@ -347,7 +444,19 @@ int main() auto funcNameFinal = geneFinalCodeKernel(inputStr, uniqueLabel, exprInfoVector, vars); cout << "=-=-=-=-=-=-=-=-=-=-=-=-= test final code's error and performance start =-=-=-=-=-=-=-=-=-=-=-=-=\n"; - finalInfo = testError(uniqueLabel, "final", intervals, scales); + 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); + } + finalInfo = testError(uniqueLabel, "final", intervals, scales, startNowIdxs, startOriginIntervals, steps); finalInfo.performance = testPerformance(uniqueLabel, "final", intervals); cout << "performance: " << finalInfo.performance << "\n\n"; cout << "=-=-=-=-=-=-=-=-=-=-=-=-= test final code's error and performance end =-=-=-=-=-=-=-=-=-=-=-=-=\n"; @@ -395,47 +504,7 @@ int main() elapsed_seconds = timeEnd - timeStart; cout << BLUE << "the whole time: " << elapsed_seconds.count() << " s" << RESET << endl; - vector summaryData; - summaryData.push_back(dimension); - summaryData.push_back(numIntervalsBefore); - summaryData.push_back(numOfIntervals); - summaryData.push_back(double(numOfExprs)); - if(thresholds.size() == 1) { - summaryData.push_back(thresholds.at(0)); - summaryData.push_back(-1); - summaryData.push_back(-1); - } - else if(thresholds.size() == 2) { - summaryData.push_back(thresholds.at(0)); - summaryData.push_back(thresholds.at(1)); - summaryData.push_back(-1); - } - else if(thresholds.size() == 3) { - summaryData.push_back(thresholds.at(0)); - summaryData.push_back(thresholds.at(1)); - summaryData.push_back(thresholds.at(2)); - } - else { - fprintf(stderr, "ERROR: we can not support %ld demision now.\n", thresholds.size()); - exit(EXIT_FAILURE); - } - summaryData.push_back(originExprInfo.aveError); - summaryData.push_back(herbieExprInfo.aveError); - summaryData.push_back(finalInfo.aveError); - summaryData.push_back(originExprInfo.maxError); - summaryData.push_back(herbieExprInfo.maxError); - summaryData.push_back(finalInfo.maxError); - summaryData.push_back(originPerformance); - summaryData.push_back(finalInfo.performance); - summaryData.push_back(elapsed_seconds.count()); - summaryData.push_back(init_seconds.count()); - summaryData.push_back(matlab_seconds.count()); - summaryData.push_back(regime_seconds.count()); - summaryData.push_back(rewrite_seconds.count()); - summaryData.push_back(final_seconds.count()); - summaryData.push_back(matlabKernelTime); - write_to_file(uniqueLabel, exprOriginBest, summaryData, "runlog.csv"); - + write_to_file_wrapper(uniqueLabel, exprOriginBest, dimension, numIntervalsBefore, numOfIntervals, numOfExprs, thresholds, originExprInfo, herbieExprInfo, finalInfo, originPerformance, elapsed_seconds.count(), init_seconds.count(), matlab_seconds.count(), regime_seconds.count(), rewrite_seconds.count(), final_seconds.count(), matlabKernelTime); fprintf(stderr, GREEN "ready> " RESET); } diff --git a/src/mathfuncRewrite.cpp b/src/mathfuncRewrite.cpp index fe4a6066f0d061063688108bb5cd0dae6c1a1bda..48aa1c84557f128fdcbc0876e80e80408b8e450d 100644 --- a/src/mathfuncRewrite.cpp +++ b/src/mathfuncRewrite.cpp @@ -38,26 +38,51 @@ ast_ptr expToexpm1(const ast_ptr &expr) ast_ptr &lhs = binOp->getLHS(); ast_ptr &rhs = binOp->getRHS(); - if((op == '+') && (lhs->type() == "Call") && (rhs->type() == "Number")) // LHS = "Call" && RHS ='Number' + if(op == '+') { - CallExprAST *callExpr = dynamic_cast(lhs.get()); - string callee = (callExpr->getCallee()); - vector &args = callExpr->getArgs(); - vector argsNew; + if((lhs->type() == "Call") && (rhs->type() == "Number")) // LHS = "Call" && RHS ='Number' + { + CallExprAST *callExpr = dynamic_cast(lhs.get()); + string callee = (callExpr->getCallee()); + vector &args = callExpr->getArgs(); + vector argsNew; - NumberExprAST *numberExpr01 = dynamic_cast(rhs.get()); - double number = (numberExpr01->getNumber()); - //得到这个表达式中的变量 - if((callee == "exp") && (number == -1)) + NumberExprAST *numberExpr01 = dynamic_cast(rhs.get()); + double number = (numberExpr01->getNumber()); + //得到这个表达式中的变量 + if((callee == "exp") && (number == -1)) + { + for(long unsigned int i = 0; i < args.size(); ++i) + { + auto arg = expandExpr(args.at(i)); + argsNew.push_back(std::move(arg)); + } + string calleeNew = "expm1"; + ast_ptr exprFinal = makePtr(calleeNew, std::move(argsNew)); + return exprFinal; + } + } + else if((lhs->type() == "Number") && (rhs->type() == "Call")) // LHS = "Number" && RHS ='Call' { - for(long unsigned int i = 0; i < args.size(); ++i) + CallExprAST *callExpr = dynamic_cast(rhs.get()); + string callee = (callExpr->getCallee()); + vector &args = callExpr->getArgs(); + vector argsNew; + + NumberExprAST *numberExpr01 = dynamic_cast(lhs.get()); + double number = (numberExpr01->getNumber()); + //得到这个表达式中的变量 + if((callee == "exp") && (number == -1)) { - auto arg = expandExpr(args.at(i)); - argsNew.push_back(std::move(arg)); + for(long unsigned int i = 0; i < args.size(); ++i) + { + auto arg = expandExpr(args.at(i)); + argsNew.push_back(std::move(arg)); + } + string calleeNew = "expm1"; + ast_ptr exprFinal = makePtr(calleeNew, std::move(argsNew)); + return exprFinal; } - string calleeNew = "expm1"; - ast_ptr exprFinal = makePtr(calleeNew, std::move(argsNew)); - return exprFinal; } } @@ -1378,4 +1403,277 @@ ast_ptr sumToProduct(const ast_ptr &expr) } return result; +} + +ast_ptr fmaToMulAndAdd(const ast_ptr &expr) +{ + if(expr == nullptr) + { + fprintf(stderr, "ERROR: fmaToMulAndAdd's input is empty!\n"); + exit(EXIT_FAILURE); + } + + if(expr->type() != "Call") + { + return expr->Clone(); + } + + CallExprAST *callExpr = dynamic_cast(expr.get()); + string callee = (callExpr->getCallee()); + vector &args = callExpr->getArgs(); + + // fma(a, b, c) := a * b + c + if(callee == "fma" && args.size() == 3) + { + ast_ptr ¶m1 = args.at(0); + ast_ptr ¶m2 = args.at(1); + ast_ptr ¶m3 = args.at(2); + if(param1 == nullptr || param2 == nullptr || param3 == nullptr) + { + fprintf(stderr, "ERROR: fmaToMulAndAdd's params is wrong!\n"); + exit(EXIT_FAILURE); + } + ast_ptr tmp1 = mulExpr(param1, param2); + ast_ptr tmp2 = addExpr(tmp1, param3); + return tmp2; + } + return expr->Clone(); +} + +vector powCombine(const ast_ptr& expr) +{ + vector results; + // results.push_back(expr->Clone()); + if(expr == nullptr) + { + fprintf(stderr, "ERROR: powCombine's input is empty!\n"); + exit(EXIT_FAILURE); + } + if(expr->type() == "Binary") + { + BinaryExprAST *binOp = dynamic_cast(expr.get()); + char op = binOp->getOp(); + string opStr(1, op); + + ast_ptr &lhs = binOp->getLHS(); + ast_ptr &rhs = binOp->getRHS(); + if((op == '*') && (lhs->type() == "Call") && (rhs->type() == "Call")) // LHS = "Call" && RHS ='Call' + { + CallExprAST *callExprLHS = dynamic_cast(lhs.get()); + string calleeLHS = (callExprLHS->getCallee()); + CallExprAST *callExprRHS = dynamic_cast(rhs.get()); + string calleeRHS = (callExprRHS->getCallee()); + + if(calleeLHS == "pow" && calleeLHS == "pow") + { + vector &argsLHS = callExprLHS->getArgs(); + vector &argsRHS = callExprRHS->getArgs(); + auto &base1 = argsLHS.at(0); + auto &base2 = argsRHS.at(0); + if(isEqual(base1, base2)) + { + auto &power1 = argsLHS.at(1); + auto &power2 = argsRHS.at(1); + auto typePower1 = power1->type(); + auto typePower2 = power2->type(); + if(typePower1 == "Number" && typePower2 == "Number") + { + NumberExprAST *numberExpr01 = dynamic_cast(power1.get()); + NumberExprAST *numberExpr02 = dynamic_cast(power2.get()); + double number1 = (numberExpr01->getNumber()); + double number2 = (numberExpr02->getNumber()); + double powerFinal = number1 + number2; + ast_ptr powerFinalExpr = makePtr(powerFinal); + vector argsNew; + argsNew.push_back(base1->Clone()); + argsNew.push_back(powerFinalExpr->Clone()); + ast_ptr result = makePtr("pow", std::move(argsNew)); + + // check if the power is equal to 0.5 + if(powerFinal == 0.5) + { + vector argsNew1; + argsNew1.push_back(base1->Clone()); + ast_ptr result1 = makePtr("sqrt", std::move(argsNew1)); + results.push_back(std::move(result1)); + } + + results.push_back(std::move(result)); + } + } + } + } + } + if(results.size() == 0) + { + results.push_back(expr->Clone()); + } + return results; +} + +vector sqrtCombine(const ast_ptr& expr) +{ + vector results; + // results.push_back(expr->Clone()); + if(expr == nullptr) + { + fprintf(stderr, "ERROR: sqrtCombine's input is empty!\n"); + exit(EXIT_FAILURE); + } + if(expr->type() == "Binary") + { + BinaryExprAST *binOp = dynamic_cast(expr.get()); + char op = binOp->getOp(); + string opStr(1, op); + + ast_ptr &lhs = binOp->getLHS(); + ast_ptr &rhs = binOp->getRHS(); + if((op == '*') && (lhs->type() == "Call") && (rhs->type() == "Call")) // LHS = "Call" && RHS ='Call' + { + CallExprAST *callExprLHS = dynamic_cast(lhs.get()); + string calleeLHS = (callExprLHS->getCallee()); + CallExprAST *callExprRHS = dynamic_cast(rhs.get()); + string calleeRHS = (callExprRHS->getCallee()); + + if(calleeLHS == "sqrt" && calleeLHS == "sqrt") + { + vector &argsLHS = callExprLHS->getArgs(); + vector &argsRHS = callExprRHS->getArgs(); + auto ¶mL = argsLHS.at(0); + auto ¶mR = argsRHS.at(0); + auto typeParamL = paramL->type(); + auto typeParamR = paramL->type(); + if((typeParamL == "Variable" && typeParamR == "Variable")) + { + VariableExprAST *varExpr01 = dynamic_cast(paramL.get()); + VariableExprAST *varExpr02 = dynamic_cast(paramR.get()); + string var1 = (varExpr01->getVariable()); + string var2 = (varExpr02->getVariable()); + if(var1 == var2) + { + ast_ptr varfinalExpr = makePtr(var1); + results.push_back(std::move(varfinalExpr)); + } + else + { + // TODO: sqrt(x)*sqrt(y) ==> sqrt(x*y) + } + } + } + } + } + if(results.size() == 0) + { + results.push_back(expr->Clone()); + } + return results; +} + +ast_ptr powToMul(const ast_ptr& expr) +{ + if(expr == nullptr) + { + fprintf(stderr, "ERROR: powToMul's input is empty!\n"); + exit(EXIT_FAILURE); + } + + if(expr->type() != "Call") + { + return expr->Clone(); + } + + CallExprAST *callExpr = dynamic_cast(expr.get()); + auto callee = (callExpr->getCallee()); + auto &args = callExpr->getArgs(); + + // fma(a, b, c) := a * b + c + if(callee == "pow") + { + ast_ptr &base = args.at(0); + ast_ptr &exponent = args.at(1); + if(base == nullptr || exponent == nullptr) + { + fprintf(stderr, "ERROR: powToMul's params is wrong!\n"); + exit(EXIT_FAILURE); + } + + auto typeBase = base->type(); + auto typeExponent = exponent->type(); + if(typeBase == "Variable" && typeExponent == "Number") + { + NumberExprAST *numberExpr = dynamic_cast(exponent.get()); + auto number = (numberExpr->getNumber()); + if((int)number == number) + { + auto tmp = base->Clone(); + for(int i = 1; i < (int)number; i++) + { + tmp = mulExpr(tmp, base); + } + return tmp; + } + } + } + return expr->Clone(); +} + +// exp(x)+exp(-x) ==> cosh(x) +ast_ptr expToCosh(const ast_ptr& expr) +{ + if(expr == nullptr) + { + fprintf(stderr, "ERROR: sqrtCombine's input is empty!\n"); + exit(EXIT_FAILURE); + } + if(expr->type() == "Binary") + { + BinaryExprAST *binOp = dynamic_cast(expr.get()); + char op = binOp->getOp(); + string opStr(1, op); + + ast_ptr &lhs = binOp->getLHS(); + ast_ptr &rhs = binOp->getRHS(); + if((op == '*') && (lhs->type() == "Call") && (rhs->type() == "Call")) // LHS = "Call" && RHS ='Call' + { + CallExprAST *callExprLHS = dynamic_cast(lhs.get()); + string calleeLHS = (callExprLHS->getCallee()); + CallExprAST *callExprRHS = dynamic_cast(rhs.get()); + string calleeRHS = (callExprRHS->getCallee()); + + if(calleeLHS == "exp" && calleeLHS == "exp") + { + vector &argsLHS = callExprLHS->getArgs(); + vector &argsRHS = callExprRHS->getArgs(); + auto ¶mL = argsLHS.at(0); + auto ¶mR = argsRHS.at(0); + auto typeParamL = paramL->type(); + auto typeParamR = paramL->type(); + if((typeParamL == "Variable" && typeParamR == "Binary")) + { + ast_ptr oneNegetive = makePtr(-1); + auto newL = mulExpr(oneNegetive, paramL); + if(isEqual(newL, paramR)) + { + vector params; + params.push_back(paramR->Clone()); + ast_ptr tmp = makePtr("cosh", std::move(params)); + return tmp; + } + } + if((typeParamL == "Binary" && typeParamR == "Variable")) + { + ast_ptr oneNegetive = makePtr(-1); + auto newR = mulExpr(oneNegetive, paramR); + if(isEqual(paramL, newR)) + { + vector params; + params.push_back(paramL->Clone()); + ast_ptr tmp = makePtr("cosh", std::move(params)); + return tmp; + } + } + } + } + } + return nullptr; } \ No newline at end of file diff --git a/src/preprocess.cpp b/src/preprocess.cpp index 3e7c13ed1cbe35ddc13ede33d13ed40e892fe846..63ddb4f453f691ec95ece315c25bad581b31ff41 100644 --- a/src/preprocess.cpp +++ b/src/preprocess.cpp @@ -226,16 +226,53 @@ ast_ptr moveDivKernel(const ast_ptr &expr) return expr->Clone(); } +bool checkConstantDenominator(const ast_ptr& expr, ast_ptr& result) +{ + if (expr == nullptr) + { + fprintf(stderr, "\tERROR: checkConstantDenominator: the input expr is nullptr!\n"); + return false; + } + if (expr->type() == "Binary") + { + BinaryExprAST *binOpPtr = dynamic_cast(expr.get()); + char op = binOpPtr->getOp(); + if (op == '/') + { + auto &rhs = binOpPtr->getRHS(); + if(rhs->type() == "Number") + { + NumberExprAST *numPtr = dynamic_cast(rhs.get()); + double num = 1 / numPtr->getNumber(); + ast_ptr newRhs = makePtr(num); + auto &lhs = binOpPtr->getLHS(); + result = mulExpr(lhs, newRhs); + return true; + } + } + } + return false; +} + +// Now, moveDiv will change the constant denominator to its reciprocal and then multiply its reciprocal. vector moveDiv(const vector &exprs) { // fprintf(stderr, "moveDiv: start--------\n"); vector items; - ast_ptr moveBefore, moveAfter; + ast_ptr moveBefore, moveAfter, checkAfter; for (long unsigned int i = 0; i < exprs.size(); i++) { moveBefore = exprs.at(i)->Clone(); moveAfter = moveDivKernel(moveBefore); - items.push_back(std::move(moveAfter)); + bool checkResult = checkConstantDenominator(moveAfter, checkAfter); + if(checkResult) + { + items.push_back(std::move(checkAfter)); + } + else + { + items.push_back(std::move(moveAfter)); + } } // print info for debug // fprintf(stderr, "\tmoveDiv: expr size = %ld\n", items.size()); @@ -409,6 +446,7 @@ ast_ptr preprocessInit(const ast_ptr &expr) // { // fprintf(stderr, "\tpreprocessInit: after extractItems: No.%lu: %s\n", i, PrintExpression(exprs1[i]).c_str()); // } + // TODO: consider if neccesary to do: for each item, run moveDiv (containing change constant denominator) for each item and then permute them. vector exprs2 = moveDiv(exprs1); // fprintf(stderr, "\tpreprocessInit: after moveDiv: exprs2 size = %ld\n", exprs2.size()); // for (size_t i = 0; i < exprs2.size(); i++) diff --git a/src/tools.cpp b/src/tools.cpp index d0764264d65b99f57c9091e5edf07c197c53dc82..412a65009c3b4ca491642810d5cebc39dbfd13a1 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -359,7 +359,7 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte return tempError; } -exprInfo testError(string uniqueLabel, string suffix, const vector &intervals, const vector &scales, bool errfile) +exprInfo testError(string uniqueLabel, string suffix, const vector &intervals, const vector &scales, const vector &startNowIdxs, const vector &startOriginIntervals, const vector &steps, bool errfile) { exprInfo tempError; size_t size = scales.size(); @@ -378,7 +378,7 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte auto scaleTmp = fmt::format("{}", scale); params.push_back(scaleTmp); } - string middle; + string middle; // do not need to add startNowIdx and startOriginInterval to middle for(size_t i = 0; i < params.size(); ++i) { if(i == 0) @@ -390,6 +390,21 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte middle = middle + "_" + params.at(i); } } + for(const auto &startNowIdx : startNowIdxs) + { + auto startNowIdxTmp = fmt::format("{}", startNowIdx); + params.push_back(startNowIdxTmp); + } + for(const auto &startOriginInterval : startOriginIntervals) + { + auto startOriginIntervalTmp = fmt::format("{}", startOriginInterval); + params.push_back(startOriginIntervalTmp); + } + for(const auto &step : steps) + { + auto stepTmp = fmt::format("{}", step); + params.push_back(stepTmp); + } string fileNameKernel = prefix + "__" + middle + "_" + suffix; namespace fs = std::filesystem; string currentPath = fs::current_path(); @@ -801,20 +816,30 @@ vector rewrite(string exprStr, string uniqueLabel, vector scales(dimension, scale); + vector startOriginIntervals; + vector steps; + vector startNowIdxs; for (int i = 0; i < dimension; i++) { - double width = intervals.at(i * 2 + 1) - intervals.at(i * 2); + auto &startOriginInterval = intervals.at(i * 2); + auto &endOriginInterval = intervals.at(i * 2 + 1); + auto &startNowInterval = intervalTmp.at(i * 2); + auto &endNowInterval = intervalTmp.at(i * 2 + 1); + startOriginIntervals.push_back(startOriginInterval); + double width = endOriginInterval - startOriginInterval; double step = width / (double)scales.at(i); - int stepNum = (intervalTmp.at(i * 2) - intervals.at(i * 2)) / step; - int stepNum1 = (intervalTmp.at(i * 2 + 1) - intervals.at(i * 2)) / step; - if(stepNum == stepNum1) + steps.push_back(step); + int startNowIdx = (startNowInterval - startOriginInterval) / step; + startNowIdxs.push_back(startNowIdx); + int endNowIdx = (endNowInterval - startOriginInterval) / step; + if(startNowIdx == endNowIdx) { - stepNum1 += 1; + endNowIdx += 1; } - scales.at(i) = stepNum1 - stepNum; + scales.at(i) = endNowIdx - startNowIdx; - intervalTmp.at(i * 2) = intervals.at(i * 2) + stepNum * step; - intervalTmp.at(i * 2 + 1) = intervals.at(i * 2) + stepNum1 * step; + startNowInterval = startOriginInterval + startNowIdx * step; + endNowInterval = startOriginInterval + endNowIdx * step; // scales.at(i) = scales.at(i) * (intervalTmp.at(i * 2 + 1) - intervalTmp.at(i * 2)) / width; } auto newTempExprs = exprAutoWrapper(tempExpr, intervalTmp, scales); @@ -864,7 +889,7 @@ vector rewrite(string exprStr, string uniqueLabel, vector testError_seconds = timeTmp2 - timeTmp1; // cout << BLUE << "rewrite: For NO." << j << ": testError time: " << testError_seconds.count() << " s" << RESET << endl; diff --git a/srcTest/test1paramFPEDParallel.c b/srcTest/test1paramFPEDParallel.c index 0fe0a365fa580f50cea0eb0892c86467bc675dbe..8e9f5a2156133dd739c87c0da4a251d0e8e54faa 100644 --- a/srcTest/test1paramFPEDParallel.c +++ b/srcTest/test1paramFPEDParallel.c @@ -42,7 +42,7 @@ int computeResult1param(double x0, mpfr_t mpfrResult) return status; } -struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int testNumX0, const char* uniqueLabel, const char* fileNameKernel, int myid, int i0StartLocal, int i0EndLocal) { +struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int testNumX0, const char* uniqueLabel, const char* fileNameKernel, int myid, int i0StartLocal, int i0EndLocal, double x0startOriginInterval, double stepX0) { DL maxInputX0; int i0; // int flag; @@ -73,20 +73,16 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int // printf("testNum : %lu 0x%lx\n", testNumX0, testNumX0); #endif - // loop boundary - lenX0 = x0End.d - x0Start.d; - double stepX0 = lenX0 / (double)testNumX0; - // Real number average maxReUlp = 0; aveReUlp = 0; // flag = 1; sumError = 0; // for(i0 = 0; i0 < testNumX0; i0++) { - // ii0.d = x0Start.d + stepX0 * i0; + // ii0.d = x0startOriginInterval.d + stepX0 * i0; // x0 = ii0.d; for(i0 = i0StartLocal; i0 <= i0EndLocal; i0++) { - x0 = x0Start.d + stepX0 * i0; + x0 = x0startOriginInterval + stepX0 * i0; computeResult1param(x0, mpfrResult); computeOrcle1param(x0, mpfrOrcle); #ifdef SINGLE @@ -155,6 +151,9 @@ int main(int argc, char **argv) unsigned long int testNumX0; x0Start.d = 1; x0End.d = 2; + int x0startNowIdx; + double x0startOriginInterval; + double stepX0; testNumX0 = TESTNUMX0; @@ -162,26 +161,35 @@ int main(int argc, char **argv) fileNameKernel = calloc(256, sizeof(char)); char *uniqueLabel; uniqueLabel = calloc(256, sizeof(char)); - if (argc == 6) + if (argc == 9) { x0Start.d = strtod(argv[1], NULL); x0End.d = strtod(argv[2], NULL); testNumX0 = strtod(argv[3], NULL); - strcpy(fileNameKernel, argv[4]); - strcpy(uniqueLabel, argv[5]); + x0startNowIdx = atoi(argv[4]); + x0startOriginInterval = strtod(argv[5], NULL); + stepX0 = strtod(argv[6], NULL); + strcpy(fileNameKernel, argv[7]); + strcpy(uniqueLabel, argv[8]); } - else if (argc == 5) + else if (argc == 8) { x0Start.d = strtod(argv[1], NULL); x0End.d = strtod(argv[2], NULL); - strcpy(fileNameKernel, argv[3]); - strcpy(uniqueLabel, argv[4]); + x0startNowIdx = atoi(argv[3]); + x0startOriginInterval = strtod(argv[4], NULL); + stepX0 = strtod(argv[5], NULL); + strcpy(fileNameKernel, argv[6]); + strcpy(uniqueLabel, argv[7]); } - else if (argc == 4) + else if (argc == 7) { testNumX0 = strtod(argv[1], NULL); - strcpy(fileNameKernel, argv[2]); - strcpy(uniqueLabel, argv[3]); + x0startNowIdx = atoi(argv[2]); + x0startOriginInterval = strtod(argv[3], NULL); + stepX0 = strtod(argv[4], NULL); + strcpy(fileNameKernel, argv[5]); + strcpy(uniqueLabel, argv[6]); } else { @@ -198,16 +206,16 @@ int main(int argc, char **argv) // local parameters init int lenX0Local = testNumX0 / numProcs; int i0StartLocal; - i0StartLocal = myid * lenX0Local; + i0StartLocal = x0startNowIdx + myid * lenX0Local; int i0EndLocal; if(myid != numProcs - 1) { - i0EndLocal = (myid + 1) * lenX0Local - 1; + i0EndLocal = x0startNowIdx + (myid + 1) * lenX0Local - 1; } else { - i0EndLocal = testNumX0; + i0EndLocal = x0startNowIdx + testNumX0; } // call the error test function - struct errorInfo err = test1FPEDparamParallel(x0Start, x0End, testNumX0, uniqueLabel, fileNameKernel, myid, i0StartLocal, i0EndLocal); + struct errorInfo err = test1FPEDparamParallel(x0Start, x0End, testNumX0, uniqueLabel, fileNameKernel, myid, i0StartLocal, i0EndLocal, x0startOriginInterval, stepX0); // gather errors and find the max struct errorInfo *errs; @@ -245,10 +253,10 @@ int main(int argc, char **argv) exit(0); } printf("average ulp\tmax ulp\n"); - printf("%lg\t%lg\n", aveError, maxError); + 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, "%lg\t%lg\n", aveError, maxError); + 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); free(fileNameErr); diff --git a/srcTest/test2paramFPEDParallel.c b/srcTest/test2paramFPEDParallel.c index a5e26c994361a037850b5718c3b163144d0294c3..c868375f42afc2dbefc39e9ac11bc64cd6d147e9 100644 --- a/srcTest/test2paramFPEDParallel.c +++ b/srcTest/test2paramFPEDParallel.c @@ -45,7 +45,7 @@ int computeResult2param(double x0, double x1, mpfr_t mpfrResult) return status; } -struct errorInfo test2paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1End, unsigned long int testNumX0, unsigned long int testNumX1, const char* uniqueLabel, const char *fileNameKernel, int myid, int i1StartLocal, int i1EndLocal) +struct errorInfo test2paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1End, unsigned long int testNumX0, unsigned long int testNumX1, const char* uniqueLabel, const char *fileNameKernel, int myid, int i0StartLocal, int i0EndLocal, int i1StartLocal, int i1EndLocal, double x0startOriginInterval, double x1startOriginInterval, double stepX0, double stepX1) { // printf("myid = %d: x0Start: %lg, x0End: %lg, x1Start: %lg, x1End: %lg\n", myid, x0Start.d, x0End.d, x1Start.d, x1End.d); DL maxInputX0, maxInputX1; @@ -72,12 +72,6 @@ struct errorInfo test2paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1E } #endif - // loop boundary - lenX0 = x0End.d - x0Start.d; - lenX1 = x1End.d - x1Start.d; - double stepX0 = lenX0 / (double)testNumX0; - double stepX1 = lenX1 / (double)testNumX1; - // Real number average maxReUlp = 0; aveReUlp = 0; @@ -86,10 +80,10 @@ struct errorInfo test2paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1E sumError = 0; for (i1 = i1StartLocal; i1 <= i1EndLocal; i1++) { - x1 = x1Start.d + stepX1 * i1; - for (i0 = 0; i0 <= (int)testNumX0; i0++) + x1 = x1startOriginInterval + stepX1 * i1; + for (i0 = i0StartLocal; i0 <= i0EndLocal; i0++) { - x0 = x0Start.d + stepX0 * i0; + x0 = x0startOriginInterval + stepX0 * i0; computeResult2param(x0, x1, mpfrResult); computeOrcle2param(x0, x1, mpfrOrcle); #ifdef SINGLE @@ -162,6 +156,9 @@ int main(int argc, char **argv) x0End.d = 2; x1Start.d = 1; x1End.d = 2; + int x0startNowIdx, x1startNowIdx; + double x0startOriginInterval, x1startOriginInterval; + double stepX0, stepX1; testNumX0 = TESTNUMX0; testNumX1 = TESTNUMX1; @@ -170,7 +167,7 @@ int main(int argc, char **argv) fileNameKernel = calloc(256, sizeof(char)); char *uniqueLabel; uniqueLabel = calloc(256, sizeof(char)); - if (argc == 9) + if (argc == 15) { x0Start.d = strtod(argv[1], NULL); x0End.d = strtod(argv[2], NULL); @@ -178,24 +175,42 @@ int main(int argc, char **argv) x1End.d = strtod(argv[4], NULL); testNumX0 = strtod(argv[5], NULL); testNumX1 = strtod(argv[6], NULL); - strcpy(fileNameKernel, argv[7]); - strcpy(uniqueLabel, argv[8]); + x0startNowIdx = atoi(argv[7]); + x1startNowIdx = atoi(argv[8]); + x0startOriginInterval = strtod(argv[9], NULL); + x1startOriginInterval = strtod(argv[10], NULL); + stepX0 = strtod(argv[11], NULL); + stepX1 = strtod(argv[12], NULL); + strcpy(fileNameKernel, argv[13]); + strcpy(uniqueLabel, argv[14]); } - else if (argc == 7) + else if (argc == 13) { x0Start.d = strtod(argv[1], NULL); x0End.d = strtod(argv[2], NULL); x1Start.d = strtod(argv[3], NULL); x1End.d = strtod(argv[4], NULL); - strcpy(fileNameKernel, argv[5]); - strcpy(uniqueLabel, argv[6]); + x0startNowIdx = atoi(argv[5]); + x1startNowIdx = atoi(argv[6]); + x0startOriginInterval = strtod(argv[7], NULL); + x1startOriginInterval = strtod(argv[8], NULL); + stepX0 = strtod(argv[9], NULL); + stepX1 = strtod(argv[10], NULL); + strcpy(fileNameKernel, argv[11]); + strcpy(uniqueLabel, argv[12]); } - else if (argc == 5) + else if (argc == 11) { testNumX0 = strtod(argv[1], NULL); testNumX1 = strtod(argv[2], NULL); - strcpy(fileNameKernel, argv[3]); - strcpy(uniqueLabel, argv[4]); + x0startNowIdx = atoi(argv[3]); + x1startNowIdx = atoi(argv[4]); + x0startOriginInterval = strtod(argv[5], NULL); + x1startOriginInterval = strtod(argv[6], NULL); + stepX0 = strtod(argv[7], NULL); + stepX1 = strtod(argv[8], NULL); + strcpy(fileNameKernel, argv[9]); + strcpy(uniqueLabel, argv[10]); } else { @@ -213,19 +228,21 @@ int main(int argc, char **argv) // local parameters init int lenX1Local = testNumX1 / numProcs; int i1StartLocal; - i1StartLocal = myid * lenX1Local; + i1StartLocal = x1startNowIdx + myid * lenX1Local; int i1EndLocal; if (myid != numProcs - 1) { - i1EndLocal = (myid + 1) * lenX1Local - 1; + i1EndLocal = x1startNowIdx + (myid + 1) * lenX1Local - 1; } else { - i1EndLocal = testNumX1; + i1EndLocal = x1startNowIdx + testNumX1; } + int i0StartLocal = x0startNowIdx; + int i0EndLocal = x0startNowIdx + testNumX0; // call the error test function - struct errorInfo err = test2paramFPEDParallel(x0Start, x0End, x1Start, x1End, testNumX0, testNumX1, uniqueLabel, fileNameKernel, myid, i1StartLocal, i1EndLocal); + struct errorInfo err = test2paramFPEDParallel(x0Start, x0End, x1Start, x1End, testNumX0, testNumX1, uniqueLabel, fileNameKernel, myid, i0StartLocal, i0EndLocal, i1StartLocal, i1EndLocal, x0startOriginInterval, x1startOriginInterval, stepX0, stepX1); // gather errors and find the max struct errorInfo *errs; @@ -264,10 +281,10 @@ int main(int argc, char **argv) exit(0); } printf("average ulp\tmax ulp\n"); - printf("%lg\t%lg\n", aveError, maxError); + 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, "%lg\t%lg\n", aveError, 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); diff --git a/srcTest/test3paramFPEDParallel.c b/srcTest/test3paramFPEDParallel.c index 04d39b8e6cff4241350ca0b3a326bedc5272e6cb..80f58e5ccf2a290c9ca88cdbde2f4cc823e3d457 100644 --- a/srcTest/test3paramFPEDParallel.c +++ b/srcTest/test3paramFPEDParallel.c @@ -44,7 +44,7 @@ int computeResult3param(double x0, double x1, double x2, mpfr_t mpfrResult) { return status; } -struct errorInfo test3paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1End, DL x2Start, DL x2End, unsigned long int testNumX0, unsigned long int testNumX1, unsigned long int testNumX2, const char* uniqueLabel, const char* fileNameKernel, int myid, int i2StartLocal, int i2EndLocal) { +struct errorInfo test3paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1End, DL x2Start, DL x2End, unsigned long int testNumX0, unsigned long int testNumX1, unsigned long int testNumX2, const char* uniqueLabel, const char* fileNameKernel, int myid, int i0StartLocal, int i0EndLocal, int i1StartLocal, int i1EndLocal, int i2StartLocal, int i2EndLocal, double x0startOriginInterval, double x1startOriginInterval, double x2startOriginInterval, double stepX0, double stepX1, double stepX2) { // printf("myid = %d: x0Start: %lg, x0End: %lg, x1Start: %lg, x1End: %lg, x2Start: %lg, x2End: %lg\n", myid, x0Start.d, x0End.d, x1Start.d, x1End.d, x2Start.d, x2End.d); DL maxInputX0, maxInputX1, maxInputX2; int i0, i1, i2; @@ -70,25 +70,17 @@ struct errorInfo test3paramFPEDParallel(DL x0Start, DL x0End, DL x1Start, DL x1E } #endif - // loop boundary - lenX0 = x0End.d - x0Start.d; - lenX1 = x1End.d - x1Start.d; - lenX2 = x2End.d - x2Start.d; - double stepX0 = lenX0 / (double)testNumX0; - double stepX1 = lenX1 / (double)testNumX1; - double stepX2 = lenX2 / (double)testNumX2; - // Real number average maxReUlp = 0; // flag = 1; // size_t testCount = 0; sumError = 0; for(i2 = i2StartLocal; i2 <= i2EndLocal; i2++) { - x2 = x2Start.d + stepX2 * i2; - for(i1 = 0; i1 <= (int)testNumX1; i1++) { - x1 = x1Start.d + stepX1 * i1; - for(i0 = 0; i0 <= (int)testNumX0; i0++) { - x0 = x0Start.d + stepX0 * i0; + x2 = x2startOriginInterval + stepX2 * i2; + for(i1 = i1StartLocal; i1 <= i1EndLocal; i1++) { + x1 = x1startOriginInterval + stepX1 * i1; + for(i0 = i0StartLocal; i0 <= i0EndLocal; i0++) { + x0 = x0startOriginInterval + stepX0 * i0; computeResult3param(x0, x1, x2, mpfrResult); computeOrcle3param(x0, x1, x2, mpfrOrcle); #ifdef SINGLE @@ -164,6 +156,9 @@ int main(int argc, char **argv) { x1End.d = 2; x2Start.d = 1; x2End.d = 2; + int x0startNowIdx, x1startNowIdx, x2startNowIdx; + double x0startOriginInterval, x1startOriginInterval, x2startOriginInterval; + double stepX0, stepX1, stepX2; testNumX0 = TESTNUMX0; testNumX1 = TESTNUMX1; @@ -173,7 +168,7 @@ int main(int argc, char **argv) { fileNameKernel = calloc(256, sizeof(char)); char *uniqueLabel; uniqueLabel = calloc(256, sizeof(char)); - if(argc == 12) { + if(argc == 21) { x0Start.d = strtod(argv[1], NULL); x0End.d = strtod(argv[2], NULL); x1Start.d = strtod(argv[3], NULL); @@ -183,23 +178,50 @@ int main(int argc, char **argv) { testNumX0 = strtod(argv[7], NULL); testNumX1 = strtod(argv[8], NULL); testNumX2 = strtod(argv[9], NULL); - strcpy(fileNameKernel, argv[10]); - strcpy(uniqueLabel, argv[11]); - } else if(argc == 9) { + x0startNowIdx = atoi(argv[10]); + x1startNowIdx = atoi(argv[11]); + x2startNowIdx = atoi(argv[12]); + x0startOriginInterval = strtod(argv[13], NULL); + x1startOriginInterval = strtod(argv[14], NULL); + x2startOriginInterval = strtod(argv[15], NULL); + stepX0 = strtod(argv[16], NULL); + stepX1 = strtod(argv[17], NULL); + stepX2 = strtod(argv[18], NULL); + strcpy(fileNameKernel, argv[19]); + strcpy(uniqueLabel, argv[20]); + } else if(argc == 18) { x0Start.d = strtod(argv[1], NULL); x0End.d = strtod(argv[2], NULL); x1Start.d = strtod(argv[3], NULL); x1End.d = strtod(argv[4], NULL); x2Start.d = strtod(argv[5], NULL); x2End.d = strtod(argv[6], NULL); - strcpy(fileNameKernel, argv[7]); - strcpy(uniqueLabel, argv[8]); - } else if(argc == 6) { + x0startNowIdx = atoi(argv[7]); + x1startNowIdx = atoi(argv[8]); + x2startNowIdx = atoi(argv[9]); + x0startOriginInterval = strtod(argv[10], NULL); + x1startOriginInterval = strtod(argv[11], NULL); + x2startOriginInterval = strtod(argv[12], NULL); + stepX0 = strtod(argv[13], NULL); + stepX1 = strtod(argv[14], NULL); + stepX2 = strtod(argv[15], NULL); + strcpy(fileNameKernel, argv[16]); + strcpy(uniqueLabel, argv[17]); + } else if(argc == 15) { testNumX0 = strtod(argv[1], NULL); testNumX1 = strtod(argv[2], NULL); testNumX2 = strtod(argv[3], NULL); - strcpy(fileNameKernel, argv[4]); - strcpy(uniqueLabel, argv[5]); + x0startNowIdx = atoi(argv[4]); + x1startNowIdx = atoi(argv[5]); + x2startNowIdx = atoi(argv[6]); + x0startOriginInterval = strtod(argv[7], NULL); + x1startOriginInterval = strtod(argv[8], NULL); + x2startOriginInterval = strtod(argv[9], NULL); + stepX0 = strtod(argv[10], NULL); + stepX1 = strtod(argv[11], NULL); + stepX2 = strtod(argv[12], NULL); + strcpy(fileNameKernel, argv[13]); + strcpy(uniqueLabel, argv[14]); } else { printf("Usage: ./test3paramFPEDParallel.exe [x0Start x0End x1Start x1End x2Start x2End testNumX0 testNumX1 testNumX2 fileNameKernel]\n"); printf("Usage: if no correct input:\n"); @@ -214,16 +236,20 @@ int main(int argc, char **argv) { // local parameters init int lenX2Local = testNumX2 / numProcs; int i2StartLocal; - i2StartLocal = myid * lenX2Local; + i2StartLocal = x2startNowIdx + myid * lenX2Local; int i2EndLocal; if(myid != numProcs - 1) { - i2EndLocal = (myid + 1) * lenX2Local - 1; + i2EndLocal = x2startNowIdx + (myid + 1) * lenX2Local - 1; } else { - i2EndLocal = testNumX2; + i2EndLocal = x2startNowIdx + testNumX2; } + int i1StartLocal = x1startNowIdx; + int i1EndLocal = x1startNowIdx + testNumX1; + int i0StartLocal = x0startNowIdx; + int i0EndLocal = x0startNowIdx + testNumX0; // call the error test function - struct errorInfo err = test3paramFPEDParallel(x0Start, x0End, x1Start, x1End, x2Start, x2End, testNumX0, testNumX1, testNumX2, uniqueLabel, fileNameKernel, myid, i2StartLocal, i2EndLocal); + struct errorInfo err = test3paramFPEDParallel(x0Start, x0End, x1Start, x1End, x2Start, x2End, testNumX0, testNumX1, testNumX2, uniqueLabel, fileNameKernel, myid, i0StartLocal, i0EndLocal, i1StartLocal, i1EndLocal, i2StartLocal, i2EndLocal, x0startOriginInterval, x1startOriginInterval, x2startOriginInterval, stepX0, stepX1, stepX2); // gather errors and find the max struct errorInfo *errs; @@ -263,10 +289,10 @@ int main(int argc, char **argv) { exit(0); } printf("average ulp\tmax ulp\n"); - printf("%lg\t%lg\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); + 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, "%lg\t%lg\n", aveError, maxError); + fprintf(fErr, "%.16le\t%.16le\n", aveError, maxError); fprintf(fErr, "\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); free(fileNameErr);