From e005e7b31b00176fc69eba8cab8369d2b29c0f3a Mon Sep 17 00:00:00 2001 From: hjw Date: Sat, 24 Dec 2022 23:15:26 +0800 Subject: [PATCH 01/11] support DD --- include/basic.hpp | 10 ++ include/geneCode.hpp | 4 + includeDD/dd.h | 23 +++ includeDD/inline.h | 18 ++ src/geneCode.cpp | 408 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 454 insertions(+), 9 deletions(-) create mode 100644 includeDD/dd.h create mode 100644 includeDD/inline.h diff --git a/include/basic.hpp b/include/basic.hpp index fbe60ea..e665a42 100644 --- a/include/basic.hpp +++ b/include/basic.hpp @@ -36,6 +36,8 @@ extern const size_t promtTimes; /// ExprAST - Base class for all expression nodes. class ExprAST { + int order = 0; + string opType = "double"; public: virtual ~ExprAST() = default; @@ -44,6 +46,14 @@ public: virtual string type() { return "Base"; } virtual std::unique_ptr Clone() { return makePtr(); } + + virtual int getOrder() { return order; } + + virtual void setOrder(int input) { order = input; } + + virtual string getOpType() { return opType; } + + virtual void setOpType(string input) { opType = input; } }; /// NumberExprAST - Expression class for numeric literals like "1.0". diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 0a44bf0..47afce2 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -35,4 +35,8 @@ string geneFinalCodeKernel(string exprStr, string uniqueLabel, vector string geneFinalCode(string exprStr, string uniqueLabel, vector exprInfoVector); +void getDepth(ast_ptr &expr, size_t &depth); + +void codegen(ast_ptr &expr, vector &vars); + #endif \ No newline at end of file diff --git a/includeDD/dd.h b/includeDD/dd.h new file mode 100644 index 0000000..71431b9 --- /dev/null +++ b/includeDD/dd.h @@ -0,0 +1,23 @@ +#ifndef _EFT +#define _EFT + +#define xTmp(x) x##Tmp +#define add_d_d_d(a, b, c) (double c; c = (a) + (b);) +#define add_d_d_dd(a, b, c) (double c[2]; c[0] = two_sum_mine(a, b, c[1]);) +#define add_dd_d_d(a, b, c) (double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b);) +#define add_dd_d_dd(a, b, c) (double c[2]; c_dd_add_dd_d(a, b, c);) +#define add_d_dd_d(a, b, c) (double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b));) +#define add_d_dd_dd(a, b, c) (double c[2]; c_dd_add_d_dd(a, b, c);) +#define add_dd_dd_d(a, b, c) (double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b));) +#define add_dd_dd_dd(a, b, c) (double c[2]; c_dd_add(a, b, c);) + +#define mul_d_d_d(a, b, c) (double c; c = (a) + (b);) +#define mul_d_d_dd(a, b, c) (double c[2]; c[0] = two_prod_mine(a, b, c[1]);) +#define mul_dd_d_d(a, b, c) (double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b);) +#define mul_dd_d_dd(a, b, c) (double c[2]; c_dd_mul_dd_d(a, b, c);) +#define mul_d_dd_d(a, b, c) (double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b));) +#define mul_d_dd_dd(a, b, c) (double c[2]; c_dd_mul_d_dd(a, b, c);) +#define mul_dd_dd_d(a, b, c) (double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b));) +#define mul_dd_dd_dd(a, b, c) (double c[2]; c_dd_mul(a, b, c);) + +#endif // _EFT \ No newline at end of file diff --git a/includeDD/inline.h b/includeDD/inline.h new file mode 100644 index 0000000..6b56880 --- /dev/null +++ b/includeDD/inline.h @@ -0,0 +1,18 @@ +#include + +/* Computes fl(a+b) and err(a+b). */ +inline double two_sum_mine(double a, double b, double &err) +{ + double s = a + b; + double bb = s - a; + err = (a - (s - bb)) + (b - bb); + return s; +} + +/* Computes fl(a*b) and err(a*b). */ +inline double two_prod_mine(double a, double b, double &err) +{ + double p = a * b; + err = fma(a, b, -p); + return p; +} \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 115af75..1b2c65e 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -289,7 +289,7 @@ string geneFinalCodeKernel(string exprStr, string uniqueLabel, std::vector" << std::endl; + fout << "#include \n"; fout << "double " << funcName << "("; for (size_t i = 0; i < vars.size(); ++i) { @@ -299,7 +299,7 @@ string geneFinalCodeKernel(string exprStr, string uniqueLabel, std::vector exprIn auto funcName = geneFinalCodeKernel(exprStr, uniqueLabel, exprInfoVector, vars); return funcName; +} + +void getDepth(ast_ptr &expr, size_t &depth) +{ + static size_t depthNow = 0; + depthNow++; + auto type = expr->type(); + if(type == "Number" || type == "Variable") + { + // nothing + } + else if(type == "Call") + { + CallExprAST *callExpr = dynamic_cast(expr.get()); + auto &args = callExpr->getArgs(); + for(auto& arg : args) + { + getDepth(arg, depth); + } + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + getDepth(lhs, depth); + getDepth(rhs, depth); + } + else + { + fprintf(stderr, "ERROR: unknown type %s", type.c_str()); + exit(EXIT_FAILURE); + } + if(depthNow > depth) + { + depth = depthNow; + } + depthNow--; +} + +void setTypeKernel(ast_ptr &expr, const vector &opTypes) +{ + static size_t depthNow = 0; + auto type = expr->type(); + auto opType = opTypes.at(depthNow); + depthNow++; + if(type == "Number" || type == "Variable") + { + expr->setOpType(opType); + } + else if(type == "Call") + { + CallExprAST *callExpr = dynamic_cast(expr.get()); + auto &args = callExpr->getArgs(); + for(auto& arg : args) + { + setTypeKernel(arg, opTypes); + } + expr->setOpType(opType); + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + setTypeKernel(lhs, opTypes); + setTypeKernel(rhs, opTypes); + expr->setOpType(opType); + } + else + { + fprintf(stderr, "ERROR: unknown type %s", type.c_str()); + exit(EXIT_FAILURE); + } + depthNow--; +} + +// set opTypes for different tree levels by middle +void setType(ast_ptr &expr, size_t depth, size_t middle) +{ + vector opTypes; + for(size_t i = 0; i < middle; i++) + { + opTypes.push_back("DD"); + } + for(size_t i = middle; i < depth; i++) + { + opTypes.push_back("double"); + } + + // start setting the operators' type by vector opTypes + setTypeKernel(expr, opTypes); +} + +void setOrdersKernel(ast_ptr &expr, int &orderNow) +{ + auto type = expr->type(); + if(type == "Number") + { + expr->setOrder(orderNow); + orderNow++; + } + else if(type == "Variable") + { + expr->setOrder(orderNow); + orderNow++; + } + else if(type == "Call") + { + CallExprAST *callExpr = dynamic_cast(expr.get()); + auto &args = callExpr->getArgs(); + vector paramOrders; + for(auto& arg : args) + { + setOrdersKernel(arg, orderNow); + } + expr->setOrder(orderNow); + orderNow++; + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + setOrdersKernel(lhs, orderNow); + setOrdersKernel(rhs, orderNow); + expr->setOrder(orderNow); + orderNow++; + } + else + { + fprintf(stderr, "ERROR: unknowntype %s\n", type.c_str()); + exit(EXIT_FAILURE); + } +} + +int setOrder(ast_ptr &expr) +{ + int order = 0; + setOrdersKernel(expr, order); + return order + 1; +} + +static std::map opMap = { + {'+', "add"}, + {'-', "sub"}, + {'*', "mul"}, + {'/', "div"}}; + +static std::map callMap = { + {"sin", "c_dd_sin"}, + {"cos", "c_dd_cos"}, + {"tan", "c_dd_tan"}, + {"exp", "c_dd_exp"}, + {"exp2", "c_dd_exp2"}, + {"exp10", "c_dd_exp10"}, + {"log", "c_dd_log"}, + {"log2", "c_dd_log2"}, + {"log10", "c_dd_log10"}, + {"asin", "c_dd_asin"}, + {"acos", "c_dd_acos"}, + {"atan", "c_dd_atan"}, + {"sinh", "c_dd_sinh"}, + {"cosh", "c_dd_cosh"}, + {"tanh", "c_dd_tanh"}, + {"asinh", "c_dd_asinh"}, + {"acosh", "c_dd_acosh"}, + {"atanh", "c_dd_atanh"} +}; + +int codegenKernel(ofstream &ofs, const ast_ptr &expr) +{ + auto type = expr->type(); + auto opType = expr->getOpType(); + auto order = expr->getOrder(); + if(type == "Number") + { + NumberExprAST *numPtr = dynamic_cast(expr.get()); + auto num = numPtr->getNumber(); + if(opType == "double") + { + ofs << "\t" << "double tmp" << order << " = " << num << ";\n"; + } + else if(opType == "DD") + { + ofs << "\t" << "double tmp" << order << "[2];\n"; + ofs << "\t" << "tmp" << order << "[0] = " << num << ";\n"; + } + return order; + } + else if(type == "Variable") + { + VariableExprAST *varPtr = dynamic_cast(expr.get()); + auto var = varPtr->getVariable(); + if(opType == "double") + { + ofs << "\t" << "double tmp" << order << " = " << var << ";\n"; + } + else if(opType == "DD") + { + ofs << "\t" << "double tmp" << order << "[2];\n"; + ofs << "\t" << "tmp" << order << "[0] = " << var << ";\n"; + } + return order; + } + else if(type == "Call") + { + CallExprAST *callExpr = dynamic_cast(expr.get()); + auto callee = (callExpr->getCallee()); + auto &args = callExpr->getArgs(); + vector paramOpTypes; + vector paramOrders; + for(const auto& arg : args) + { + auto opType = arg->getOpType(); + paramOpTypes.push_back(opType); + auto paramOrder = codegenKernel(ofs, arg); + paramOrders.push_back(paramOrder); + } + + if(opType == "double") + { + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + auto ¶mOpType = paramOpTypes.at(i); + if(paramOpType == "double") + { + ofs << "\t" << "double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + else if(paramOpType == "DD") + { + ofs << "\t" << "double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << "[0];\n"; + } + else + { + fprintf(stderr, "ERROR: Unknown paramOpType %s\n", paramOpType.c_str()); + exit(EXIT_FAILURE); + } + } + ofs << "\t" << "double tmp" << order << " = " << callee << "("; + for(size_t i = 0; i < paramOrders.size() - 1; i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "p" << paramOrders.back(); + ofs << ");\n"; + } + else if(opType == "DD") + { + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + auto ¶mOpType = paramOpTypes.at(i); + if(paramOpType == "double") + { + 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.0;\n"; + } + else if(paramOpType == "DD") + { + ofs << "\t" << "double p" << paramOrders.at(i) << "[2];\n"; + 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 + { + fprintf(stderr, "ERROR: Unknown paramOpType %s\n", paramOpType.c_str()); + exit(EXIT_FAILURE); + } + } + ofs << "\t" << "double tmp" << 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 << "tmp" << order; + ofs << ");\n"; + } + + return order; + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + char op = binPtr->getOp(); + auto it = opMap.find(op); + auto opStr = it->second; + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + auto orderL = codegenKernel(ofs, lhs); + auto orderR = codegenKernel(ofs, rhs); + auto opTypeL = lhs->getOpType(); + auto opTypeR = rhs->getOpType(); + if(opType == "double") + { + if(opTypeL == "double" && opTypeR == "double") + { + ofs << "\t" << opStr << "_d_d_d(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + } + else if(opTypeL == "double" && opTypeR == "DD") + { + ofs << "\t" << opStr << "_d_dd_d(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + } + else if(opTypeL == "DD" && opTypeR == "double") + { + ofs << "\t" << opStr << "_dd_d_d(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + } + else if(opTypeL == "DD" && opTypeR == "DD") + { + ofs << "\t" << opStr << "_dd_dd_d(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + } + else + { + fprintf(stderr, "ERROR: unsupported type: opTypeL = %s, opTypeR = %s\n", opTypeL.c_str(), opTypeR.c_str()); + exit(EXIT_FAILURE); + } + } + else if(opType == "DD") + { + if(opTypeL == "double" && opTypeR == "double") + { + ofs << "\t" << opStr << "_d_d_dd(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + } + else if(opTypeL == "double" && opTypeR == "DD") + { + ofs << "\t" << opStr << "_d_dd_dd(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + } + else if(opTypeL == "DD" && opTypeR == "double") + { + ofs << "\t" << opStr << "_dd_d_dd(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + } + else if(opTypeL == "DD" && opTypeR == "DD") + { + ofs << "\t" << opStr << "_dd_dd_dd(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + } + else + { + fprintf(stderr, "ERROR: unsupported type: opTypeL = %s, opTypeR = %s\n", opTypeL.c_str(), opTypeR.c_str()); + exit(EXIT_FAILURE); + } + } + else + { + fprintf(stderr, "ERROR: unsupported type: opType = %s\n", opType.c_str()); + exit(EXIT_FAILURE); + } + return order; + } + else + { + fprintf(stderr, "ERROR: unsupported type: type = %s\n", type.c_str()); + exit(EXIT_FAILURE); + } +} + +void codegen(ast_ptr &expr, vector &vars) +{ + // AST init + setOrder(expr); + size_t depth = 0; + getDepth(expr, depth); + cout << "depth: " << depth << endl; + size_t middle = depth / 2; // !!! + setType(expr, depth, middle); + + // generate init + string uniqueLabel = "tmp"; + string directory = "srcTest/" + uniqueLabel + "/"; + string funcName = "expr_" + uniqueLabel + ""; + string fileName = directory + funcName + ".c"; + ofstream file_clean(fileName, ios_base::out); + ofstream ofs(fileName, ios::app); + + // generate + ofs << "#include \n"; + ofs << "#include \n"; + ofs << "#include \"dd.h\"\n"; + ofs << "#include \"inline.h\"\n"; + ofs << "double " << funcName << "("; + for (size_t i = 0; i < vars.size() - 1; i++) + { + ofs << "double" << " " << vars.at(i) << ", "; + } + ofs << "double" << " " << vars.back(); + ofs << ") {\n"; + codegenKernel(ofs, expr); + ofs << "}" << endl; } \ No newline at end of file -- Gitee From a9b8aa7b6714d9354ee83cd367d399d35015c9b0 Mon Sep 17 00:00:00 2001 From: hjw Date: Sat, 7 Jan 2023 22:28:12 +0800 Subject: [PATCH 02/11] support DD --- benchMarkInterval.txt | 2 +- detectErrorOneFPEDParallel.sh | 2 +- detectErrorThreeFPEDParallel.sh | 2 +- detectErrorTwoFPEDParallel.sh | 2 +- include/geneCode.hpp | 4 +-- includeDD/dd.h | 53 +++++++++++++++++++---------- includeDD/inline.h | 59 ++++++++++++++++++++++++++++++--- src/geneCode.cpp | 46 +++++++++++++++++-------- 8 files changed, 129 insertions(+), 41 deletions(-) diff --git a/benchMarkInterval.txt b/benchMarkInterval.txt index 16b257f..0715ee0 100644 --- a/benchMarkInterval.txt +++ b/benchMarkInterval.txt @@ -4,7 +4,7 @@ 0 999 -8 8 0.01 100 --1 1 +-0.5 0.5 0.01 3 0.01 100 0.01 100 diff --git a/detectErrorOneFPEDParallel.sh b/detectErrorOneFPEDParallel.sh index d203a6f..4d91933 100755 --- a/detectErrorOneFPEDParallel.sh +++ b/detectErrorOneFPEDParallel.sh @@ -28,7 +28,7 @@ numProcs=32 echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${prefix} ${middle} ${suffix}" directory="./srcTest"/${uniqueLabel} # echo "${CC} ${testFileName}.c ${prefix}_${suffix}.c ${prefix}_mpfr.c computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -O3 -o ${testFileName}.exe" -${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -o ${testFileName}.exe +${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -lqd -o ${testFileName}.exe # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${prefix}__${middle}_${suffix}" mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${prefix}__${middle}_${suffix} ${uniqueLabel} # mv outputs/${prefix}__${middle}_${suffix}_error.txt ./outputs/${uniqueLabel}/${prefix}__${middle}_${suffix}_error.txt diff --git a/detectErrorThreeFPEDParallel.sh b/detectErrorThreeFPEDParallel.sh index 313c9ba..d90d246 100755 --- a/detectErrorThreeFPEDParallel.sh +++ b/detectErrorThreeFPEDParallel.sh @@ -36,7 +36,7 @@ numProcs=32 echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${prefix} ${middle} ${suffix}" directory="./srcTest"/${uniqueLabel} # echo "${CC} ${testFileName}.c ${prefix}_${suffix}.c ${prefix}_mpfr.c computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -O3 -o ${testFileName}.exe" -${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -o ${testFileName}.exe +${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -lqd -o ${testFileName}.exe # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${prefix}__${middle}_${suffix}" mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${prefix}__${middle}_${suffix} ${uniqueLabel} rm ${testFileName}.exe diff --git a/detectErrorTwoFPEDParallel.sh b/detectErrorTwoFPEDParallel.sh index 0828a8a..dcb5069 100755 --- a/detectErrorTwoFPEDParallel.sh +++ b/detectErrorTwoFPEDParallel.sh @@ -34,7 +34,7 @@ numProcs=32 echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x1Start} ${x1End} ${x0Size} ${x1Size} ${prefix} ${middle} ${suffix}" directory="./srcTest"/${uniqueLabel} # echo "${CC} ${testFileName}.c ${prefix}_${suffix}.c ${prefix}_mpfr.c computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -O3 -o ${testFileName}.exe" -${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -o ${testFileName}.exe +${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -lqd -o ${testFileName}.exe # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x2Start} ${x2End} ${x0Size} ${x1Size} ${x2Size} ${prefix}__${middle}_${suffix}" mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x1Start} ${x1End} ${x0Size} ${x1Size} ${prefix}__${middle}_${suffix} ${uniqueLabel} diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 47afce2..2728342 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -35,8 +35,8 @@ string geneFinalCodeKernel(string exprStr, string uniqueLabel, vector string geneFinalCode(string exprStr, string uniqueLabel, vector exprInfoVector); -void getDepth(ast_ptr &expr, size_t &depth); +void getDepth(ast_ptr &expr, int &depth); -void codegen(ast_ptr &expr, vector &vars); +void codegen(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail); #endif \ No newline at end of file diff --git a/includeDD/dd.h b/includeDD/dd.h index 71431b9..15f0d34 100644 --- a/includeDD/dd.h +++ b/includeDD/dd.h @@ -2,22 +2,41 @@ #define _EFT #define xTmp(x) x##Tmp -#define add_d_d_d(a, b, c) (double c; c = (a) + (b);) -#define add_d_d_dd(a, b, c) (double c[2]; c[0] = two_sum_mine(a, b, c[1]);) -#define add_dd_d_d(a, b, c) (double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b);) -#define add_dd_d_dd(a, b, c) (double c[2]; c_dd_add_dd_d(a, b, c);) -#define add_d_dd_d(a, b, c) (double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b));) -#define add_d_dd_dd(a, b, c) (double c[2]; c_dd_add_d_dd(a, b, c);) -#define add_dd_dd_d(a, b, c) (double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b));) -#define add_dd_dd_dd(a, b, c) (double c[2]; c_dd_add(a, b, c);) -#define mul_d_d_d(a, b, c) (double c; c = (a) + (b);) -#define mul_d_d_dd(a, b, c) (double c[2]; c[0] = two_prod_mine(a, b, c[1]);) -#define mul_dd_d_d(a, b, c) (double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b);) -#define mul_dd_d_dd(a, b, c) (double c[2]; c_dd_mul_dd_d(a, b, c);) -#define mul_d_dd_d(a, b, c) (double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b));) -#define mul_d_dd_dd(a, b, c) (double c[2]; c_dd_mul_d_dd(a, b, c);) -#define mul_dd_dd_d(a, b, c) (double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b));) -#define mul_dd_dd_dd(a, b, c) (double c[2]; c_dd_mul(a, b, c);) +#define add_d_d_d(a, b, c) double c; c = (a) + (b); +#define add_d_d_dd(a, b, c) double c[2]; c[0] = two_sum_mine(a, b, &(c[1])); +#define add_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b); +#define add_dd_d_dd(a, b, c) double c[2]; c_dd_add_dd_d(a, b, c); +#define add_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b)); +#define add_d_dd_dd(a, b, c) double c[2]; c_dd_add_d_dd(a, b, c); +#define add_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b)); +#define add_dd_dd_dd(a, b, c) double c[2]; c_dd_add(a, b, c); -#endif // _EFT \ No newline at end of file +#define sub_d_d_d(a, b, c) double c; c = (a) - (b); +#define sub_d_d_dd(a, b, c) double c[2]; c[0] = two_diff_mine(a, b, &(c[1])); +#define sub_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b); +#define sub_dd_d_dd(a, b, c) double c[2]; c_dd_sub_dd_d(a, b, c); +#define sub_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b)); +#define sub_d_dd_dd(a, b, c) double c[2]; c_dd_sub_d_dd(a, b, c); +#define sub_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b)); +#define sub_dd_dd_dd(a, b, c) double c[2]; c_dd_sub(a, b, c); + +#define mul_d_d_d(a, b, c) double c; c = (a) * (b); +#define mul_d_d_dd(a, b, c) double c[2]; c[0] = two_prod_mine(a, b, &(c[1])); +#define mul_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b); +#define mul_dd_d_dd(a, b, c) double c[2]; c_dd_mul_dd_d(a, b, c); +#define mul_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b)); +#define mul_d_dd_dd(a, b, c) double c[2]; c_dd_mul_d_dd(a, b, c); +#define mul_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b)); +#define mul_dd_dd_dd(a, b, c) double c[2]; c_dd_mul(a, b, c); + +#define div_d_d_d(a, b, c) double c; c = (a) / (b); +#define div_d_d_dd(a, b, c) double c[2]; c[0] = div_mine(a, b, &(c[1])); +#define div_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b); +#define div_dd_d_dd(a, b, c) double c[2]; c_dd_div_dd_d(a, b, c); +#define div_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b)); +#define div_d_dd_dd(a, b, c) double c[2]; c_dd_div_d_dd(a, b, c); +#define div_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b)); +#define div_dd_dd_dd(a, b, c) double c[2]; c_dd_div(a, b, c); + +#endif // _EFT diff --git a/includeDD/inline.h b/includeDD/inline.h index 6b56880..dc754ef 100644 --- a/includeDD/inline.h +++ b/includeDD/inline.h @@ -1,18 +1,69 @@ #include +#include /* Computes fl(a+b) and err(a+b). */ -inline double two_sum_mine(double a, double b, double &err) +static inline double two_sum_mine(double a, double b, double *err) { double s = a + b; double bb = s - a; - err = (a - (s - bb)) + (b - bb); + *err = (a - (s - bb)) + (b - bb); return s; } /* Computes fl(a*b) and err(a*b). */ -inline double two_prod_mine(double a, double b, double &err) +static inline double two_prod_mine(double a, double b, double *err) { double p = a * b; - err = fma(a, b, -p); + *err = fma(a, b, -p); return p; +} + +static inline double two_diff_mine(double a, double b, double *err) +{ + double s = a - b; + double bb = s - a; + *err = (a - (s - bb)) - (b + bb); + return s; +} + +static inline double quick_two_sum_mine(double a, double b, double *err) +{ + double s = a + b; + *err = b - (s - a); + return s; +} + +static inline double div_mine(double a, double b, double *err) +{ + double q1, q2; + double p1, p2; + double s; + + q1 = a / b; + + /* Compute a - q1 * b */ + p1 = two_prod_mine(q1, b, &p2); + s = two_diff_mine(a, p1, err); + *err -= p2; + + /* get next approximation */ + q2 = (s + *err) / b; + + s = quick_two_sum_mine(q1, q2, err); + return s; +} + +// pow = exp(b * log(a)) +static inline void c_dd_pow_mine(double *a, double *b, double *result) { + if(a[0] == 0 && a[1] == 0) + { + result[0] = 0; + result[1] = 0; + return; + } + double tmp1[2]; + double tmp2[2]; + c_dd_log(a, tmp1); + c_dd_mul(tmp1, b, tmp2); + c_dd_exp(tmp2, result); } \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 1b2c65e..2219b19 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -356,9 +356,9 @@ string geneFinalCode(string exprStr, string uniqueLabel, vector exprIn return funcName; } -void getDepth(ast_ptr &expr, size_t &depth) +void getDepth(ast_ptr &expr, int &depth) { - static size_t depthNow = 0; + static int depthNow = 0; depthNow++; auto type = expr->type(); if(type == "Number" || type == "Variable") @@ -432,14 +432,14 @@ void setTypeKernel(ast_ptr &expr, const vector &opTypes) } // set opTypes for different tree levels by middle -void setType(ast_ptr &expr, size_t depth, size_t middle) +void setType(ast_ptr &expr, int depth, int middle) { vector opTypes; - for(size_t i = 0; i < middle; i++) + for(int i = 0; i < middle; i++) { opTypes.push_back("DD"); } - for(size_t i = middle; i < depth; i++) + for(int i = middle; i < depth; i++) { opTypes.push_back("double"); } @@ -508,10 +508,10 @@ static std::map callMap = { {"cos", "c_dd_cos"}, {"tan", "c_dd_tan"}, {"exp", "c_dd_exp"}, - {"exp2", "c_dd_exp2"}, - {"exp10", "c_dd_exp10"}, + // {"exp2", "c_dd_exp2"}, + // {"exp10", "c_dd_exp10"}, {"log", "c_dd_log"}, - {"log2", "c_dd_log2"}, + // {"log2", "c_dd_log2"}, {"log10", "c_dd_log10"}, {"asin", "c_dd_asin"}, {"acos", "c_dd_acos"}, @@ -521,7 +521,9 @@ static std::map callMap = { {"tanh", "c_dd_tanh"}, {"asinh", "c_dd_asinh"}, {"acosh", "c_dd_acosh"}, - {"atanh", "c_dd_atanh"} + {"atanh", "c_dd_atanh"}, + {"sqrt", "c_dd_sqrt"}, + {"pow", "c_dd_pow_mine"} }; int codegenKernel(ofstream &ofs, const ast_ptr &expr) @@ -541,6 +543,7 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) { ofs << "\t" << "double tmp" << order << "[2];\n"; ofs << "\t" << "tmp" << order << "[0] = " << num << ";\n"; + ofs << "\t" << "tmp" << order << "[1] = 0.0;\n"; } return order; } @@ -556,6 +559,7 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) { ofs << "\t" << "double tmp" << order << "[2];\n"; ofs << "\t" << "tmp" << order << "[0] = " << var << ";\n"; + ofs << "\t" << "tmp" << order << "[1] = 0.0;\n"; } return order; } @@ -712,21 +716,25 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) } } -void codegen(ast_ptr &expr, vector &vars) +void codegen(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail) { // AST init setOrder(expr); - size_t depth = 0; + auto order = expr->getOrder(); + int depth = 0; getDepth(expr, depth); cout << "depth: " << depth << endl; - size_t middle = depth / 2; // !!! + // int middle = (depth - 3) > 1 ? (depth - 3) : 1; // !!! + int middle = depth - 1; setType(expr, depth, middle); + auto opType = expr->getOpType(); // generate init - string uniqueLabel = "tmp"; string directory = "srcTest/" + uniqueLabel + "/"; - string funcName = "expr_" + uniqueLabel + ""; + // string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(middle); + string funcName = "expr_" + uniqueLabel + "_" + tail; string fileName = directory + funcName + ".c"; + cout << "fileName: " << fileName << endl; ofstream file_clean(fileName, ios_base::out); ofstream ofs(fileName, ios::app); @@ -743,5 +751,15 @@ void codegen(ast_ptr &expr, vector &vars) ofs << "double" << " " << vars.back(); ofs << ") {\n"; codegenKernel(ofs, expr); + ofs << "\t" << "double result;\n"; + if(opType == "double") + { + ofs << "\t" << "result = tmp" << order << ";\n"; + } + else + { + ofs << "\t" << "result = tmp" << order << "[0];\n"; + } + ofs << "\t" << "return result;\n"; ofs << "}" << endl; } \ No newline at end of file -- Gitee From 927fa2d943bfa275654ca5f39d683269c71f3961 Mon Sep 17 00:00:00 2001 From: hjw Date: Thu, 26 Jan 2023 11:31:30 +0800 Subject: [PATCH 03/11] support performance test initially --- includeTEST/binary.h | 36 ++++++ srcTest/Makefile | 33 ++++++ srcTest/binary.c | 210 ++++++++++++++++++++++++++++++++++ srcTest/dataClean.c | 55 +++++++++ srcTest/gccPerformanceTest.c | 105 +++++++++++++++++ srcTest/testPerformanceOne.sh | 45 ++++++++ 6 files changed, 484 insertions(+) create mode 100644 includeTEST/binary.h create mode 100644 srcTest/Makefile create mode 100644 srcTest/binary.c create mode 100644 srcTest/dataClean.c create mode 100644 srcTest/gccPerformanceTest.c create mode 100755 srcTest/testPerformanceOne.sh diff --git a/includeTEST/binary.h b/includeTEST/binary.h new file mode 100644 index 0000000..77871a7 --- /dev/null +++ b/includeTEST/binary.h @@ -0,0 +1,36 @@ +#ifndef MYHEAD +#define MYHEAD + +#define DATA_COUNT 1000000 + +#define MAXEXP 0x7ffu +#define MINEXP 0x001u +#define DEXPBIAS 0x3ff +#define DMANTISSA 0x000fffffffffffffll +#define DMANTWIDTH 52 +#define DEXPWIDTH 11 + +typedef unsigned long int _UL; +typedef long int _L; +typedef union +{ + double d; + unsigned long int l; +} DL; + +#define D(h,l) l,h +typedef union +{ + struct + { + unsigned int lo; + unsigned int hi; + } word; + + double d; +} du; +#define QNANHI 0xfff80000 +#define QNANLO 0x00000000 +#define QNANF 0xffc00000 + +#endif diff --git a/srcTest/Makefile b/srcTest/Makefile new file mode 100644 index 0000000..03466e1 --- /dev/null +++ b/srcTest/Makefile @@ -0,0 +1,33 @@ +export PROJECT_NAME = exprAuto + +CC = gcc +CPP = g++ +INCLUDE = -I../include -I../includeTEST +LIBS = +ECHO = printf + +# $(info $(CFLAGS) ) +override CFLAGS += -O3 -g -Wall -Wextra -Wpedantic -Wno-unused-function -fdiagnostics-color=always +# $(info $(CFLAGS) ) + +# default: dataClean.exe + +dataClean.exe: dataClean.o + @$(ECHO) "\033[1;32mBuilding $@ \n\033[0m" + $(CC) -o $@ $^ $(LIBS) + +dataClean.o: dataClean.c + @$(ECHO) "\033[1;32mBuilding $@ \n\033[0m" + $(CC) -o $@ -c $< $(CFLAGS) $(INCLUDE) + +gccPerformanceTest.o: gccPerformanceTest.c + @$(ECHO) "\033[1;32mBuilding $@ \n\033[0m" + $(CC) -o $@ -c $< $(CFLAGS) $(INCLUDE) + +binary.o: binary.c + @$(ECHO) "\033[1;32mBuilding $@ \n\033[0m" + $(CC) -o $@ -c $< $(CFLAGS) $(INCLUDE) + +.PHONY: clean +clean: + rm -f *.o *.exe \ No newline at end of file diff --git a/srcTest/binary.c b/srcTest/binary.c new file mode 100644 index 0000000..d0f68d1 --- /dev/null +++ b/srcTest/binary.c @@ -0,0 +1,210 @@ +#include +#include + +#include "binary.h" + +/* copy: copy 'from' into 'to'; assume to is big enough */ +void copy(char to[], char from[]) +{ + int i; + i = 0; + while((to[i] = from[i]) != '\0') + ++i; +} + +_UL ftoid(double x) { return *((_UL *)(&x)); } + +double itofd(_UL x) { return *((double *)(&x)); } + +void getbinary(_UL x, int *result) +{ + int i; + _UL temp; + + temp = x; + for(i = 0; i <= 63; i++) + { + result[i] = temp & 0x0000000000000001; + temp = temp >> 1; + } +} + +_UL getUL(int *result) +{ + int i; + _UL temp; + + temp = 0; + for(i = 63; i >= 0; i--) + { + // result[i] = temp & 0x0000000000000001; + // temp = temp >> 1; + temp = temp << 1; + temp = temp + result[i]; + } + + return temp; +} + +void printbinary(int *result) +{ + int i; + + for(i = 63; i >= 0; i--) + { + printf("%d", result[i]); + } + printf("\n"); +} + +void fprintbinary(FILE *file, int *result) +{ + int i; + + for(i = 63; i >= 0; i--) + { + fprintf(file, "%d", result[i]); + } + fprintf(file, "\n"); +} + +void binaryshow(double x) +{ + _UL temp; + int sign, e, i, result[64]; + + temp = ftoid(x); + getbinary(temp, result); + sign = result[63]; + e = 0; + for(i = 10; i >= 0; i--) + { + e = (e << 1) + result[52 + i]; + } + + if(e == 0) + { + printf(" 0."); + } + else + { + e = e - (1 << 10) + 1; + if(sign == 0) + { + printf("+1."); + } + else + { + printf("-1."); + } + } + for(i = 51; i >= 0; i--) + { + printf("%d", result[i]); + } + printf("b%d\n", e); +} + +_UL computeULPDiff(double x1, double x2) +{ + _UL temp1, temp2; + _UL t; + + temp1 = ftoid(x1); + temp2 = ftoid(x2); + + temp1 = temp1 & 0x000fffffffffffff; + temp2 = temp2 & 0x000fffffffffffff; + + if(temp1 > temp2) + { + t = temp1 - temp2; + } + else + { + t = temp2 - temp1; + } + + return t; +} + +int computeAccurateBit(double x1, double x2) +{ + int y1[64], y2[64], i, count; + _UL temp1, temp2; + + temp1 = ftoid(x1); + temp2 = ftoid(x2); + getbinary(temp1, y1); + getbinary(temp2, y2); + + count = 0; + for(i = 51; i >= 0; i--) + { + if(y1[i] != y2[i]) + { + break; + } + count++; + } + + return count; +} + +int jiou(int x) +{ + if(x % 2 == 0) + return 1; + else + return 0; +} + +double computeULP(double y) +{ + double x = 0, res = 0, powermin = 0, powermax = 0, powermiddle = 0; + int expmin = 0, expmax = 0, expmiddle = 0, jioupanduan = 0; + x = fabs(y); + + // printf("res=%.8f\n", pow(2, logb(x)+1-53)); + + if(x < pow(2, -1021)) + res = pow(2, -1074); + else if(x > (1 - pow(2, -53)) * pow(2, 1024)) + res = pow(2, 971); + else + { + powermin = pow(2, -1021); + expmin = -1021; + powermax = pow(2, 1024); + expmax = 1024; + } + + while(expmax - expmin > 1) + { + jioupanduan = jiou(expmin + expmax); + + if(jioupanduan == 1) + expmiddle = (expmax + expmin) / 2; + else + expmiddle = (expmax + expmin + 1) / 2; + + powermiddle = pow(2, expmiddle); + + if(x >= powermiddle) + { + powermin = powermiddle; + expmin = expmiddle; + } + else + { + powermax = powermiddle; + expmax = expmiddle; + } + + if(x == powermin) + res = pow(2, expmin - 53); + else + res = pow(2, expmin - 52); + } + return res; +} diff --git a/srcTest/dataClean.c b/srcTest/dataClean.c new file mode 100644 index 0000000..7c3a3c4 --- /dev/null +++ b/srcTest/dataClean.c @@ -0,0 +1,55 @@ +#include +#include + +#define MAX_LEN 255 +#define PERCENT 0.0005 +#ifndef RUNTIME +#define RUNTIME 10000 +#endif + +int main(int argc, char *argv[]) +{ + int row = 0, i = 0; + long cycle = 0; + FILE *data; + long time_base[RUNTIME]; + long time_base_sum = 0; + int start, end; + + if(argc == 2) + { + data = fopen(argv[1], "r"); + } + else + { + printf("ERROR: Invalid arguments. argc should be 2, not %d\n", argc); + exit(EXIT_FAILURE); + } + + if(!data) + { + printf("Error in opening file.\r\n"); + exit(1); + } + + // printf("----Starting data clean: %d----\n", RUNTIME); + row = 0; + while(fscanf(data, "%ld\n", &time_base[row]) != EOF) + { + row++; + } + start = row * PERCENT; + end = row - start; + // printf("the data size is %d, we choose: %d to %d\n", row, start, end); + for(i = start; i < end; i++) + { + time_base_sum += time_base[i]; + } + // printf("----End data clean----\n"); + + cycle = time_base_sum / (end - start); + // printf("the performance result (cycle): %ld\n", cycle); + printf("%ld\n", cycle); + + fclose(data); +} diff --git a/srcTest/gccPerformanceTest.c b/srcTest/gccPerformanceTest.c new file mode 100644 index 0000000..fdf7f9b --- /dev/null +++ b/srcTest/gccPerformanceTest.c @@ -0,0 +1,105 @@ +#include +#include +#include +// #include +#include +#include + +#include "common.h" + +#ifndef FUNCNAME +#define FUNCNAME sin +#endif +#ifndef RUNTIME +#define RUNTIME 10000 +#endif + +double FUNCNAME(double); +/* copy: copy 'from' into 'to'; assume to is big enough */ +void copy(char to[], char from[]); + +// for performance test +extern inline __attribute__((always_inline)) unsigned long rdtscp() +{ + unsigned long a, d, c; + + __asm__ volatile("rdtscp" : "=a"(a), "=d"(d), "=c"(c)); + + return (a | (d << 32)); +} + +int main(int argc, char *argv[]) +{ + int i; + unsigned long times[RUNTIME]; + unsigned long sum; + uint64_t start, end; + double inputdata[RUNTIME]; + double result[RUNTIME], sumResult = 0, test = 1; + double data_start = 0, data_end = 1; + FILE *stream_time; + char outputFile[64] = "FUNCNAME_time.txt"; // the name of the outputFile. + + srand((unsigned)time(NULL)); + if(argc == 2) + { + copy(outputFile, argv[1]); + // printf("Performance test function: %s\n", outputFile); + // printf("outputFile is %s.\ntest from %f, end at %f by default\n", outputFile, data_start, data_end); + } + if(argc == 4) + { + copy(outputFile, argv[1]); + data_start = atof(argv[2]); + data_end = atof(argv[3]); + // printf("Performance test function: %s\n", outputFile); + // printf("outputFile is %s.\ntest from %f, end at %f\n", outputFile, data_start, data_end); + } + stream_time = fopen(outputFile, "w"); + if(stream_time == (FILE *)0) + { + printf("open file error!\n"); + exit(1); + } + + // printf("----Starting generating %d test data----\n", RUNTIME); + for(i = 0; i < RUNTIME; i++) + { + inputdata[i] = (double)rand() / ((double)RAND_MAX + 1) * ((data_end) - (data_start)) + (data_start); + } + // printf("----End generating %d test data----\n", RUNTIME); + + // printf("----Starting performance test----\n"); + for(i = 0; i < 100; i++) + { + FUNCNAME(inputdata[i]); + } + for(i = 0; i < RUNTIME; i++) + { + start = rdtscp(); + result[i] = FUNCNAME(inputdata[i]); + end = rdtscp(); + // printf("the %d result is %f\n", i, result[i]); + result[i] = result[i] + test; + times[i] = end - start; + // printf("time is %llu clock cycles\n", times[i]); + } + + // printf("----End performance test----\n"); + + sum = 0; + for(i = 0; i < RUNTIME; i++) + { + fprintf(stream_time, "%lu\n", times[i]); + sum = sum + times[i]; + sumResult = sumResult + result[i]; + } + sum = sum / RUNTIME; + printf("sumResult is %f\n", sumResult); + // printf("the performance result to be clean: %lu\n", sum); + if(fclose(stream_time) == EOF) + { + printf("close file error!\n"); + exit(1); + } +} diff --git a/srcTest/testPerformanceOne.sh b/srcTest/testPerformanceOne.sh new file mode 100755 index 0000000..a76493b --- /dev/null +++ b/srcTest/testPerformanceOne.sh @@ -0,0 +1,45 @@ +#example: cd path/to/srcTest; taskset -c 0 ./testPerformanceOne.sh Bsplines3 origin 0 100 + +if [ $# == 1 ]; then + uniqueLabel=${1} + suffix=origin + start=0.01 + end=100 + runtime=10000 +elif [ $# == 4 ]; then + uniqueLabel=${1} + suffix=${2} + start=${3} + end=${4} + runtime=10000 +elif [ $# == 5 ]; then + uniqueLabel=${1} + suffix=${2} + start=${3} + end=${4} + runtime=${5} +else + echo "please input 1, 4 or 5 parameters" + exit +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 + +# make gccPerformanceTest.o -s CFLAGS="-DFUNCNAME=${funcName} -DRUNTIME=${runtime}" +gcc gccPerformanceTest.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.c.o ${funcName}.o -lm -lqd -o gccPerformanceTest_${uniqueLabel}.exe -O3 +./gccPerformanceTest_${uniqueLabel}.exe ${resultFileName} ${start} ${end} > /dev/null +# rm -rf gccPerformanceTest_${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 > ../outputs/${uniqueLabel}/${funcName}_performance.txt +rm -rf ${resultFileName} ${resultFileName}.sort +# rm dataClean.exe + -- Gitee From 448f3ef8c485bd0e2118d99b875828fa2aba7c3b Mon Sep 17 00:00:00 2001 From: hjw Date: Sat, 28 Jan 2023 22:02:32 +0800 Subject: [PATCH 04/11] Add performance test to the Main process --- Makefile | 2 +- include/tools.hpp | 2 ++ src/tools.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0a53543..290e4c2 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ LIBS = -lpython3.8 -lfmt ECHO = printf # $(info $(CFLAGS) ) -override CFLAGS += -g -Wall -Wextra -Wpedantic -Wno-unused-function -fdiagnostics-color=always +override CFLAGS += -g -Wall -Wextra -Wpedantic -Wno-unused-function -fdiagnostics-color=always --std=c++2a # $(info $(CFLAGS) ) EXPRAUTO_ALL_SRCS_CPP = $(wildcard src/*.cpp) diff --git a/include/tools.hpp b/include/tools.hpp index 1159fdc..3d5fc50 100644 --- a/include/tools.hpp +++ b/include/tools.hpp @@ -35,6 +35,8 @@ exprInfo testError(string uniqueLabel, string suffix, double x0Start, double x0E exprInfo testError(string uniqueLabel, string suffix, double x0Start, double x0End, double x1Start, double x1End, double x2Start, double x2End, int x0Size, int x1Size, int x2Size); +double testPerformance(string uniqueLabel, string suffix, const vector &intervals); + void geneBoundaryData(string uniqueLabel, string suffix); void geneIntervalData(string uniqeuLabel, vector &intervals, vector &threholds); diff --git a/src/tools.cpp b/src/tools.cpp index ac0dc82..c8c435a 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -387,7 +388,9 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte } } string fileNameKernel = prefix + "__" + middle + "_" + suffix; - string testName = "./outputs/" + uniqueLabel + "/" + fileNameKernel + "_error.txt"; + namespace fs = std::filesystem; + string currentPath = fs::current_path(); + string testName = currentPath + "/outputs/" + uniqueLabel + "/" + fileNameKernel + "_error.txt"; string number[3] = {"One", "Two", "Three"}; string scriptName = "./detectError" + number[size - 1] + "FPEDParallel.sh"; string commandStr = scriptName + " " + uniqueLabel; @@ -444,6 +447,66 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte return tempError; } +double testPerformance(string uniqueLabel, string suffix, const vector &intervals) +{ + size_t size = intervals.size() / 2; + string prefix = "expr_" + uniqueLabel; + string fileNameKernel = prefix + "_" + suffix; + if (size < 4) + { + vector params; + for(const auto &interval : intervals) + { + auto paraTmp = fmt::format("{}", interval); + params.push_back(paraTmp); + } + + string number[3] = {"One", "Two", "Three"}; + string scriptName = "./testPerformance" + number[size - 1] + ".sh"; + string commandStr = "taskset -c 0 " +scriptName + " " + uniqueLabel + " " + suffix; + for(const auto & param : params) + { + commandStr = commandStr + " " + param; + } + commandStr = "cd srcTest; " + commandStr + "; cd -;"; + cout << "fileNameKernel: " << fileNameKernel << "\ncommand: " << commandStr << endl; + char command[200] = {0}; + strcat(command, commandStr.c_str()); + system(command); + } + else if (size == 4) + { + fprintf(stderr, "WRONG: rewrite: the intervalTmp's dimension is %ld, which we don't support now.\n", size); + exit(EXIT_FAILURE); + } + else + { + fprintf(stderr, "WRONG: rewrite: the intervalTmp's dimension is %ld, which we don't support now.\n", size); + exit(EXIT_FAILURE); + } + + namespace fs = std::filesystem; + string currentPath = fs::current_path(); + string testName = currentPath + "/outputs/" + uniqueLabel + "/" + fileNameKernel + "_performance.txt"; + std::ifstream ifs(testName, std::ios::in); + double tempCycles; + if(ifs.eof()) + { + std::cout << "is null" << std::endl; + ifs.close(); + tempCycles = 0; + } + else + { + std::string lineStr; + std::getline(ifs, lineStr); + std::istringstream ss(lineStr); + ss >> tempCycles; + } + + return tempCycles; +} + // TODO: implement // call matlab to generate the boundaryData to file void geneBoundaryData(string uniqueLabel, string suffix) -- Gitee From 8371c8ccfb63f5469e0ec64339eca3ef5681d2f1 Mon Sep 17 00:00:00 2001 From: hjw Date: Mon, 20 Feb 2023 16:28:36 +0800 Subject: [PATCH 05/11] Support testing performance manually --- srcTest/testPerformanceOneManual.sh | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100755 srcTest/testPerformanceOneManual.sh diff --git a/srcTest/testPerformanceOneManual.sh b/srcTest/testPerformanceOneManual.sh new file mode 100755 index 0000000..ff23c00 --- /dev/null +++ b/srcTest/testPerformanceOneManual.sh @@ -0,0 +1,44 @@ +#example: cd path/to/srcTest; taskset -c 0 ./testPerformanceOneManual.sh Bsplines3 origin 0 100 + +if [ $# == 1 ]; then + uniqueLabel=${1} + suffix=origin + start=0.01 + end=100 + runtime=10000 +elif [ $# == 4 ]; then + uniqueLabel=${1} + suffix=${2} + start=${3} + end=${4} + runtime=10000 +elif [ $# == 5 ]; then + uniqueLabel=${1} + suffix=${2} + start=${3} + end=${4} + runtime=${5} +else + echo "please input 1, 4 or 5 parameters" + exit +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 + +# make gccPerformanceTest.o -s CFLAGS="-DFUNCNAME=${funcName} -DRUNTIME=${runtime}" +gcc gccPerformanceTest.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 + +### 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 dd93eb1adb1ce864fa7bed980951b12e50be399e Mon Sep 17 00:00:00 2001 From: hjw Date: Mon, 20 Feb 2023 16:39:40 +0800 Subject: [PATCH 06/11] Support more functions for mpfr --- src/geneCode.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 2219b19..d69cf2e 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -208,14 +208,19 @@ string geneMpfrCode(const ast_ptr &exprAst, const string uniqueLabel, vector vars; // getVariablesFromExpr(exprAst, vars); size_t mpfr_variables = 0; -- Gitee From 04dc78cf03485779110e5bcb1cf806b95be38950 Mon Sep 17 00:00:00 2001 From: hjw Date: Mon, 20 Feb 2023 16:44:27 +0800 Subject: [PATCH 07/11] Support TGen initially --- .gitignore | 1 + detectErrorOneFPEDParallel.sh | 2 +- include/geneCode.hpp | 2 ++ includeTEST/tgen.h | 18 +++++++++++++++ src/geneCode.cpp | 43 +++++++++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 includeTEST/tgen.h diff --git a/.gitignore b/.gitignore index 1bf4bd6..609777a 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ .vscode/ .history/ build/ +srcGen/ main *.txt __pycache__/ diff --git a/detectErrorOneFPEDParallel.sh b/detectErrorOneFPEDParallel.sh index 4d91933..af34d56 100755 --- a/detectErrorOneFPEDParallel.sh +++ b/detectErrorOneFPEDParallel.sh @@ -28,7 +28,7 @@ numProcs=32 echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${prefix} ${middle} ${suffix}" directory="./srcTest"/${uniqueLabel} # echo "${CC} ${testFileName}.c ${prefix}_${suffix}.c ${prefix}_mpfr.c computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -O3 -o ${testFileName}.exe" -${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -lqd -o ${testFileName}.exe +${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -Llibs -lTGen -lmpfr -lm -lqd -o ${testFileName}.exe # echo "mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${prefix}__${middle}_${suffix}" mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${prefix}__${middle}_${suffix} ${uniqueLabel} # mv outputs/${prefix}__${middle}_${suffix}_error.txt ./outputs/${uniqueLabel}/${prefix}__${middle}_${suffix}_error.txt diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 2728342..e358bbe 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -23,6 +23,8 @@ string geneOriginCodeKernel(string exprStr, vector vars, string uniqueLa string geneOriginCode(string exprStr, string uniqueLabel, string tail); +string geneTGenCode(string exprStr, vector vars, string uniqueLabel,string tail); + void geneHerbieCode(string exprstr, vector cs, string exprname,double v[], double u[]); void geneDaisyCode(string exprStr); diff --git a/includeTEST/tgen.h b/includeTEST/tgen.h new file mode 100644 index 0000000..61cf97e --- /dev/null +++ b/includeTEST/tgen.h @@ -0,0 +1,18 @@ +double sin_gen(double); +double cos_gen(double); +double tan_gen(double); +double asin_gen(double); +double acos_gen(double); +double atan_gen(double); +double sinh_gen(double); +double cosh_gen(double); +double tanh_gen(double); +double asinh_gen(double); +double acosh_gen(double); +double atanh_gen(double); +double exp_gen(double); +double exp2_gen(double); +double exp10_gen(double); +double log_gen(double); +double log2_gen(double); +double log10_gen(double); \ No newline at end of file diff --git a/src/geneCode.cpp b/src/geneCode.cpp index d69cf2e..f2079c8 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -163,6 +163,49 @@ string geneOriginCode(string exprStr, string uniqueLabel, string tail) return funcName; } +string geneTGenCode(string exprStr, vector vars, string uniqueLabel, string tail) +{ + // replace func to func_gen + string exprNewStr(exprStr); + vector supportFuncList = {"sin", "cos", "tan", "exp", "log", "sinh", "cosh", "tanh"}; + for(auto replaceFrom : supportFuncList) + { + string replaceTo(replaceFrom); + replaceTo.append("_gen("); + replaceFrom += "("; + int pos = exprNewStr.find(replaceFrom); + while(pos != -1) + { + exprNewStr.replace(pos, replaceFrom.length(), replaceTo); + pos = exprNewStr.find(replaceFrom); + } + } + // generate TGen code + std::ofstream fout; + string directory = "srcTest/" + uniqueLabel + "/"; + string funcName = "expr_" + uniqueLabel + "_" + tail; + string fileName = directory + funcName + ".c"; + fout.open(fileName); + fout << "#include \n"; + fout << "#include \"tgen.h\"\n"; // this one is important + fout << "double " << funcName << "("; + for (size_t i = 0; i < vars.size(); ++i) + { + if (i != vars.size() - 1) + fout << "double" << " " << vars.at(i) << ", "; + else + fout << "double" << " " << vars.at(i); + } + fout << ")\n"; + fout << "{\n"; + fout << "\t" << "double result = " << exprNewStr << ";\n"; + fout << "\t" << "return result;\n"; + fout << "}\n"; + fout.close(); + + return funcName; +} + void geneHerbieCode(string exprstr, vector cs, string exprname, double v[], double u[]) { std::ofstream fout; -- Gitee From d4ee422525c2be9825449fefdb202ea1e209b684 Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 21 Feb 2023 10:57:02 +0800 Subject: [PATCH 08/11] Fix bugs about DD --- includeDD/dd.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/includeDD/dd.h b/includeDD/dd.h index 15f0d34..49e977e 100644 --- a/includeDD/dd.h +++ b/includeDD/dd.h @@ -14,29 +14,29 @@ #define sub_d_d_d(a, b, c) double c; c = (a) - (b); #define sub_d_d_dd(a, b, c) double c[2]; c[0] = two_diff_mine(a, b, &(c[1])); -#define sub_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b); +#define sub_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) - (b); #define sub_dd_d_dd(a, b, c) double c[2]; c_dd_sub_dd_d(a, b, c); -#define sub_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b)); +#define sub_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) - (xTmp(b)); #define sub_d_dd_dd(a, b, c) double c[2]; c_dd_sub_d_dd(a, b, c); -#define sub_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b)); +#define sub_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) - (xTmp(b)); #define sub_dd_dd_dd(a, b, c) double c[2]; c_dd_sub(a, b, c); #define mul_d_d_d(a, b, c) double c; c = (a) * (b); #define mul_d_d_dd(a, b, c) double c[2]; c[0] = two_prod_mine(a, b, &(c[1])); -#define mul_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b); +#define mul_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) * (b); #define mul_dd_d_dd(a, b, c) double c[2]; c_dd_mul_dd_d(a, b, c); -#define mul_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b)); +#define mul_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) * (xTmp(b)); #define mul_d_dd_dd(a, b, c) double c[2]; c_dd_mul_d_dd(a, b, c); -#define mul_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b)); +#define mul_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) * (xTmp(b)); #define mul_dd_dd_dd(a, b, c) double c[2]; c_dd_mul(a, b, c); #define div_d_d_d(a, b, c) double c; c = (a) / (b); #define div_d_d_dd(a, b, c) double c[2]; c[0] = div_mine(a, b, &(c[1])); -#define div_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b); +#define div_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) / (b); #define div_dd_d_dd(a, b, c) double c[2]; c_dd_div_dd_d(a, b, c); -#define div_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b)); +#define div_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) / (xTmp(b)); #define div_d_dd_dd(a, b, c) double c[2]; c_dd_div_d_dd(a, b, c); -#define div_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b)); +#define div_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) / (xTmp(b)); #define div_dd_dd_dd(a, b, c) double c[2]; c_dd_div(a, b, c); #endif // _EFT -- Gitee From af21167e9f235fca930d37cdd6f04444671531e9 Mon Sep 17 00:00:00 2001 From: hjw Date: Tue, 21 Feb 2023 15:50:39 +0800 Subject: [PATCH 09/11] support DD Details: Generate double-double implementations in all states --- include/geneCode.hpp | 2 +- src/geneCode.cpp | 189 ++++++++++++++++++++++++++++------ srcTest/testPerformanceOne.sh | 2 +- 3 files changed, 160 insertions(+), 33 deletions(-) diff --git a/include/geneCode.hpp b/include/geneCode.hpp index e358bbe..75842a4 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -39,6 +39,6 @@ string geneFinalCode(string exprStr, string uniqueLabel, vector exprIn void getDepth(ast_ptr &expr, int &depth); -void codegen(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail); +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 f2079c8..3b5f09a 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -496,7 +496,81 @@ void setType(ast_ptr &expr, int depth, int middle) setTypeKernel(expr, opTypes); } -void setOrdersKernel(ast_ptr &expr, int &orderNow) +// set opTypes for different tree nodes by opTypes +void setType(ast_ptr &expr, vector opTypes) +{ + auto type = expr->type(); + if(type == "Number" || type == "Variable") + { + return; + } + + auto order = expr->getOrder(); + auto opType = opTypes.at(order); + // cout << "setType: NO." << order << ", type = " << type << ", opType = " << opType << "\n"; + expr->setOpType(opType); + if(type == "Call") + { + CallExprAST *callExpr = dynamic_cast(expr.get()); + auto &args = callExpr->getArgs(); + for(auto& arg : args) + { + setType(arg, opTypes); + } + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + setType(lhs, opTypes); + setType(rhs, opTypes); + } + else + { + fprintf(stderr, "ERROR: unknown type %s", type.c_str()); + exit(EXIT_FAILURE); + } +} + +// set opTypes for different tree nodes by opTypes +void setType(ast_ptr &expr, map opTypes) +{ + auto type = expr->type(); + if(type == "Number" || type == "Variable") + { + return; + } + + auto order = expr->getOrder(); + auto opType = opTypes.at(order); + // cout << "setType: NO." << order << ", type = " << type << ", opType = " << opType << "\n"; + expr->setOpType(opType); + if(type == "Call") + { + CallExprAST *callExpr = dynamic_cast(expr.get()); + auto &args = callExpr->getArgs(); + for(auto& arg : args) + { + setType(arg, opTypes); + } + } + else if(type == "Binary") + { + BinaryExprAST *binPtr = dynamic_cast(expr.get()); + ast_ptr &lhs = binPtr->getLHS(); + ast_ptr &rhs = binPtr->getRHS(); + setType(lhs, opTypes); + setType(rhs, opTypes); + } + else + { + fprintf(stderr, "ERROR: unknown type %s", type.c_str()); + exit(EXIT_FAILURE); + } +} + +void setOrdersKernel(ast_ptr &expr, int &orderNow, vector &opOrder) { auto type = expr->type(); if(type == "Number") @@ -511,14 +585,15 @@ void setOrdersKernel(ast_ptr &expr, int &orderNow) } else if(type == "Call") { - CallExprAST *callExpr = dynamic_cast(expr.get()); - auto &args = callExpr->getArgs(); + CallExprAST *callPtr = dynamic_cast(expr.get()); + auto &args = callPtr->getArgs(); vector paramOrders; for(auto& arg : args) { - setOrdersKernel(arg, orderNow); + setOrdersKernel(arg, orderNow, opOrder); } expr->setOrder(orderNow); + opOrder.push_back(orderNow); orderNow++; } else if(type == "Binary") @@ -526,9 +601,10 @@ void setOrdersKernel(ast_ptr &expr, int &orderNow) BinaryExprAST *binPtr = dynamic_cast(expr.get()); ast_ptr &lhs = binPtr->getLHS(); ast_ptr &rhs = binPtr->getRHS(); - setOrdersKernel(lhs, orderNow); - setOrdersKernel(rhs, orderNow); + setOrdersKernel(lhs, orderNow, opOrder); + setOrdersKernel(rhs, orderNow, opOrder); expr->setOrder(orderNow); + opOrder.push_back(orderNow); orderNow++; } else @@ -538,11 +614,13 @@ void setOrdersKernel(ast_ptr &expr, int &orderNow) } } -int setOrder(ast_ptr &expr) +// set orders for nodes in expr and return the operation nodes' order (aka binary & call) +vector setOrder(ast_ptr &expr) { int order = 0; - setOrdersKernel(expr, order); - return order + 1; + vector opOrder; + setOrdersKernel(expr, order, opOrder); + return opOrder; } static std::map opMap = { @@ -764,29 +842,10 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) } } -void codegen(ast_ptr &expr, vector &vars, const string uniqueLabel, string tail) +void codegen(ast_ptr &expr, vector &vars, const string funcName, ofstream &ofs) { - // AST init - setOrder(expr); - auto order = expr->getOrder(); - int depth = 0; - getDepth(expr, depth); - cout << "depth: " << depth << endl; - // int middle = (depth - 3) > 1 ? (depth - 3) : 1; // !!! - int middle = depth - 1; - setType(expr, depth, middle); auto opType = expr->getOpType(); - - // generate init - string directory = "srcTest/" + uniqueLabel + "/"; - // string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(middle); - string funcName = "expr_" + uniqueLabel + "_" + tail; - string fileName = directory + funcName + ".c"; - cout << "fileName: " << fileName << endl; - ofstream file_clean(fileName, ios_base::out); - ofstream ofs(fileName, ios::app); - - // generate + auto order = expr->getOrder(); ofs << "#include \n"; ofs << "#include \n"; ofs << "#include \"dd.h\"\n"; @@ -810,4 +869,72 @@ void codegen(ast_ptr &expr, vector &vars, const string uniqueLabel, stri } ofs << "\t" << "return result;\n"; ofs << "}" << endl; -} \ No newline at end of file +} + +// 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) +{ + // AST init + auto opOrder = setOrder(expr); + auto lenOp = opOrder.size(); + + // set opTypes: method NO.1 + // int depth = 0; + // getDepth(expr, depth); + // cout << "codegen: depth: " << depth << endl; + // 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; + // for(int j = 0; j <= order; j++) + // { + // auto tmp = currentNum % 2; + // if(tmp == 0) + // { + // opTypes.push_back("DD"); + // } + // else + // { + // opTypes.push_back("double"); + // } + // currentNum = currentNum >> 1; + // } + + int maxNum = 1 << lenOp; + for(int num = 0; num < maxNum; num++) + { + // set opTypes: method NO.3 + auto currentNum = num; + std::map opTypes; + vector dataTypes = {"DD", "double"}; + for(size_t i = 0; i < lenOp; i++) + { + auto id = opOrder[i]; + auto tmp = currentNum % 2; + opTypes[id] = dataTypes[tmp]; + currentNum = currentNum >> 1; + } + setType(expr, opTypes); + + // init to generate code + string directory = "srcTest/" + uniqueLabel + "/"; + string funcName = "expr_" + uniqueLabel + "_" + tail + "_" + to_string(num); + string fileName = directory + funcName + ".c"; + cout << "fileName: " << fileName << "\topTypes: "; + for(map::iterator it = opTypes.begin(); it != opTypes.end(); it++) + { + cout << it->first << " " << it->second << ", "; + } + cout << "\n"; + ofstream file_clean(fileName, ios_base::out); + ofstream ofs(fileName, ios::app); + + // call codegen to generate code + codegen(expr, vars, funcName, ofs); + } + + return maxNum; +} diff --git a/srcTest/testPerformanceOne.sh b/srcTest/testPerformanceOne.sh index a76493b..fa7ee70 100755 --- a/srcTest/testPerformanceOne.sh +++ b/srcTest/testPerformanceOne.sh @@ -32,7 +32,7 @@ funcName=expr_${uniqueLabel}_${suffix} gcc gccPerformanceTest.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.c.o ${funcName}.o -lm -lqd -o gccPerformanceTest_${uniqueLabel}.exe -O3 +gcc gccPerformanceTest.o binary.o ${funcName}.o -lm -lqd -o gccPerformanceTest_${uniqueLabel}.exe -O3 ./gccPerformanceTest_${uniqueLabel}.exe ${resultFileName} ${start} ${end} > /dev/null # rm -rf gccPerformanceTest_${uniqueLabel}.exe -- Gitee From f579dcb5c310a86f503f5d5d6ad47cefe759366e Mon Sep 17 00:00:00 2001 From: hjw Date: Sat, 25 Feb 2023 21:10:08 +0800 Subject: [PATCH 10/11] support LD initially --- Makefile | 2 +- includeDD/dd.h | 134 ++++++++++++++++++++++++++++++++------- includeDD/inline.h | 10 +-- src/geneCode.cpp | 152 +++++++++++++++++++++++++++------------------ 4 files changed, 207 insertions(+), 91 deletions(-) diff --git a/Makefile b/Makefile index 290e4c2..291ac1e 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 = -lpython3.8 -lfmt +LIBS = -lm -lpython3.8 -lfmt ECHO = printf # $(info $(CFLAGS) ) diff --git a/includeDD/dd.h b/includeDD/dd.h index 49e977e..91a1c94 100644 --- a/includeDD/dd.h +++ b/includeDD/dd.h @@ -1,42 +1,130 @@ -#ifndef _EFT -#define _EFT +#ifndef _MULTITYPE +#define _MULTITYPE #define xTmp(x) x##Tmp -#define add_d_d_d(a, b, c) double c; c = (a) + (b); -#define add_d_d_dd(a, b, c) double c[2]; c[0] = two_sum_mine(a, b, &(c[1])); -#define add_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) + (b); +// =========================================== ADD ======================================= +#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_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_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]; + +#define add_d_d_dd(a, b, c) double c[2]; c[0] = two_add_mine(a, b, &(c[1])); // check c[0] = (a) + (b) +#define add_ld_d_dd(a, b, c) long double xTmp(c) = (a) + (b); double c[2]; c[0] = xTmp(c); c[1] = xTmp(c) - c[0]; #define add_dd_d_dd(a, b, c) double c[2]; c_dd_add_dd_d(a, b, c); -#define add_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) + (xTmp(b)); #define add_d_dd_dd(a, b, c) double c[2]; c_dd_add_d_dd(a, b, c); -#define add_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) + (xTmp(b)); +#define add_ld_dd_dd(a, b, c) double xTmp(a)[2]; xTmp(a)[0] = a; xTmp(a)[1] = a - xTmp(a)[0]; double c[2]; c_dd_add(xTmp(a), b, c); #define add_dd_dd_dd(a, b, c) double c[2]; c_dd_add(a, b, c); +#define add_d_ld_dd(a, b, c) long double xTmp(c) = (a) + (b); double c[2]; c[0] = xTmp(c); c[1] = c - xTmp(c)[0]; +#define add_ld_ld_dd(a, b, c) long double xTmp(c) = (a) + (b); double c[2]; c[0] = xTmp(c); c[1] = c - xTmp(c)[0]; +#define add_dd_ld_dd(a, b, c) double xTmp(b)[2]; xTmp(b)[0] = b; xTmp(b)[1] = b - xTmp(b)[0]; double c[2]; c_dd_add(a, xTmp(b), c); + +#define add_d_d_ld(a, b, c) long double c = (a) + (b); +#define add_ld_d_ld(a, b, c) long double c = (a) + (b); +#define add_dd_d_ld(a, b, c) double xTmp(c)[2]; c_dd_add_dd_d(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define add_d_dd_ld(a, b, c) double xTmp(c)[2]; c_dd_add_d_dd(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define add_dd_dd_ld(a, b, c) double xTmp(c)[2]; c_dd_add(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define add_ld_dd_ld(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)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define add_d_ld_ld(a, b, c) long double c; c = (a) + (b); +#define add_ld_ld_ld(a, b, c) long double c; c = (a) + (b); +#define add_dd_ld_ld(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)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; -#define sub_d_d_d(a, b, c) double c; c = (a) - (b); -#define sub_d_d_dd(a, b, c) double c[2]; c[0] = two_diff_mine(a, b, &(c[1])); -#define sub_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) - (b); +// =========================================== 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_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_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]; + +#define sub_d_d_dd(a, b, c) double c[2]; c[0] = two_sub_mine(a, b, &(c[1])); // check c[0] = (a) - (b) +#define sub_ld_d_dd(a, b, c) long double xTmp(c) = (a) - (b); double c[2]; c[0] = xTmp(c); c[1] = xTmp(c) - c[0]; #define sub_dd_d_dd(a, b, c) double c[2]; c_dd_sub_dd_d(a, b, c); -#define sub_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) - (xTmp(b)); #define sub_d_dd_dd(a, b, c) double c[2]; c_dd_sub_d_dd(a, b, c); -#define sub_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) - (xTmp(b)); +#define sub_ld_dd_dd(a, b, c) double xTmp(a)[2]; xTmp(a)[0] = a; xTmp(a)[1] = a - xTmp(a)[0]; double c[2]; c_dd_sub(xTmp(a), b, c); #define sub_dd_dd_dd(a, b, c) double c[2]; c_dd_sub(a, b, c); +#define sub_d_ld_dd(a, b, c) long double xTmp(c) = (a) - (b); double c[2]; c[0] = xTmp(c); c[1] = c - xTmp(c)[0]; +#define sub_ld_ld_dd(a, b, c) long double xTmp(c) = (a) - (b); double c[2]; c[0] = xTmp(c); c[1] = c - xTmp(c)[0]; +#define sub_dd_ld_dd(a, b, c) double xTmp(b)[2]; xTmp(b)[0] = b; xTmp(b)[1] = b - xTmp(b)[0]; double c[2]; c_dd_sub(a, xTmp(b), c); + +#define sub_d_d_ld(a, b, c) long double c = (a) - (b); +#define sub_ld_d_ld(a, b, c) long double c = (a) - (b); +#define sub_dd_d_ld(a, b, c) double xTmp(c)[2]; c_dd_sub_dd_d(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define sub_d_dd_ld(a, b, c) double xTmp(c)[2]; c_dd_sub_d_dd(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define sub_dd_dd_ld(a, b, c) double xTmp(c)[2]; c_dd_sub(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define sub_ld_dd_ld(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)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define sub_d_ld_ld(a, b, c) long double c; c = (a) - (b); +#define sub_ld_ld_ld(a, b, c) long double c; c = (a) - (b); +#define sub_dd_ld_ld(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)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; -#define mul_d_d_d(a, b, c) double c; c = (a) * (b); -#define mul_d_d_dd(a, b, c) double c[2]; c[0] = two_prod_mine(a, b, &(c[1])); -#define mul_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) * (b); +// =========================================== 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_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_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]; + +#define mul_d_d_dd(a, b, c) double c[2]; c[0] = two_mul_mine(a, b, &(c[1])); // check c[0] = (a) * (b) +#define mul_ld_d_dd(a, b, c) long double xTmp(c) = (a) * (b); double c[2]; c[0] = xTmp(c); c[1] = xTmp(c) - c[0]; #define mul_dd_d_dd(a, b, c) double c[2]; c_dd_mul_dd_d(a, b, c); -#define mul_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) * (xTmp(b)); #define mul_d_dd_dd(a, b, c) double c[2]; c_dd_mul_d_dd(a, b, c); -#define mul_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) * (xTmp(b)); +#define mul_ld_dd_dd(a, b, c) double xTmp(a)[2]; xTmp(a)[0] = a; xTmp(a)[1] = a - xTmp(a)[0]; double c[2]; c_dd_mul(xTmp(a), b, c); #define mul_dd_dd_dd(a, b, c) double c[2]; c_dd_mul(a, b, c); +#define mul_d_ld_dd(a, b, c) long double xTmp(c) = (a) * (b); double c[2]; c[0] = xTmp(c); c[1] = c - xTmp(c)[0]; +#define mul_ld_ld_dd(a, b, c) long double xTmp(c) = (a) * (b); double c[2]; c[0] = xTmp(c); c[1] = c - xTmp(c)[0]; +#define mul_dd_ld_dd(a, b, c) double xTmp(b)[2]; xTmp(b)[0] = b; xTmp(b)[1] = b - xTmp(b)[0]; double c[2]; c_dd_mul(a, xTmp(b), c); + +#define mul_d_d_ld(a, b, c) long double c = (a) * (b); +#define mul_ld_d_ld(a, b, c) long double c = (a) * (b); +#define mul_dd_d_ld(a, b, c) double xTmp(c)[2]; c_dd_mul_dd_d(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define mul_d_dd_ld(a, b, c) double xTmp(c)[2]; c_dd_mul_d_dd(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define mul_dd_dd_ld(a, b, c) double xTmp(c)[2]; c_dd_mul(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define mul_ld_dd_ld(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)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define mul_d_ld_ld(a, b, c) long double c; c = (a) * (b); +#define mul_ld_ld_ld(a, b, c) long double c; c = (a) * (b); +#define mul_dd_ld_ld(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)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; -#define div_d_d_d(a, b, c) double c; c = (a) / (b); -#define div_d_d_dd(a, b, c) double c[2]; c[0] = div_mine(a, b, &(c[1])); -#define div_dd_d_d(a, b, c) double xTmp(a) = a[0]; double c; c = (xTmp(a)) / (b); +// =========================================== 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_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_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]; + +#define div_d_d_dd(a, b, c) double c[2]; c[0] = div_mine(a, b, &(c[1])); // check c[0] = (a) / (b) +#define div_ld_d_dd(a, b, c) long double xTmp(c) = (a) / (b); double c[2]; c[0] = xTmp(c); c[1] = xTmp(c) - c[0]; #define div_dd_d_dd(a, b, c) double c[2]; c_dd_div_dd_d(a, b, c); -#define div_d_dd_d(a, b, c) double xTmp(b) = b[0]; double c; c = (a) / (xTmp(b)); #define div_d_dd_dd(a, b, c) double c[2]; c_dd_div_d_dd(a, b, c); -#define div_dd_dd_d(a, b, c) double xTmp(a) = a[0]; double xTmp(b) = b[0]; double c; c = (xTmp(a)) / (xTmp(b)); +#define div_ld_dd_dd(a, b, c) double xTmp(a)[2]; xTmp(a)[0] = a; xTmp(a)[1] = a - xTmp(a)[0]; double c[2]; c_dd_div(xTmp(a), b, c); #define div_dd_dd_dd(a, b, c) double c[2]; c_dd_div(a, b, c); +#define div_d_ld_dd(a, b, c) long double xTmp(c) = (a) / (b); double c[2]; c[0] = xTmp(c); c[1] = c - xTmp(c)[0]; +#define div_ld_ld_dd(a, b, c) long double xTmp(c) = (a) / (b); double c[2]; c[0] = xTmp(c); c[1] = c - xTmp(c)[0]; +#define div_dd_ld_dd(a, b, c) double xTmp(b)[2]; xTmp(b)[0] = b; xTmp(b)[1] = b - xTmp(b)[0]; double c[2]; c_dd_div(a, xTmp(b), c); + +#define div_d_d_ld(a, b, c) long double c = (a) / (b); +#define div_ld_d_ld(a, b, c) long double c = (a) / (b); +#define div_dd_d_ld(a, b, c) double xTmp(c)[2]; c_dd_div_dd_d(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define div_d_dd_ld(a, b, c) double xTmp(c)[2]; c_dd_div_d_dd(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define div_dd_dd_ld(a, b, c) double xTmp(c)[2]; c_dd_div(a, b, xTmp(c)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define div_ld_dd_ld(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)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; +#define div_d_ld_ld(a, b, c) long double c; c = (a) / (b); +#define div_ld_ld_ld(a, b, c) long double c; c = (a) / (b); +#define div_dd_ld_ld(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)); long double c; c = xTmp(c)[0]; c += xTmp(c)[1]; -#endif // _EFT +#endif // _MULTITYPE diff --git a/includeDD/inline.h b/includeDD/inline.h index dc754ef..294dfc8 100644 --- a/includeDD/inline.h +++ b/includeDD/inline.h @@ -2,7 +2,7 @@ #include /* Computes fl(a+b) and err(a+b). */ -static inline double two_sum_mine(double a, double b, double *err) +static inline double two_add_mine(double a, double b, double *err) { double s = a + b; double bb = s - a; @@ -11,14 +11,14 @@ static inline double two_sum_mine(double a, double b, double *err) } /* Computes fl(a*b) and err(a*b). */ -static inline double two_prod_mine(double a, double b, double *err) +static inline double two_mul_mine(double a, double b, double *err) { double p = a * b; *err = fma(a, b, -p); return p; } -static inline double two_diff_mine(double a, double b, double *err) +static inline double two_sub_mine(double a, double b, double *err) { double s = a - b; double bb = s - a; @@ -42,8 +42,8 @@ static inline double div_mine(double a, double b, double *err) q1 = a / b; /* Compute a - q1 * b */ - p1 = two_prod_mine(q1, b, &p2); - s = two_diff_mine(a, p1, err); + p1 = two_mul_mine(q1, b, &p2); + s = two_sub_mine(a, p1, err); *err -= p2; /* get next approximation */ diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 3b5f09a..74ef580 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -3,6 +3,7 @@ #include "parserASTLY.hpp" #include +#include using std::cout; using std::endl; @@ -665,12 +666,21 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) { ofs << "\t" << "double tmp" << order << " = " << num << ";\n"; } + else if(opType == "ld") + { + ofs << "\t" << "long double tmp" << order << " = " << num << ";\n"; + } else if(opType == "DD") { ofs << "\t" << "double tmp" << order << "[2];\n"; ofs << "\t" << "tmp" << order << "[0] = " << num << ";\n"; ofs << "\t" << "tmp" << order << "[1] = 0.0;\n"; } + else + { + fprintf(stderr, "opType %s of number %lf is error\n", opType.c_str(), num); + exit(EXIT_FAILURE); + } return order; } else if(type == "Variable") @@ -681,15 +691,24 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) { ofs << "\t" << "double tmp" << order << " = " << var << ";\n"; } + else if(opType == "ld") + { + ofs << "\t" << "long double tmp" << order << " = " << var << ";\n"; + } else if(opType == "DD") { ofs << "\t" << "double tmp" << order << "[2];\n"; ofs << "\t" << "tmp" << order << "[0] = " << var << ";\n"; ofs << "\t" << "tmp" << order << "[1] = 0.0;\n"; } + else + { + fprintf(stderr, "opType %s of variable %s is error\n", opType.c_str(), var.c_str()); + exit(EXIT_FAILURE); + } return order; } - else if(type == "Call") + else if(type == "Call") // the parameters' type should be the same to the return value's type { CallExprAST *callExpr = dynamic_cast(expr.get()); auto callee = (callExpr->getCallee()); @@ -713,6 +732,10 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) { ofs << "\t" << "double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; } + else if(paramOpType == "ld") // ld to double is straight. + { + ofs << "\t" << "double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } else if(paramOpType == "DD") { ofs << "\t" << "double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << "[0];\n"; @@ -731,6 +754,38 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) ofs << "p" << paramOrders.back(); ofs << ");\n"; } + else if(opType == "ld") + { + for(size_t i = 0; i < paramOpTypes.size(); i++) + { + auto ¶mOpType = paramOpTypes.at(i); + if(paramOpType == "double") + { + ofs << "\t" << "long double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + else if(paramOpType == "ld") + { + ofs << "\t" << "long double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << ";\n"; + } + else if(paramOpType == "DD") + { + ofs << "\t" << "long double p" << paramOrders.at(i) << " = tmp" << paramOrders.at(i) << "[0];\n"; + ofs << "\t" << "p" << paramOrders.at(i) << " += tmp" << paramOrders.at(i) << "[1];\n"; + } + else + { + fprintf(stderr, "ERROR: Unknown paramOpType %s\n", paramOpType.c_str()); + exit(EXIT_FAILURE); + } + } + ofs << "\t" << "long double tmp" << order << " = " << callee << "("; + for(size_t i = 0; i < paramOrders.size() - 1; i++) + { + ofs << "p" << paramOrders.at(i) << ", "; + } + ofs << "p" << paramOrders.back(); + ofs << ");\n"; + } else if(opType == "DD") { for(size_t i = 0; i < paramOpTypes.size(); i++) @@ -742,6 +797,12 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) ofs << "\t" << "p" << paramOrders.at(i) << "[0] = tmp" << paramOrders.at(i) << ";\n"; ofs << "\t" << "p" << paramOrders.at(i) << "[1] = 0.0;\n"; } + else if(paramOpType == "ld") + { + 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] = tmp" << paramOrders.at(i) << " - p" << paramOrders.at(i) << "[0];\n"; + } else if(paramOpType == "DD") { ofs << "\t" << "double p" << paramOrders.at(i) << "[2];\n"; @@ -765,6 +826,11 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) ofs << "tmp" << order; ofs << ");\n"; } + else + { + fprintf(stderr, "ERROR: Unknown opType %s\n", opType.c_str()); + exit(EXIT_FAILURE); + } return order; } @@ -780,59 +846,16 @@ int codegenKernel(ofstream &ofs, const ast_ptr &expr) auto orderR = codegenKernel(ofs, rhs); auto opTypeL = lhs->getOpType(); auto opTypeR = rhs->getOpType(); - if(opType == "double") - { - if(opTypeL == "double" && opTypeR == "double") - { - ofs << "\t" << opStr << "_d_d_d(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; - } - else if(opTypeL == "double" && opTypeR == "DD") - { - ofs << "\t" << opStr << "_d_dd_d(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; - } - else if(opTypeL == "DD" && opTypeR == "double") - { - ofs << "\t" << opStr << "_dd_d_d(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; - } - else if(opTypeL == "DD" && opTypeR == "DD") - { - ofs << "\t" << opStr << "_dd_dd_d(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; - } - else - { - fprintf(stderr, "ERROR: unsupported type: opTypeL = %s, opTypeR = %s\n", opTypeL.c_str(), opTypeR.c_str()); - exit(EXIT_FAILURE); - } - } - else if(opType == "DD") - { - if(opTypeL == "double" && opTypeR == "double") - { - ofs << "\t" << opStr << "_d_d_dd(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; - } - else if(opTypeL == "double" && opTypeR == "DD") - { - ofs << "\t" << opStr << "_d_dd_dd(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; - } - else if(opTypeL == "DD" && opTypeR == "double") - { - ofs << "\t" << opStr << "_dd_d_dd(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; - } - else if(opTypeL == "DD" && opTypeR == "DD") - { - ofs << "\t" << opStr << "_dd_dd_dd(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; - } - else - { - fprintf(stderr, "ERROR: unsupported type: opTypeL = %s, opTypeR = %s\n", opTypeL.c_str(), opTypeR.c_str()); - exit(EXIT_FAILURE); - } - } - else - { - fprintf(stderr, "ERROR: unsupported type: opType = %s\n", opType.c_str()); - exit(EXIT_FAILURE); - } + std::map opType2funcType = { + {"double", "d"}, + {"ld", "ld"}, + {"DD", "dd"}, + }; + auto funcType = opType2funcType.at(opType); + auto funcTypeL = opType2funcType.at(opTypeL); + auto funcTypeR = opType2funcType.at(opTypeR); + ofs << "\t" << opStr << "_" << funcTypeL << "_" << funcTypeR << "_" << funcType << "(tmp" << orderL << ", tmp" << orderR << ", tmp" << order << ");\n"; + return order; } else @@ -858,14 +881,18 @@ void codegen(ast_ptr &expr, vector &vars, const string funcName, ofstrea ofs << "double" << " " << vars.back(); ofs << ") {\n"; codegenKernel(ofs, expr); - ofs << "\t" << "double result;\n"; - if(opType == "double") + if(opType == "double" || opType == "ld") { - ofs << "\t" << "result = tmp" << order << ";\n"; + ofs << "\t" << "double result = tmp" << order << ";\n"; + } + else if(opType == "DD") + { + ofs << "\t" << "double result = tmp" << order << "[0];\n"; } else { - ofs << "\t" << "result = tmp" << order << "[0];\n"; + fprintf(stderr, "ERROR: unsupported opType: opType = %s\n", opType.c_str()); + exit(EXIT_FAILURE); } ofs << "\t" << "return result;\n"; ofs << "}" << endl; @@ -903,19 +930,20 @@ int codegenWrapper(ast_ptr &expr, vector &vars, const string uniqueLabel // currentNum = currentNum >> 1; // } - int maxNum = 1 << lenOp; + vector dataTypes = {"DD", "ld", "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; - vector dataTypes = {"DD", "double"}; for(size_t i = 0; i < lenOp; i++) { auto id = opOrder[i]; - auto tmp = currentNum % 2; + auto tmp = currentNum % lenDataTypes; opTypes[id] = dataTypes[tmp]; - currentNum = currentNum >> 1; + currentNum = currentNum / lenDataTypes; } setType(expr, opTypes); -- Gitee From 435005c1b7be54aac90c95f6c3605bffaf80563d Mon Sep 17 00:00:00 2001 From: hjw Date: Wed, 8 Mar 2023 16:03:53 +0800 Subject: [PATCH 11/11] Improve the initialization step and the interval division step Details: Modify the function name: geneOriginCodeKernel -> geneExprCodeKernel;geneOriginCode -> geneExprCode. zuhe -> permuteMultiVec Implement geneHerbieCode function in the initial step. Add the pickTheBest function for optimization of the initial step. Increase the matlab program to generate upEdge and its c++ call function geneBoundaryData. Add program file such as devideUpEdgeData for interval function division under single dimension. Re-implement the getIntervalData function. The input is the upEdge data and threshold value of the expression. The function internally calls the devideUpEdgeData function to generate the interval division data of each dimension, and then calls the permuteMultiVec function (formerly known as zuhe) to exhaustively combine them, and finally outputs all the interval division results of the expression under different dimensions. Update TODO information. Optimize the format of the output information in the geneFinalCodeKernel function. Optimize the implementation of main function code and eliminate useless code. Modify the rewrite function interface to facilitate the reception of interval division data. Optimize the code implementation and remove unnecessary code in the tools.cpp file. Add the macro definition ERRORFILE to the single parameter error test file for use to control whether to generate an error file. Add the merge command to the single-parameter error test script to merge multiple error files generated by parallel tests. --- benchMarkThreshold.txt | 44 +++++ detectErrorOneFPEDParallel.sh | 14 +- include/devideUpEdgeData.hpp | 5 + include/exprAuto.hpp | 4 +- include/geneCode.hpp | 10 +- include/tools.hpp | 12 +- src/devideUpEdgeData.cpp | 325 +++++++++++++++++++++++++++++++ src/expandAST.cpp | 4 +- src/exprAuto.cpp | 41 +++- src/geneCode.cpp | 74 ++++++- src/getUpEdge.m | 201 +++++++++++++++++++ src/main.cpp | 144 ++++++++++---- src/tools.cpp | 208 ++++++++++++-------- srcTest/test1paramFPEDParallel.c | 53 ++--- 14 files changed, 969 insertions(+), 170 deletions(-) create mode 100644 benchMarkThreshold.txt create mode 100644 include/devideUpEdgeData.hpp create mode 100644 src/devideUpEdgeData.cpp create mode 100644 src/getUpEdge.m diff --git a/benchMarkThreshold.txt b/benchMarkThreshold.txt new file mode 100644 index 0000000..cd0b7e4 --- /dev/null +++ b/benchMarkThreshold.txt @@ -0,0 +1,44 @@ +0.8 +1 +1 +1 +10 +2 +2 +2.1 +1 +2 +0.5 +10 +5 +1 +1.5 +200 +1 +1 +2 +1 +2 +2 +2 +2 +1 +3 +0.6 +1.5 +1.2 +1.2 +2 +350,4 +1 +2.6 +2.5 +2.8 +3 +3 +3.2 +2.6 +2.6 +2.6 +2 +2 diff --git a/detectErrorOneFPEDParallel.sh b/detectErrorOneFPEDParallel.sh index af34d56..5d69f16 100755 --- a/detectErrorOneFPEDParallel.sh +++ b/detectErrorOneFPEDParallel.sh @@ -25,7 +25,7 @@ fi testFileName=test1paramFPEDParallel numProcs=32 -echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${prefix} ${middle} ${suffix}" +# echo "Detecting error: ${uniqueLabel} ${x0Start} ${x0End} ${x0Size} ${prefix} ${middle} ${suffix}" directory="./srcTest"/${uniqueLabel} # echo "${CC} ${testFileName}.c ${prefix}_${suffix}.c ${prefix}_mpfr.c computeULP.c -IincludeTEST -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -lmpfr -lm -O3 -o ${testFileName}.exe" ${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory}/${prefix}_mpfr.c ./srcTest/computeULP.c -IincludeTEST -IincludeDD -DEXPRESSION=${prefix}_ -DSUFFIX=${suffix} -Llibs -lTGen -lmpfr -lm -lqd -o ${testFileName}.exe @@ -33,5 +33,15 @@ ${CC} ./srcTest/${testFileName}.c ${directory}/${prefix}_${suffix}.c ${directory mpirun -n ${numProcs} ./${testFileName}.exe ${x0Start} ${x0End} ${x0Size} ${prefix}__${middle}_${suffix} ${uniqueLabel} # mv outputs/${prefix}__${middle}_${suffix}_error.txt ./outputs/${uniqueLabel}/${prefix}__${middle}_${suffix}_error.txt rm ${testFileName}.exe -echo "end detecting ${uniqueLabel}" + +# combine files +cd ./outputs/${uniqueLabel} +findWord="${prefix}__${middle}_${suffix}_sample_*.txt" +# echo "For suffix = ${suffix}, Find and combine by shell command cat: ${findWord}" +find . -name "${findWord}" | sort -h | xargs cat > sample_${uniqueLabel}_${suffix}.txt +# echo "sample file: `pwd`/sample_${uniqueLabel}_${suffix}.txt" +rm ${findWord} +cd - > /dev/null + +echo "end detecting error ${uniqueLabel}" echo diff --git a/include/devideUpEdgeData.hpp b/include/devideUpEdgeData.hpp new file mode 100644 index 0000000..2f3b486 --- /dev/null +++ b/include/devideUpEdgeData.hpp @@ -0,0 +1,5 @@ +#ifndef _DEVIDEUPEDGEDATA +#define _DEVIDEUPEDGEDATA +// void devideUpEdgeData(string upEdgeFileName, string intervalFileName, double threshold = 2, double thresholdCombine = 101); +vector devideUpEdgeData(string upEdgeFileName, double threshold = 2, double thresholdCombine = 0); +#endif \ No newline at end of file diff --git a/include/exprAuto.hpp b/include/exprAuto.hpp index 3870985..2a9208a 100644 --- a/include/exprAuto.hpp +++ b/include/exprAuto.hpp @@ -31,7 +31,7 @@ vector dealWithBinOpKernel(const ast_ptr &expr); vector dealWithBinOp(vector &exprs, const char &op); -// TODO: delete the same expr in exprs using the function 'isEqual' +// TODO: (not sure) delete the same expr in exprs using the function 'isEqual' void deleteTheSame(vector &exprs); vector dealWithCalls(const ast_ptr &expr); @@ -44,6 +44,8 @@ void sortExpr(ast_ptr &expr); vector tryRewrite(ast_ptr expr, bool addSelf = true); +string pickTheBest(string uniqueLabel, vector testSet, vector intervals, vector scales); + void geneSampleData(); vector createAll(vector &numerators, vector &denominators); diff --git a/include/geneCode.hpp b/include/geneCode.hpp index 75842a4..39e399e 100644 --- a/include/geneCode.hpp +++ b/include/geneCode.hpp @@ -19,13 +19,15 @@ vector getVariablesFromExpr(const ast_ptr &expr); bool getVariablesFromExpr(const ast_ptr &expr, vector &vars); -string geneOriginCodeKernel(string exprStr, vector vars, string uniqueLabel,string tail); +string geneExprCodeKernel(string exprStr, vector vars, string uniqueLabel,string tail); -string geneOriginCode(string exprStr, string uniqueLabel, string tail); +string geneExprCode(string exprStr, string uniqueLabel, string tail); -string geneTGenCode(string exprStr, vector vars, string uniqueLabel,string tail); +string geneTGenCode(string exprStr, vector vars, string uniqueLabel, string tail); -void geneHerbieCode(string exprstr, vector cs, string exprname,double v[], double u[]); +void geneHerbieCode(string exprstr, vector cs, string exprname, double v[], double u[]); + +string geneHerbieCode(string uniqueLabel); void geneDaisyCode(string exprStr); diff --git a/include/tools.hpp b/include/tools.hpp index 3d5fc50..6175c2f 100644 --- a/include/tools.hpp +++ b/include/tools.hpp @@ -37,16 +37,16 @@ exprInfo testError(string uniqueLabel, string suffix, double x0Start, double x0E double testPerformance(string uniqueLabel, string suffix, const vector &intervals); -void geneBoundaryData(string uniqueLabel, string suffix); +string geneBoundaryData(string uniqueLabel, string suffix); -void geneIntervalData(string uniqeuLabel, vector &intervals, vector &threholds); - -vector getIntervalData(); +vector geneIntervalData(vector upEdgeFileNames, string uniqueLabel, vector &thresholds); vector> getIntervalData(string filename); -vector rewrite(string exprSr, string uniqueLabel); +vector> getIntervalData(vector upEdgeFileNames, vector &thresholds); + +vector rewrite(string exprStr, string uniqueLabel, vector> &intervalData); -vector> zuhe(vector> vec); +vector> permuteMultiVec(vector> vec); #endif \ No newline at end of file diff --git a/src/devideUpEdgeData.cpp b/src/devideUpEdgeData.cpp new file mode 100644 index 0000000..2e5827a --- /dev/null +++ b/src/devideUpEdgeData.cpp @@ -0,0 +1,325 @@ +#include +#include +#include +#include +#include +#include +#include +#include +clock_t start; +clock_t end; + +using namespace std; +#define DEBUG +#undef DEBUG + +int read_scanf(const string &filename, const int &cols, vector &_vector, const double &ulp) { + FILE *fp = fopen(filename.c_str(), "r"); + bool flag = true; + double tmp; + if (!fp) { + cout << "File open error!\n"; + return 0; + } + while (flag) { + //将txt文本文件中的一行数据存入rowArray中,并将rowArray存入vector中 + double *rowArray = new double[cols]; // new一个double类型的动态数组 + if (EOF == fscanf(fp, "%le", &rowArray[0])) { //读取数据,存在_vector[cols]中 + break; + } + if (EOF == fscanf(fp, "%le", &rowArray[1])) { + break; + } + if (EOF == fscanf(fp, "%le", &tmp)) { + break; + } + // if (tmp < ulp) { + // tmp = ulp; + // } + rowArray[2] = tmp; + _vector.push_back(rowArray); + } + fclose(fp); + return 1; +} + +//将采样点对应的行号/序号、坐标值、误差、距离存入vector中 +void storeData(double rows, double x, double ulpErr, double distance, vector &points) { + double *point = new double[4]; + point[0] = rows; + point[1] = x; + point[2] = ulpErr; + point[3] = distance; + points.push_back(point); +} + +//打印区间数据 +void printRegime(const int &num, vector &vector, string fintervalName, string fdistanceName, string fwidthName) { + ofstream finterval, fdistance, fwidth; + finterval.open(fintervalName); + fdistance.open(fdistanceName); + fwidth.open(fwidthName); + for (int i = 0; i < num; i += 2) { + // if (vector[i][1] == vector[i + 1][1]) { + // continue; // 注释掉后,单个突出也会记录 + // } + // finterval << "lineNo: [" << vector[i][0] << ", " << vector[i + 1][0] << "]; input: " << "[" << vector[i][1] << ", " << vector[i + 1][1] << "]" << endl; + finterval << "[" << vector[i][1] << ", " << vector[i + 1][1] << "]\n"; // print intervals data to file fintervalName + // fdistance << vector[i][3] << endl; // print intervals' distance data to file "distanceTmp.txt" + // fwidth << vector[i+1][3] << endl; // print intervals' width data to file "widthTmp.txt" + } + finterval.close(); + fdistance.close(); + fwidth.close(); +} + +void ifRegimeulp(const int &num, vector &vector, std::vector &store_vector, const double &threshold) { + double distance; + double k, b, tmp; + + for (int i = 0; i < num - 1; ++i) { + // find the interval start point and set the distance value. The distance value is the distance to the previous interval + if (vector[i][2] > threshold) { + if (i == 0) { + // if 1st interval, the distance value is 0 + distance = 0; + storeData(0, vector[i][1], vector[i][2], distance, store_vector); + } else if (vector[i - 1][2] <= threshold) { + if(store_vector.size() == 0) { + distance = 0; + } else { + distance = i - store_vector.back()[0]; + } + k = (vector[i][1] - vector[i - 1][1]) / (vector[i][2] - vector[i - 1][2]); + b = vector[i][1] - k * vector[i][2]; + tmp = k * threshold + b; + // storeData(i, vector[i][1], vector[i][2], distance, store_vector); // 保存的是误差大于阈值的最左边点 + storeData(i - 0.5, tmp, threshold, distance, store_vector); // 保存的左端点连线与阈值横线的交点,这也是为何i-0.5 + } + } + // find the interval end point and set the distance value. The distance value is the width of the current interval + if (vector[i][2] > threshold) { + if (vector[i + 1][2] <= threshold) { + distance = i - store_vector.back()[0]; + k = (vector[i + 1][1] - vector[i][1]) / (vector[i + 1][2] - vector[i][2]); + b = vector[i][1] - k * vector[i][2]; + tmp = k * threshold + b; + // storeData(i, vector[i][1], vector[i][2], distance, store_vector); // 保存的是误差大于阈值的最右边点 + storeData(i + 0.5, tmp, threshold, distance, store_vector); // 保存的是最右边点与阈值横线的交点,这也是为何i+0.5 + } + else if (i == num - 2) { + // the last point's ULP error > threshold, so store the last point, that is vector[num - 1] + distance = i - store_vector.back()[0]; + storeData(num - 1, vector[num - 1][1], vector[num - 1][2], distance, store_vector); + } + } + } +} + +// 函数的轮廓线数据,即每个轮廓点对应的输入、误差,是基于扩展后的投影面误差采样数据,利用matlab的boundary函数得到的,保存在matlab_vector向量中。 +// 基于轮廓线数据,调用ifRegimeulp函数,初步得到精度优化区间的起止点信息,保存在store_vector向量中。 +// store_vector 保存的是精度优化区间的起止点信息,即其在matlab_vector向量中对应的序号、输入、误差、距离(matlab序号)。 +// store_vector 每相邻的2个元素,分别对应区间的起点和止点信息,构成一个精度优化区间。每个元素中又有3个信息,即其在matlab_vector向量中对应的序号、输入、误差。 +// output_vector 保存的是精度优化区间的起止点信息,即其在matlab_vector向量中对应的序号、输入、误差、距离(真实输入)。 +int findMinMax(vector &matlab_vector, vector &store_vector, vector &output_vector) { + int vectorNum = store_vector.size(); + double start, end, startInput, endInput, currentInput, startError, endError, distance; + double maxInput, minInput, lastmaxInput, minIdx, maxIdx; + + for (int i = 0; i < vectorNum; i += 2) { + start = store_vector[i][0]; + end = store_vector[i+1][0]; + startInput = store_vector[i][1]; + endInput = store_vector[i+1][1]; + startError = store_vector[i][2]; + endError = store_vector[i+1][2]; + minIdx = start; + maxIdx = end; + minInput = startInput; + maxInput = endInput; + + // Considering that the boundary line may protrude on both sides, the start and end points stored in 'store_vector' that intersect with the threshold are not necessarily the endpoints (leftmost and rightmost points) of the interval. + // Therefore, it is necessary to traverse the coordinate information of all points within the interval and update the endpoints of the interval to the leftmost and rightmost points found. + // 考虑到轮廓线可能向两边突出去,所以store_vector中存储的与阈值相交的起止点并不一定是区间的端点(最左最右点)。因此,需要遍历区间内所有点的坐标信息,将区间端点更新为找到的最小值和最大值。 + for (int j = ceil(start); j <= floor(end); j++) { + currentInput = matlab_vector[j][1]; + if(currentInput < minInput) { + minIdx = j; + minInput = currentInput; + } else if(currentInput > maxInput) { + maxIdx = j; + maxInput = currentInput; + } + } + // store the start point to output vector + if(minInput != startInput) { + #ifdef DEBUG + printf("\tFor No.%d: minInput != startInput. startInput: %g, minInput: %g.\n", i / 2, startInput, minInput); + #endif + startInput = matlab_vector[minIdx][1]; + startError = matlab_vector[minIdx][2]; + } + // 更新distance,即当前区间左端点到其右侧区间右端点的距离 + if(i != 0) { + distance = minInput - lastmaxInput; + } else { + distance = 0; + } + storeData(minIdx, startInput, startError, distance, output_vector); + // store the end point to output vector + if(maxInput != endInput) { + #ifdef DEBUG + printf("\tFor No.%d: maxInput != endInput. endInput: %g, maxInput: %g.\n", i / 2, endInput, maxInput); + #endif + endInput = matlab_vector[maxIdx][1]; + endError = matlab_vector[maxIdx][2]; + } + distance = endInput - startInput; + storeData(maxIdx, endInput, endError, distance, output_vector); + + // update the lastmaxInput + lastmaxInput = maxInput; + + // cout << i / 2 << ": " << minIdx << " " << minInput << " " << startInput << " " << maxIdx << " " << maxInput << " " << endInput << endl; + // cout << "No." << i/2+1 << ": the index is [" << minInput << ", " << maxInput << "], the corresponding input is [" << startInput << ", " << endInput << "]" << endl; + } + + // the output vector is from edge, a Matlab variable which stores the index, the input and the error of the sample data + // minIdx is the index of the element in the output vector. + // minInput is the index of the element in the sample data. + // startInput is the corresponding input value in the sample data. + // cout << "i: minIdx minInput startInput maxIdx maxInput endInput" << endl; + // cout << i << ": " << minIdx << " " << minInput << " " << startInput << " " << maxIdx << " " << maxInput << " " << endInput << endl; + // cout << i << ": the output vector index is " << minIdx << " " << maxIdx << endl; + // cout << i << ": the sampleData index is " << minInput << " " << maxInput << endl; + // cout << i << ": the corresponding input to the new sampleData index is " << startInput << " " << endInput << endl; + // cout << i << ": the width is " << maxInput - minInput + 1 << "\n" << endl; + + return 1; +} + +// add_zzy interval_merge +// TODO-done: Just compare the input value but not the idx of input. Because the idx is for the boundary line which is useless. +void interval_merge(vector in_vector, vector &out_vector, const double &thresholdCombine) { + if(in_vector.size() == 0) { + cout << "NOTE: interval_merge: none intervals" << endl; + return; + } + if (in_vector.size() == 2) { + double *temp = in_vector[0]; + out_vector.push_back(temp); + double *temp1 = in_vector[1]; + out_vector.push_back(temp1); + return; + } + double *temp = in_vector.front(); + out_vector.push_back(temp); + // cout << out_vector.size() << endl; + for (int i = 2; i < in_vector.size(); i += 2) { + // cout << i << " " << out_vector.size() << endl; + // if (in_vector.at(i)[3] < thresholdCombine && in_vector.at(i - 1)[3] > thresholdCombine && in_vector.at(i + 1)[3] > thresholdCombine) { + if (in_vector.at(i)[3] < thresholdCombine) { + if (i == in_vector.size() - 2) { + temp = in_vector.at(i + 1); + out_vector.push_back(temp); + } else { + continue; + } + } else { + temp = in_vector.at(i-1); + out_vector.push_back(temp); + temp = in_vector.at(i); + out_vector.push_back(temp); + // temp = in_vector.at(i+1); + // out_vector.push_back(temp); + if (i == in_vector.size() - 2) { + temp = in_vector.at(i + 1); + out_vector.push_back(temp); + } + } + } + // cout << out_vector.size() << endl; + // for (int i = 0; i < out_vector.size(); i += 2) { + // cout << "["; + // cout << out_vector.at(i)[1] << "," << out_vector.at(i + 1)[1] << "]" < extractInfo(vector &origin) { + vector destination; + for (size_t i = 0; i < origin.size(); i++) { + destination.push_back(origin[i][1]); + } + return destination; +} + +vector devideUpEdgeData(string upEdgeFileName, double threshold, double thresholdCombine) { + vector intervalData; + // thresholdCombine = 0; // TODO: set thresholdCombine + // upEdgeFileName 文件中有3列,分别是序号、输入、误差。该文件是由matlab生成,故文件中的序号从1开始,而非0。 + // matlab_vector可视为二维数组,保存的是 upEdgeFileName 中的边界点数据,包括序号、输入、误差;输出数组元素: + int columns = 3; + vector matlab_vector; + if (!read_scanf(upEdgeFileName, columns, matlab_vector, threshold)) { + fprintf(stderr, "ERROR: devideUpEdgeData: read file error\n"); + exit(EXIT_FAILURE); + } + + // 初步获取区间信息 + vector store_vector; + ifRegimeulp(matlab_vector.size(), matlab_vector, store_vector, threshold); + // printRegime(store_vector.size(), store_vector, "intervalTmp.txt", "distanceTmp.txt", "widthTmp.txt"); + + // 进一步优化区间信息 + vector output_vector; + findMinMax(matlab_vector, store_vector, output_vector); + // printRegime(output_vector.size(), output_vector, "intervalTmp_beforeCombine.txt", "distanceTmp_beforeCombine.txt", "widthTmp_beforeCombine.txt"); + + // Merge intervals that are close in distance. + vector merge_vector; + interval_merge(output_vector, merge_vector, thresholdCombine); + // printRegime(merge_vector.size(), merge_vector, intervalFileName, "distanceTmp_afterCombine.txt", "widthTmp_afterCombine.txt"); + + // generate the interval data vector + intervalData = extractInfo(merge_vector); + return intervalData; +} + +// void devideKernel(const string &filePath, const string &intervalFileName, const double &threshold, const double &thresholdCombine) { +// // filePath文件中有3列,分别是序号、输入、误差。该文件是由matlab生成,故文件中的序号从1开始,而非0。 +// // matlab_vector可视为二维数组,保存的是filePath中的边界点数据,包括序号、输入、误差;输出数组元素: +// vector matlab_vector; +// int columns = 3; +// if (!read_scanf(filePath, columns, matlab_vector, threshold)) { +// return; +// } +// // 初步获取区间信息 +// vector store_vector; +// ifRegimeulp(matlab_vector.size(), matlab_vector, store_vector, threshold); +// // printRegime(store_vector.size(), store_vector, "intervalTmp.txt", "distanceTmp.txt", "widthTmp.txt"); +// // 进一步优化区间信息 +// vector output_vector; +// findMinMax(matlab_vector, store_vector, output_vector); +// // printRegime(output_vector.size(), output_vector, "intervalTmp_beforeCombine.txt", "distanceTmp_beforeCombine.txt", "widthTmp_beforeCombine.txt"); +// // Merge intervals that are close in distance. +// vector merge_vector; +// interval_merge(output_vector, merge_vector, thresholdCombine); +// printRegime(merge_vector.size(), merge_vector, intervalFileName, "distanceTmp_afterCombine.txt", "widthTmp_afterCombine.txt"); +// } +// void devideUpEdgeData(string upEdgeFileName, string intervalFileName, double threshold, double thresholdCombine) { +// // cout << upEdgeFileName << " " << threshold << "\n"; +// // start = clock(); +// devideKernel(upEdgeFileName, intervalFileName, threshold, thresholdCombine); +// // end = clock(); +// // double endtime = (double)(end - start)/CLOCKS_PER_SEC; +// // cout << "Total time:" << endtime << endl; +// // cout << "Total time:" << endtime * 1000 << "ms" << endl; +// } \ No newline at end of file diff --git a/src/expandAST.cpp b/src/expandAST.cpp index 8406463..8a82891 100644 --- a/src/expandAST.cpp +++ b/src/expandAST.cpp @@ -135,7 +135,7 @@ ast_ptr expandExpr(const ast_ptr &expr) return exprFinal; } - else if((opL != '+') && (opR == '+'))// TODO: opL or opR is / + else if((opL != '+') && (opR == '+')) { ast_ptr &lhsR = binOpR->getLHS(); ast_ptr &rhsR = binOpR->getRHS(); @@ -156,7 +156,7 @@ ast_ptr expandExpr(const ast_ptr &expr) // { // } - // else if((opL != '/') && (opR == '/'))// TODO: opL or opR is / + // else if((opL != '/') && (opR == '/')) // { // } diff --git a/src/exprAuto.cpp b/src/exprAuto.cpp index 9762b59..3b874d9 100644 --- a/src/exprAuto.cpp +++ b/src/exprAuto.cpp @@ -1007,6 +1007,32 @@ size_t computeRandomNum(size_t sum) return randomNum; } +// for main +string pickTheBest(string uniqueLabel, vector testSet, vector intervals, vector scales) +{ + string bestExpr = "origin"; + double maxError = INFINITY; + double aveError = INFINITY; + 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); + // cout << "pickTheBest: for item No." << i << ": maxError: " << tempError.maxError << "\n"; + // cout << "pickTheBest: for item No." << i << ": aveError: " << tempError.aveError << "\n"; + + if ((tempError.maxError < maxError) || ((tempError.maxError == maxError) && (tempError.aveError < aveError))) + { + bestExpr = suffixTmp; + maxError = tempError.maxError; + aveError = tempError.aveError; + } + } + return bestExpr; +} + size_t pickTheBest(vector &items, ast_ptr &originExpr) { auto uniqueLabel = getUniqueLabel(); @@ -1016,8 +1042,8 @@ size_t pickTheBest(vector &items, ast_ptr &originExpr) getVariablesFromExpr(originExpr, vars); auto funcNameMpfr = geneMpfrCode(originExpr, uniqueLabel, vars); - string filename = "./intervalData.txt"; // TODO: get the filename from uniqueLabel - auto intervalData = getIntervalData(filename); + string filename = "./intervalData.txt"; // TODO: (useful for multi parameters) get the filename from uniqueLabel + auto intervalData = getIntervalData(filename); // TODO: (useful for multi parameters) update to getInterval(filename, dimension) size_t scale; auto intervalTmp = intervalData.at(0); auto dimension = intervalTmp.size() / 2; @@ -1044,7 +1070,7 @@ size_t pickTheBest(vector &items, ast_ptr &originExpr) // generate function code and test error string suffixTmp = suffix + std::to_string(i); - geneOriginCodeKernel(item, vars, uniqueLabel, suffixTmp); + geneExprCodeKernel(item, vars, uniqueLabel, suffixTmp); // auto timeTmp1 = std::chrono::high_resolution_clock::now(); auto tempError = testError(uniqueLabel, suffixTmp, intervalTmp, scales); // auto timeTmp2 = std::chrono::high_resolution_clock::now(); @@ -1083,6 +1109,7 @@ size_t pickTheBest(vector &items, ast_ptr &originExpr) return maxIdx; } +// be useful for multi parameters test void geneSampleData() { // static size_t callCount = 0; @@ -1092,8 +1119,8 @@ void geneSampleData() // prompt += "geneSampleData: "; cout << "geneSampleData start--------" < parameters; @@ -1366,9 +1393,9 @@ vector exprAutoWrapper(ast_ptr &expr, const std::vector &interv getVariablesFromExpr(expr, vars); auto exprStr = PrintExpression(expr); - auto funcNameOrigin = geneOriginCodeKernel(exprStr, vars, uniqueLabel, "origin"); + auto funcNameOrigin = geneExprCodeKernel(exprStr, vars, uniqueLabel, "origin"); auto expr1Str = PrintExpression(expr1); - auto funcNameSympy = geneOriginCodeKernel(expr1Str, vars, uniqueLabel, "sympy"); + auto funcNameSympy = geneExprCodeKernel(expr1Str, vars, uniqueLabel, "sympy"); auto funcNameMpfr = geneMpfrCode(exprStr, uniqueLabel, vars); // int scale = 256; diff --git a/src/geneCode.cpp b/src/geneCode.cpp index 74ef580..c792f1f 100644 --- a/src/geneCode.cpp +++ b/src/geneCode.cpp @@ -4,6 +4,7 @@ #include #include +#include using std::cout; using std::endl; @@ -116,7 +117,7 @@ bool getVariablesFromExpr(const ast_ptr &expr, vector &vars) return true; } -string geneOriginCodeKernel(string exprStr, vector vars, string uniqueLabel, string tail) +string geneExprCodeKernel(string exprStr, vector vars, string uniqueLabel, string tail) { // print input info // cout << "expression : " << exprStr << endl; @@ -153,13 +154,13 @@ string geneOriginCodeKernel(string exprStr, vector vars, string uniqueLa return funcName; } -string geneOriginCode(string exprStr, string uniqueLabel, string tail) +string geneExprCode(string exprStr, string uniqueLabel, string tail) { auto originExpr = ParseExpressionFromString(exprStr); vector vars; getVariablesFromExpr(originExpr, vars); - auto funcName = geneOriginCodeKernel(exprStr, vars, uniqueLabel, tail); + auto funcName = geneExprCodeKernel(exprStr, vars, uniqueLabel, tail); return funcName; } @@ -233,6 +234,62 @@ void geneHerbieCode(string exprstr, vector cs, string exprname, double v fout.close(); } +// TODO: not real implementation +string geneHerbieCode(string uniqueLabel) +{ + map benchmarkHerbie = { + {"Bsplines3", "-pow(x, 3.0) /6.0"}, + {"exp1x", "expm1(x) / x"}, + {"exp1x_log", "expm1(x) / x"}, + {"intro_example", "(x / (1.0 + pow(x, 3.0))) * fma(x, x, (1.0 - x))"}, + {"logexp", "log1p(exp(x))"}, + {"NMSEexample31", "(x + (1.0 - x)) / fma(pow(x, 0.25), pow(x, 0.25), sqrt((x + 1.0)))"}, + {"NMSEexample310", "log1p(-x) / log1p(x)"}, + {"NMSEexample34", "tan((x / 2.0))"}, + {"NMSEexample35", "atan2((x + (1.0- x)), (1.0+fma(sqrt(x), sqrt(x), (x * x))))"}, + {"NMSEexample36", ""}, + {"NMSEexample37", "expm1(x)"}, + {"NMSEexample38", "fma(x, log((1.0 + (1.0 / x))), log1p(x)) + -1.0"}, + {"NMSEexample39", ""}, + {"NMSEproblem331", "-1.0 / fma(x, x, x)"}, + {"NMSEproblem333", "((1.0 / (x + -1.0)) + (1.0 / (1.0 + x))) + (-2.0 / x)"}, + {"NMSEproblem334", ""}, + {"NMSEproblem336", "log1p((1.0 / x))"}, + {"NMSEproblem337", ""}, + {"NMSEproblem341", "(sin(x) / x) * (tan((x / 2.0)) / x)"}, + {"NMSEproblem343", ""}, + {"NMSEproblem344", "sqrt((1.0 + exp(x)))"}, + {"NMSEproblem345", ""}, + {"NMSEsection311", "(1.0 + expm1(x)) / expm1(x)"}, + {"predatorPrey", ""}, + {"sine", ""}, + {"sineorder3", ""}, + {"sqroot", ""}, + {"sqrt_add", ""}, + {"test05_nonlin1_r4", ""}, + {"test05_nonlin1_test2", ""}, + {"verhulst", ""}, + }; + + auto pos = benchmarkHerbie.find(uniqueLabel); + if (pos != benchmarkHerbie.end()) + { + string herbieExpr = pos->second; + if(herbieExpr != "") + { + geneExprCode(herbieExpr, uniqueLabel, "herbie"); + return herbieExpr; + } + else + { + fprintf(stderr, "ERROR: geneHerbieCode: we can not handle %s\n", uniqueLabel.c_str()); + exit(EXIT_FAILURE); + } + } + fprintf(stderr, "ERROR: geneHerbieCode: we can not handle %s\n", uniqueLabel.c_str()); + exit(EXIT_FAILURE); +} + void geneDaisyCode(string exprStr) { cout << exprStr << endl; @@ -323,11 +380,12 @@ string geneFinalCodeKernel(string exprStr, string uniqueLabel, std::vector=maxTmp); +meanTmp = mean(sampleData(:,2)); +upperTmp = (maxTmp + meanTmp) / 10; +domainTmp = 0.01; +leftTmp = int64(max(1, maxIndex - lenTmp * domainTmp * 0.5)); +rightTmp = int64(min(lenTmp, maxIndex + lenTmp * domainTmp * 0.5)); + +for j = 1:1 % 右端点需要更正为maxIndex的长度 + leftTmp(j) = int64(max(1, maxIndex(j) - lenTmp * domainTmp * 0.5)); + rightTmp(j) = int64(min(lenTmp, maxIndex(j) + lenTmp * domainTmp * 0.5)); + localTmp = find(sampleData(leftTmp(j):rightTmp(j),2) > upperTmp); + wholeTmp = find(sampleData(:,2) > upperTmp); + rateTmp = length(localTmp) / length(wholeTmp); + edgeIndex = boundary(sampleData(:,1), sampleData(:,2), 1.0); + edge = [edgeIndex, sampleData(edgeIndex,1), sampleData(edgeIndex,2)]; + + % simple way + % upEdgeIndex = edge(:,3)>=2; + % upEdge = edge(upEdgeIndex,:); + + % upEdge: tradional way + edge = flipud(edge); % 水平轴上下翻转数组 + if isempty(edge) + fprintf("\tedge is empty!\n"); + break; + end + upEdgeStart = 1; + upEdgeEnd = length(edge); + edgeTmp = edge; + thresholdTrash = 5; + minEdgeInput = min(edgeTmp(:,2)); % 记录的是误差对应的输入 + maxEdgeInput = max(edgeTmp(:,2)); % 记录的是误差对应的输入 + + threshold = 2; + edgeTmp(edge(:,3) thresholdTrash) + upEdgeStart = max(1,k-1-thresholdTrash); + break + end + else + trash = 0; + end + end + % ready for upEdge's tail + trash = 0; + for k = length(edgeTmp):-1:1 + if(edgeTmp(k,2) == maxEdgeInput) + upEdgeEnd = min(k, length(edgeTmp)); + break + end + if(edgeTmp(k,end) ~= threshold) + trash = trash + 1; + if(trash > thresholdTrash) + upEdgeEnd = min(k+1+thresholdTrash, length(edgeTmp)); + break + end + else + trash = 0; + end + end + % after getting head & tail, we get upEdge + upEdge = edge(upEdgeStart:upEdgeEnd,:); % upEdge是保留了上半段轮廓线中小于阈值的部分 + + if rateTmp > 0.5 % 做判断是因为rateTmp大于0.5即说明其图形unstable,出现了畸变 + % fprintf("%s is unstable, rate = %g, maxError = %g\n", sampleFileName, rateTmp, maxTmp); + % draw pic and save pic + % figure(1); + % scatter(sampleData(:,1), sampleData(:,2), '.'); + % hold on; plot(edge(:,2), edge(:,3), '-r', 'LineWidth', 1); hold off; + % set(gca, 'Fontname', 'Times newman', 'Fontsize', 55); + % nameTmp = strcat("unstable_scatterEdge_", sampleFileName); + % % title(nameTmp, 'Interpreter', 'none'); + % % grid on; + % img =gcf; print(img, '-djpeg', '-r100', nameTmp); + + % update boundary error to [2, 10]。这一段其实可以放到前边去 + radio = (maxTmp - 2) / 8; + indexTmp = sampleData(:,2) >= 2; + sampleData(indexTmp, 2) = (sampleData(indexTmp,2) - 2) / radio + 2; + maxTmp = max(sampleData(indexTmp,2)); + edgeIndex = boundary(sampleData(:,1), sampleData(:,2), 1.0); + edge = [edgeIndex, sampleData(edgeIndex,1), sampleData(edgeIndex,2)]; + + % upEdge: tradional way + edge = flipud(edge); + if isempty(edge) + fprintf("\tedge is empty!\n"); + break; + end + upEdgeStart = 1; + upEdgeEnd = length(edge); + edgeTmp = edge; + thresholdTrash = 5; + minEdgeInput = min(edgeTmp(:,2)); + maxEdgeInput = max(edgeTmp(:,2)); + + threshold = 2; + edgeTmp(edge(:,3) thresholdTrash) + upEdgeStart = max(1,k-1-thresholdTrash); + break + end + else + trash = 0; + end + end + % tail + trash = 0; + for k = length(edgeTmp):-1:1 + if(edgeTmp(k,2) == maxEdgeInput) + upEdgeEnd = min(k, length(edgeTmp)); + break + end + if(edgeTmp(k,end) ~= threshold) + trash = trash + 1; + if(trash > thresholdTrash) + upEdgeEnd = min(k+1+thresholdTrash, length(edgeTmp)); + break + end + else + trash = 0; + end + end + % after head & tail + upEdge = edge(upEdgeStart:upEdgeEnd,:); % upEdge是保留了上半段轮廓线中小于阈值的部分 + + % draw pic and save pic + % figure(1); + % scatter(sampleData(:,1), sampleData(:,2), '.'); + % hold on; plot(upEdge(:,2), upEdge(:,3), '-r', 'LineWidth', 1); hold off; + % set(gca, 'Fontname', 'Times newman', 'Fontsize', 55); + % nameTmp = strcat("unstable_1_scatterEdge_", sampleFileName); + % % title(nameTmp, 'Interpreter', 'none'); + % % grid on; + % img =gcf; print(img, '-djpeg', '-r100', nameTmp); + else % do nothing, just for debug + % fprintf("%s is stable, rate = %g, maxError = %g\n", sampleFileName, rateTmp, maxTmp); + % draw pic and save pic + % figure(1); + % scatter(sampleData(:,1), sampleData(:,2), '.'); + % hold on; plot(upEdge(:,2), upEdge(:,3), '-r', 'LineWidth', 1); hold off; + % set(gca, 'Fontname', 'Times newman', 'Fontsize', 55); + % nameTmp = strcat("stable_scatterEdge_", sampleFileName); + % % title(nameTmp, 'Interpreter', 'none'); + % % grid on; + % img =gcf; print(img, '-djpeg', '-r100', nameTmp); + end + + % save upEdge data to file whose format like upEdge_Bspline3.txt + if(~isempty(edge)) + % fprintf("\tupEdgeFileName: %s with %d lines\n", upEdgeFileName, length(upEdge)); + save(upEdgeFileName, 'upEdge', '-ascii', '-double'); % the 2nd parameter mean the data to save to file + else + fprintf("\tedge is empty\n"); + end + + % if(length(maxIndex) > 1) + % fprintf("\tleftTmp(%d) = %d, rightTmp(%d) = %d\n", j, leftTmp(j), j, rightTmp(j)); + % end +end +if maxTmp > 2 + indexTmp = sampleData(:,2) >= 2; + meanTmp = mean(sampleData(indexTmp, 2)); +else + meanTmp = mean(sampleData(:, 2)); +end + +% compute the threshold for deviding intervals +% thresholdTmp = (maxTmp + meanTmp) / 2; +% fprintf("%s: max = %g, average = %g, threshold = %d\n", sampleFileName, maxTmp, meanTmp, thresholdTmp); + +% 去除误差小于0.5的点,然后绘图。感觉区别不大。下面这段代码就是示例代码,仅仅是绘图,并没有保存数据或图片 +% indexTmp = sampleData(:,2)>0.5; +% sampleDataTmp1 = (sampleDataTmp(indexTmp,:)); +% edgeIndex = boundary(sampleDataTmp1(:,1), sampleDataTmp1(:,2), 1.0); +% edge = [edgeIndex, sampleDataTmp1(edgeIndex,1), sampleDataTmp1(edgeIndex,2)]; +% figure(2); +% scatter(sampleDataTmp1(:,1), sampleDataTmp1(:,2), '.'); +% hold on; plot(edge(:,2), edge(:,3), '-r', 'LineWidth', 1); hold off; diff --git a/src/main.cpp b/src/main.cpp index 1008feb..a8a622a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,6 +22,41 @@ using std::vector; #ifndef DOUBLE_PRECISION #define DOUBLE_PRECISION 17 #endif + +map> benchmarkThresholds = { + {"Bsplines3", {0.8}}, + {"exp1x", {1}}, + {"exp1x_log", {1}}, + {"intro_example", {1}}, + {"logexp", {10}}, + {"NMSEexample31", {2}}, + {"NMSEexample310", {2}}, + {"NMSEexample34", {2.1}}, + {"NMSEexample35", {1}}, + {"NMSEexample36", {2}}, + {"NMSEexample37", {0.5}}, + {"NMSEexample38", {10}}, + {"NMSEexample39", {5}}, + {"NMSEproblem331", {1}}, + {"NMSEproblem333", {1.5}}, + {"NMSEproblem334", {200}}, + {"NMSEproblem336", {1}}, + {"NMSEproblem337", {1}}, + {"NMSEproblem341", {2}}, + {"NMSEproblem343", {1}}, + {"NMSEproblem344", {2}}, + {"NMSEproblem345", {2}}, + {"NMSEsection311", {2}}, + {"predatorPrey", {2}}, + {"sine", {1}}, + {"sineorder3", {3}}, + {"sqroot", {0.6}}, + {"sqrt_add", {1.5}}, + {"test05_nonlin1_r4", {1.2}}, + {"test05_nonlin1_test2", {1.2}}, + {"verhulst", {2}}, +}; + //===----------------------------------------------------------------------===// // Main driver code. //===----------------------------------------------------------------------===// @@ -46,7 +81,7 @@ int main() cout << "open tmpResult.txt failed"; exit(EXIT_FAILURE); } - int getlineCount = 0; + // int getlineCount = 0; fprintf(stderr, GREEN "ready> " RESET); string inputStr = ""; @@ -54,9 +89,9 @@ int main() while (getline(cin, inputStr)) // read line from keyboard input { // only rewrite - getlineCount++; - if (getlineCount == 35 || getlineCount == 36 || getlineCount < 0) - continue; + // getlineCount++; + // if (getlineCount == 35 || getlineCount == 36 || getlineCount < 0) + // continue; if (inputStr == "exit;" || inputStr == "quit;" || inputStr == "exit" || inputStr == "quit") { @@ -79,11 +114,16 @@ int main() auto pos = benchMarkData.find(inputStr); bool isBenchMark = false; string name; + vector thresholds; if (pos != benchMarkData.end()) { name = inputStr; inputStr = pos->second.begin()->first; - cout << inputStr << endl; + cout << "expression := " << inputStr << endl; + + thresholds = benchmarkThresholds.at(name); + // fmt::print("thresholds := {}\n", thresholds); + isBenchMark = true; } @@ -93,8 +133,8 @@ int main() auto originExpr = ParseExpressionFromString(inputStr); vector vars; getVariablesFromExpr(originExpr, vars); + int dimension = vars.size(); // cout << vars.size() << endl; - fprintf(stderr, GREEN "interval> " RESET); // after input completed, start timing @@ -114,20 +154,21 @@ int main() } // For temporary use only . It will be replaced by geneBoundaryData and geneIntervalData - ofstream ofs; - ofs.open("intervalData.txt", ios::out); - for (size_t i = 0; i < intervals.size(); i++) - { - if (i == intervals.size() - 1) - { - ofs << intervals.at(i); - } - else - { - ofs << intervals.at(i) << " "; - } - } - ofs.close(); + // ofstream ofs; + // ofs.open("intervalData.txt", ios::out); + // TODO-DONE: (but no need do it): judge if intervals.size() == dimension + // for (int i = 0; i < dimension; i++) + // { + // if (i == dimension - 1) + // { + // ofs << intervals.at(i); + // } + // else + // { + // ofs << intervals.at(i) << " "; + // } + // } + // ofs.close(); // Read scale from keyboard // fprintf(stderr, GREEN "scale> " RESET); @@ -137,15 +178,15 @@ int main() // Default scale setting according to the variables' size int sampleScale; - if (vars.size() == 1) + if (dimension == 1) { sampleScale = 500000; } - else if (vars.size() == 2) + else if (dimension == 2) { sampleScale = 1024; } - else if (vars.size() == 3) + else if (dimension == 3) { sampleScale = 256; } @@ -154,7 +195,7 @@ int main() sampleScale = 10; } vector scales; - for (size_t i = 0; i < vars.size(); i++) + for (int i = 0; i < dimension; i++) { scales.push_back(sampleScale); } @@ -171,43 +212,68 @@ int main() string mkdirCommand = "mkdir -p srcTest/" + uniqueLabel + " outputs/" + uniqueLabel; system(mkdirCommand.c_str()); - auto funcNameOrigin = geneOriginCodeKernel(inputStr, vars, uniqueLabel, "origin"); - // auto funcNameOrigin = geneOriginCode(inputStr, uniqueLabel, "origin"); + auto funcNameOrigin = geneExprCodeKernel(inputStr, vars, uniqueLabel, "origin"); + // auto funcNameOrigin = geneExprCode(inputStr, uniqueLabel, "origin"); // auto funcNameHerbie = geneHerbieCode(inputStr, uniqueLabel, "herbie"); + auto funcNameHerbie = geneHerbieCode(uniqueLabel); // auto funcNameDaisy = geneDaisyCode(inputStr, uniqueLabel, "daisy"); auto funcNameMpfr = geneMpfrCode(inputStr, uniqueLabel, vars); - // TODO: pick the best from origin, herbie, daisy + // TODO: improve pickTheBest to support more suffix // pickTheBest(uniqueLabel, 0, 1, 100); - - cout << BLUE << "main: start testError for origin: " << inputStr << RESET << endl; + vector suffixSet = {"origin", "herbie"}; + auto suffix = pickTheBest(uniqueLabel, suffixSet, intervals, scales); + if (suffix == "origin") + { + inputStr = funcNameOrigin; + } + else if (suffix == "herbie") + { + inputStr = funcNameHerbie; + } + else + { + fprintf(stderr, "ERROR: main: we do not support the suffix %s now\n", suffix.c_str()); + exit(EXIT_FAILURE); + } + // cout << BLUE << "main: start testError for origin: " << inputStr << RESET << endl; // auto timeTmp1 = std::chrono::high_resolution_clock::now(); // geneSampleData(); - auto infoTmp = testError(uniqueLabel, "origin", intervals, scales); + // auto infoTmp = testError(uniqueLabel, "origin", intervals, scales); // auto timeTmp2 = std::chrono::high_resolution_clock::now(); - cout << BLUE << "main: ending testError for origin: " << inputStr << RESET << endl; + // cout << BLUE << "main: ending testError for origin: " << inputStr << RESET << endl; // std::chrono::duration testError_seconds = timeTmp2 - timeTmp1; // cout << BLUE << "testError time: " << testError_seconds.count() << "s" << RESET << endl; // fprintf(stderr, GREEN "ready> " RESET); // continue; - - geneBoundaryData(uniqueLabel, "origin"); // matlab - - vector intervalsTemp; - vector threholdsTemp; - geneIntervalData(uniqueLabel, intervalsTemp, threholdsTemp); + + // auto infoTmp = testError(uniqueLabel, "origin", intervals, scales); // TODO-done: 完善origin误差测试 // WHY do it? Because no pickTheBest before. So, have to use testError to get the sample data. + auto upEdgeFileName = geneBoundaryData(uniqueLabel, suffix); // sample data == matlab ==> upEdge data // TODO: support multiple dimension + cout << "upEdgeFileName: " << upEdgeFileName << "\n"; + vector upEdgeFileNames; + upEdgeFileNames.push_back(upEdgeFileName); + auto intervalData = getIntervalData(upEdgeFileNames, thresholds); + fmt::print("after regime, we have {} intervals: {}\n", intervalData.size(), intervalData); + // fprintf(stderr, GREEN "ready> " RESET); + // continue; cout << "=-=-=-=-=-=-=-=-=-=-=-=-= rewrite start =-=-=-=-=-=-=-=-=-=-=-=-=" << endl; // auto timeTmp3 = std::chrono::high_resolution_clock::now(); - auto exprInfoVector = rewrite(inputStr, uniqueLabel); + auto exprInfoVector = rewrite(inputStr, uniqueLabel, intervalData); // auto timeTmp4 = std::chrono::high_resolution_clock::now(); // std::chrono::duration rewrite_seconds = timeTmp4 - timeTmp3; // cout << BLUE << "rewrite time: " << rewrite_seconds.count() << " s" << RESET << endl; // fprintf(stderr, GREEN "ready> " RESET); // continue; cout << "=-=-=-=-=-=-=-=-=-=-=-=-= rewrite end =-=-=-=-=-=-=-=-=-=-=-=-=" << endl; + auto funcNameFinal = geneFinalCodeKernel(inputStr, uniqueLabel, exprInfoVector, vars); + cout << "=-=-=-=-=-=-=-=-=-=-=-=-= test final code's error and performance start =-=-=-=-=-=-=-=-=-=-=-=-=\n"; + auto infoTmp = testError(uniqueLabel, "final", intervals, scales); + infoTmp.performance = testPerformance(uniqueLabel, "final", intervals); + cout << "performance: " << infoTmp.performance << "\n\n"; + cout << "=-=-=-=-=-=-=-=-=-=-=-=-= test final code's error and performance end =-=-=-=-=-=-=-=-=-=-=-=-=\n"; // write the results to file // auto results = exprAutoWrapper(inputStr, intervals, scales); @@ -233,7 +299,7 @@ int main() // continue; // write the results to file - fout << "-------------------------------------NO." << getlineCount << ": " << inputStr << endl; + // fout << "-------------------------------------NO." << getlineCount << ": " << inputStr << endl; for (size_t i = 0; i < results.size(); i++) { auto &result = results.at(i); diff --git a/src/tools.cpp b/src/tools.cpp index c8c435a..6b2b892 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -4,6 +4,7 @@ #include "basic.hpp" #include "geneCode.hpp" #include "color.hpp" +#include "devideUpEdgeData.hpp" #include #include #include @@ -18,6 +19,7 @@ #include #include #include +#include using std::cout; using std::endl; @@ -400,7 +402,9 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte } commandStr = commandStr + " " + prefix + " " + middle + " " + suffix; - cout << "fileNameKernel: " << fileNameKernel << "\ncommand: " << commandStr << "\ntestName: " << testName << endl; + // cout << "fileNameKernel: " << fileNameKernel << "\n"; + cout << "command: " << commandStr << "\n"; + // cout << "testName: " << testName << "\n"; char command[200] = {0}; strcat(command, commandStr.c_str()); system(command); @@ -408,7 +412,7 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte std::ifstream ifs(testName, std::ios::in); if(ifs.eof()) { - std::cout << "is null" << std::endl; + cout << "is null" << "\n"; ifs.close(); tempError.intervals = intervals; @@ -440,7 +444,7 @@ exprInfo testError(string uniqueLabel, string suffix, const vector &inte } else { - fprintf(stderr, "WRONG: rewrite: the intervalTmp's dimension is %ld, which we don't support now.\n", size); + fprintf(stderr, "WRONG: testError: the intervalTmp's dimension is %ld, which we don't support now.\n", size); exit(EXIT_FAILURE); } @@ -468,20 +472,21 @@ double testPerformance(string uniqueLabel, string suffix, const vector & { commandStr = commandStr + " " + param; } - commandStr = "cd srcTest; " + commandStr + "; cd -;"; - cout << "fileNameKernel: " << fileNameKernel << "\ncommand: " << commandStr << endl; + commandStr = "cd srcTest; " + commandStr + "; cd - > /dev/null;"; + // cout << "fileNameKernel: " << fileNameKernel << "\n"; + cout << "command: " << commandStr << "\n"; char command[200] = {0}; strcat(command, commandStr.c_str()); system(command); } else if (size == 4) { - fprintf(stderr, "WRONG: rewrite: the intervalTmp's dimension is %ld, which we don't support now.\n", size); + fprintf(stderr, "WRONG: testPerformance: the intervalTmp's dimension is %ld, which we don't support now.\n", size); exit(EXIT_FAILURE); } else { - fprintf(stderr, "WRONG: rewrite: the intervalTmp's dimension is %ld, which we don't support now.\n", size); + fprintf(stderr, "WRONG: testPerformance: the intervalTmp's dimension is %ld, which we don't support now.\n", size); exit(EXIT_FAILURE); } @@ -507,46 +512,96 @@ double testPerformance(string uniqueLabel, string suffix, const vector & return tempCycles; } -// TODO: implement -// call matlab to generate the boundaryData to file -void geneBoundaryData(string uniqueLabel, string suffix) +// TODO: support multiple dimension +// call matlab to generate the upEdgeData to file +string geneBoundaryData(string uniqueLabel, string suffix) { - suffix = "origin"; - string filename = "./outputs/" + uniqueLabel + "/expr_" + uniqueLabel + "_" + suffix + "_boudary.txt"; - std::ofstream ofs; - ofs.open(filename, std::ios::out); - ofs << "123" << std::endl; - ofs.close(); - std::cout << "generate boundaryData file:" << filename << std::endl; -} - -// TODO: improve -// generate the interval info to file -void geneIntervalData(string uniqueLabel, vector &intervals, vector &threholds) -{ - // filename = "expr_" + uniqueLabel + "_interval.txt"; - for (size_t j = 1; j < threholds.size(); j++) + char *currentPath; + if((currentPath = getcwd(NULL, 0)) == NULL) { - intervals.push_back(to_string(j * 2)); - intervals.push_back(to_string(j * 2 + 1)); - threholds.push_back(j + 0.0002); - } - for (size_t i = 0; i < threholds.size(); i++) - { - string fileName; - string prefix = "./outputs/" + uniqueLabel + "/expr_" + uniqueLabel; - string middle = "_" + intervals.at(i * 2) + "_" + intervals.at(i * 2 + 1) + "_" + to_string(threholds.at(i)); - string suffix = "_interval.txt"; - fileName = prefix + middle + suffix; - std::ofstream ofs; - ofs.open(fileName, std::ios::out); - ofs << "123" << std::endl; - ofs.close(); - std::cout << "generate boudaryDate file:" << fileName << std::endl; + perror("getcwd error"); } + string currentPathStr(currentPath); + string outputFilesPath = currentPathStr + "/outputs/" + uniqueLabel + "/"; + string sampleFileName = outputFilesPath + "sample_" + uniqueLabel + "_" + suffix + ".txt"; + string upEdgeFileName = outputFilesPath + "upEdge_" + uniqueLabel + "_" + suffix + ".txt"; + string matlabExecutable = "/home/xyy/helloBro/softwares/matlab/R2020a/bin/matlab"; // set to your own matlab executable + string matlabCommands = " -batch \"sampleFileName=\'" + sampleFileName + "\'; upEdgeFileName = \'" + upEdgeFileName + "\'; run " + currentPathStr + "/src/getUpEdge\""; // DO NOT need to add the suffix ".m" for matlab file! + string commandStr = matlabExecutable + matlabCommands; + cout << "Matlab command: " << commandStr << "\n"; + // cout << "length of commandStr: " << commandStr.size() << "\n"; + char command[512] = {0}; + strcat(command, commandStr.c_str()); + system(command); + free(currentPath); + // std::cout << "generate upEdge file:" << upEdgeFileName << std::endl; + + return upEdgeFileName; } -//生成区间数据 +// string geneIntervalData1D(string upEdgeFileName, string uniqueLabel, double threshold) // generate the interval info to file at the target dimension +// { +// // init +// double thresholdCombine = 101; +// string prefix = "./outputs/" + uniqueLabel + "/expr_" + uniqueLabel; +// string suffix = "_interval.txt"; +// // call devideUpEdgeData for each dimension +// string middle = "_" + to_string(threshold); +// string intervalFileName = prefix + middle + suffix; +// cout << "generate interval file:" << intervalFileName << endl; +// devideUpEdgeData(upEdgeFileName, intervalFileName, threshold, thresholdCombine); +// return intervalFileName; +// } + +// vector getIntervalData1D(string filename) // read filename to get vector +// { +// vector intervalData; +// std::ifstream ifs; +// ifs.open(filename, std::ios::in); +// if (!ifs.is_open()) +// { +// std::cout << "ERROR: getIntervalData: fail to open " << filename << std::endl; +// exit(EXIT_FAILURE); +// } +// string currentLine; +// while (getline(ifs, currentLine, '\n')) +// { +// // cout << currentLine << endl; +// std::istringstream iss(currentLine); +// string tmp; +// while(getline(iss, tmp, ' ')) +// { +// intervalData.push_back(atof(tmp.c_str())); +// } +// } +// ifs.close(); +// return intervalData; +// } + +// vector geneIntervalData(vector upEdgeFileNames, string uniqueLabel, vector &thresholds) // according the upEdgeFile data, generate the interval info into file +// { +// // init +// double thresholdCombine = 101; +// vector intervalFilenames; +// string prefix = "./outputs/" + uniqueLabel + "/expr_" + uniqueLabel; +// string suffix = "_interval.txt"; +// // call devideUpEdgeData for each dimension +// for (size_t i = 0; i < thresholds.size(); i++) +// { +// auto &upEdgeFileName = upEdgeFileNames.at(i); +// auto &threshold = thresholds.at(i); +// string middle = "_" + to_string(threshold); +// string intervalFileName = prefix + middle + suffix; +// cout << "generate interval file:" << intervalFileName << endl; +// intervalFilenames.push_back(intervalFileName); +// devideUpEdgeData(upEdgeFileName, intervalFileName, threshold, thresholdCombine); +// } +// return intervalFilenames; +// } + +// may useless, ready to comment it +// read filename to get vector>. +// A line is a vector. lines are vector<~> (~ is vector) vector> getIntervalData(string filename) { vector> intervalData; @@ -558,52 +613,48 @@ vector> getIntervalData(string filename) exit(EXIT_FAILURE); } - string buf; - while (getline(ifs, buf)) + string currentLine; + while (getline(ifs, currentLine, '\n')) { + // cout << currentLine << endl; vector lineData; - // cout << buf << endl; - int flag = 1; - vector index; - for (size_t i = 0; i < buf.length(); i++) + std::istringstream iss(currentLine); + string tmp; + while(getline(iss, tmp, ' ')) { - if (buf[i] == ' ') - { - flag += 1; - index.push_back(i); - } + lineData.push_back(atof(tmp.c_str())); } - for (size_t i = 0; i < index.size(); i++) - { - if (i == 0) - { - string data = buf.substr(0, index.at(i)); - lineData.push_back(atof(data.c_str())); - } - else - { - int n = index.at(i) - index.at(i - 1) - 1; - string data = buf.substr(index.at(i - 1) + 1, n); - lineData.push_back(atof(data.c_str())); - } - } - int pos = index.back() + 1; - int n = buf.length() - 1 - index.at(index.size() - 1); - string last = buf.substr(pos, n); - lineData.push_back(atof(last.c_str())); intervalData.push_back(lineData); } ifs.close(); return intervalData; } -// call exprAuto to rewrite the input expression -vector rewrite(string exprStr, string uniqueLabel) +// according to the corresponding intervalData file in each dimension, generate the interval data, and then generate all permutation of all dimensions. +vector> getIntervalData(vector upEdgeFileNames, vector &thresholds) { - // string filename = "expr_" + uniqueLabel + "_interval.txt"; - string filename = "./intervalData.txt"; // TODO: get the filename from uniqueLabel + vector> intervalDataMultiDim; + int dimension = thresholds.size(); + // auto thresholdCombine = 0; + for (int i = 0; i < dimension; i++) // iterate all the dimensions + { + // call devideUpEdgeData for each dimension: matlab upEdge ==> interval vector + auto &upEdgeFileName = upEdgeFileNames.at(i); + auto &threshold = thresholds.at(i); + auto intervalData1D = devideUpEdgeData(upEdgeFileName, threshold); // TODO: add the parameter thresholdCombine + // push_back interval vector + intervalDataMultiDim.push_back(intervalData1D); + } + // call permuteMultiVec to get all permutation + auto results = permuteMultiVec(intervalDataMultiDim); + return results; +} - auto intervalData = getIntervalData(filename); +// call exprAuto to rewrite the input expression +vector rewrite(string exprStr, string uniqueLabel, vector> &intervalData) +{ + // string filename = "expr_" + uniqueLabel + "_interval.txt"; // useless + // string filename = "./intervalData.txt"; // TODO-done: get the filename from uniqueLabel. Now we get intervalData from input parameters directly. auto tempExpr = ParseExpressionFromString(exprStr); @@ -649,7 +700,7 @@ vector rewrite(string exprStr, string uniqueLabel) // generate function code and test error string suffixTmp = suffix + std::to_string(j); - geneOriginCode(newExpr, uniqueLabel, suffixTmp); + geneExprCode(newExpr, uniqueLabel, suffixTmp); // auto timeTmp1 = std::chrono::high_resolution_clock::now(); auto tempError = testError(uniqueLabel, suffixTmp, intervalTmp, scales); // auto timeTmp2 = std::chrono::high_resolution_clock::now(); @@ -696,7 +747,8 @@ vector rewrite(string exprStr, string uniqueLabel) return exprInfoVector; } -vector> zuhe(vector> vec) +// permute multiple vector +vector> permuteMultiVec (vector> vec) { vector> suzu; size_t row = vec.size(); diff --git a/srcTest/test1paramFPEDParallel.c b/srcTest/test1paramFPEDParallel.c index 01627c5..1b8c18a 100644 --- a/srcTest/test1paramFPEDParallel.c +++ b/srcTest/test1paramFPEDParallel.c @@ -21,6 +21,7 @@ struct errorInfo { #define TESTNUMX0 500000 // #define FP // #define DEBUG +#define ERRORFILE double EXPRESSIONMPFR(double, mpfr_t); double EXPRESSIONMINE(double); @@ -39,7 +40,7 @@ int computeResult1param(double x0, mpfr_t mpfrResult) return status; } -struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int testNumX0, 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) { DL maxInputX0; int i0; // int flag; @@ -49,24 +50,26 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int mpfr_t mpfrOrcle, mpfrResult; mpfr_inits2(PRECISION, mpfrOrcle, mpfrResult, (mpfr_ptr) 0); - // file - // char *directory = "outputs"; - // char *suffix = "sample"; - // char *fileNameSample; - // FILE *f; - // fileNameSample = (char *) calloc(strlen(fileNameKernel) + strlen(suffix) + 128, sizeof(char)); - // sprintf(fileNameSample, "./%s/%s_%s_%d.txt", directory, fileNameKernel, suffix, myid); - // // printf("%s\n", fileNameSample); - // if ((f = fopen(fileNameSample, "w")) == NULL) { - // printf("Error opening file %s.\n", fileNameSample); - // exit(0); - // } + // write error data to file + #ifdef ERRORFILE + char *directory = "./outputs"; + char *suffix = "sample"; + char *fileNameSample; + FILE *f; + fileNameSample = (char *) calloc(strlen(directory) + strlen(uniqueLabel) + strlen(fileNameKernel) + strlen(suffix) + 128, sizeof(char)); + sprintf(fileNameSample, "%s/%s/%s_%s_%02d.txt", directory, uniqueLabel, fileNameKernel, suffix, myid); + // printf("%s\n", fileNameSample); + if ((f = fopen(fileNameSample, "w")) == NULL) { + printf("Error opening file %s.\n", fileNameSample); + exit(0); + } // printf("test expression: %s\n", STR2(EXPRESSION)); // printf("x0Start : %lg 0x%016lx\nx0End : %lg 0x%016lx\n", x0Start.d, x0Start.l, x0End.d, x0End.l); // fprintf(f, "x0Start : %lg 0x%016lx\nx0End : %lg 0x%016lx\n", x0Start.d, x0Start.l, x0End.d, x0End.l); // fprintf(f, "\nxInput\t\txInput (Hex)\t\tresult\t\tresult (Hex)\t\torcle\t\torcle (Hex)\t\tulp error\n"); // printf("testNum : %lu 0x%lx\n", testNumX0, testNumX0); + #endif // loop boundary lenX0 = x0End.d - x0Start.d; @@ -96,7 +99,9 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int // printf("happen to NaN or inf\n"); // exit(1); // } - // fprintf(f, "%le\t%e\n", x0, reUlp); + #ifdef ERRORFILE + fprintf(f, "%le\t%le\n", x0, reUlp); + #endif if (isnormal(reUlp) != 0) { sumError += reUlp; @@ -107,7 +112,6 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int } } } - // fprintf(f, "\n"); // aveReUlp = aveReUlp / (testNumX0); // if(flag == 1) { // printf("all error are 0!!\n"); @@ -116,10 +120,13 @@ struct errorInfo test1FPEDparamParallel(DL x0Start, DL x0End, unsigned long int // printf("%le\t%le\n", aveReUlp, maxReUlp); // printf("\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveReUlp, maxInputX0.l, maxInputX0.d, maxReUlp); // } + #ifdef ERRORFILE + // fprintf(f, "\n"); // clear - // fclose(f); - // free(fileNameSample); + fclose(f); + free(fileNameSample); + #endif mpfr_clears(mpfrOrcle, mpfrResult, (mpfr_ptr) 0); struct errorInfo err; err.sumError = sumError; @@ -178,10 +185,10 @@ int main(int argc, char **argv) { printf("Usage: \tthe fixed inputs [%g %g %lu] will be used\n", x0Start.d, x0End.d, testNumX0); } - if(myid == 0) { - printf("\n---------------------------------------------------start test1paramFPEDParallel\n"); - printf("Parameters: x0Start: %lg, x0End: %lg, testNumX0 = %lu, fileNameKernel: %s\n", x0Start.d, x0End.d, testNumX0, fileNameKernel); - } + // if(myid == 0) { + // printf("\n---------------------------------------------------start test1paramFPEDParallel\n"); + // printf("Parameters: x0Start: %lg, x0End: %lg, testNumX0 = %lu, fileNameKernel: %s\n", x0Start.d, x0End.d, testNumX0, fileNameKernel); + // } // local parameters init int lenX0Local = testNumX0 / numProcs; @@ -195,7 +202,7 @@ int main(int argc, char **argv) { } // call the error test function - struct errorInfo err = test1FPEDparamParallel(x0Start, x0End, testNumX0, fileNameKernel, myid, i0StartLocal, i0EndLocal); + struct errorInfo err = test1FPEDparamParallel(x0Start, x0End, testNumX0, uniqueLabel, fileNameKernel, myid, i0StartLocal, i0EndLocal); // gather errors and find the max struct errorInfo *errs; @@ -234,7 +241,7 @@ int main(int argc, char **argv) { } printf("average ulp\tmax ulp\n"); printf("%lg\t%lg\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, "%lg\t%lg\n", aveError, maxError); fprintf(fErr, "\naveReUlp = %lg\nmaxInputX0 = 0x%016lx %lg, maxReUlp = %lg\n", aveError, maxInputX0.l, maxInputX0.d, maxError); -- Gitee