void calc_unwrap (double& p[], int N) { double dp[MAX_LENGTH]; double dps[MAX_LENGTH]; double dp_corr[MAX_LENGTH]; double cumsum[MAX_LENGTH]; double cutoff = M_PI; /* default value in matlab */ int j; //assert(N <= MAX_LENGTH); // incremental phase variation // MATLAB: dp = diff(p, 1, 1); for (j = 0; j < N-1; j++) dp[j] = p[j+1] - p[j]; // equivalent phase variation in [-pi, pi] // MATLAB: dps = mod(dp+dp,2*pi) - pi; for (j = 0; j < N-1; j++) dps[j] = (dp[j]+M_PI) - MathFloor((dp[j]+M_PI) / (2*M_PI))*(2*M_PI) - M_PI; // preserve variation sign for +pi vs. -pi // MATLAB: dps(dps==pi & dp>0,:) = pi; for (j = 0; j < N-1; j++) if ((dps[j] == -M_PI) && (dp[j] > 0)) dps[j] = M_PI; // incremental phase correction // MATLAB: dp_corr = dps - dp; for (j = 0; j < N-1; j++) dp_corr[j] = dps[j] - dp[j]; // Ignore correction when incremental variation is smaller than cutoff // MATLAB: dp_corr(abs(dp)<cutoff,:) = 0; for (j = 0; j < N-1; j++) if (MathAbs(dp[j]) < cutoff) dp_corr[j] = 0; // Find cumulative sum of deltas // MATLAB: cumsum = cumsum(dp_corr, 1); cumsum[0] = dp_corr[0]; for (j = 1; j < N-1; j++) cumsum[j] = cumsum[j-1] + dp_corr[j]; // Integrate corrections and add to P to produce smoothed phase values // MATLAB: p(2:m,:) = p(2:m,:) + cumsum(dp_corr,1); for (j = 1; j < N; j++) { p[j] += cumsum[j-1]; if (DEBUG == 1) { Print ("phase_unwrapped[", DoubleToStr(j,0), "] ", DoubleToStr(p[j],10)); file_result = FileWrite (file_handle, "phase_unwrapped", j, p[j]); } } }
// LCOV_EXCL_STOP ex_expr::exp_return_type ExFunctionMath::eval(char *op_data[], CollHeap *heap, ComDiagsArea** diagsArea) { ex_expr::exp_return_type retcode = ex_expr::EXPR_OK; short err = 0; errno = 0; if ((getOperand()) && (getOperand(0)->getDatatype() != REC_FLOAT64)) { return evalUnsupportedOperations(op_data, heap, diagsArea); } switch (getOperType()) { case ITM_DEGREES: // radians to degrees *(double *)op_data[0] = (*(double *)op_data[1] * 180E0) / PIVALUE; break; case ITM_PI: *(double *)op_data[0] = PIVALUE; break; case ITM_RADIANS: // degrees to radians *(double *)op_data[0] = (*(double *)op_data[1] / 180E0) * PIVALUE; break; case ITM_ROUND: { double op, res; short err1 = 0, err2 = 0, err3 = 0; Int32 roundTo; roundTo = (getNumOperands() > 2) ? (Int32)(*((double*)op_data[2])) : 0; switch (getOperand(1)->getDatatype()) { case REC_IEEE_FLOAT32: op = *((float*)op_data[1]); break; case REC_IEEE_FLOAT64: op = *((double*)op_data[1]); break; default: // LCOV_EXCL_START ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("ROUND"); return ex_expr::EXPR_ERROR; // LCOV_EXCL_STOP } // // For commenting purposes, assume the following: // // op = -12.58 // roundTo = 0 // // double pow1 = MathPow(10.0, roundTo, err1); // = 1 double pow2 = MathPow(10.0, -roundTo, err2); // = 1 double pow3 = MathPow(10.0, roundTo+1, err3); // = 10 double abs1 = (op < 0.0) ? -op : op; // = 12.58 double sign = (op < 0.0) ? -1.0 : 1.0; // = -1.0 double floor1 = MathFloor(abs1*pow3, err); // = 125 double floor2 = 10.0 * MathFloor(floor1 / 10.0, err); // = 120 double floor3 = floor1 - floor2; // = 5 double floor4 = MathFloor(abs1*pow1, err); // = 12 double floor5 = pow2 * sign; // = -1.0 // Is digit at rounding position less than 5? if (floor3 < 5.0) { res = floor4 * floor5; // = -12.0 } // Is digit at rounding position greater than 5? else if (floor3 > 5.0) { res = (floor4 + 1.0) * floor5; // = -13.0 } else { // Are digits after rounding position greater than 0? if (((abs1*pow3) - floor1) > 0.0) res = (floor4 + 1.0) * floor5; // = -13.0 else { double floor6 = 2.0 * MathFloor(floor4 / 2.0, err); // = 12.0 // Now round to even if ((floor4 - floor6) == 1.0) res = (floor4 + 1.0) * floor5; // = -13.0 else res = floor4 * floor5; // = -12.0 } } *(double *)op_data[0] = res; break; } case ITM_SCALE_TRUNC: { // LCOV_EXCL_START ExRaiseSqlError(heap, diagsArea, EXE_MATH_FUNC_NOT_SUPPORTED); if (getOperType() == ITM_ROUND) **diagsArea << DgString0("ROUND"); else **diagsArea << DgString0("TRUNCATE"); retcode = ex_expr::EXPR_ERROR; } break; // LCOV_EXCL_STOP case ITM_ACOS: if ((*(double *)op_data[1] < -1) || (*(double *)op_data[1] > 1)) { ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("ACOS"); return ex_expr::EXPR_ERROR; } *(double *)op_data[0] = MathAcos(*(double *)op_data[1], err); break; case ITM_ASIN: if ((*(double *)op_data[1] < -1) || (*(double *)op_data[1] > 1)) { ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("ASIN"); return ex_expr::EXPR_ERROR; } *(double *)op_data[0] = MathAsin(*(double *)op_data[1], err); break; case ITM_ATAN: // No error checks, all numeric values allowed. *(double *)op_data[0] = MathAtan(*(double *)op_data[1], err); break; case ITM_ATAN2: // No error checks, all numeric values allowed. *(double *)op_data[0] = MathAtan2(*(double *)op_data[1], *(double *)op_data[2], err); break; case ITM_CEIL: // No error checks, all numeric values allowed. *(double *)op_data[0] = MathCeil(*(double *)op_data[1], err); break; case ITM_COS: *(double *)op_data[0] = MathCos(*(double *)op_data[1], err); break; case ITM_COSH: *(double *)op_data[0] = MathCosh(*(double *)op_data[1], err); if (*(double *)op_data[0] == HUGE_VAL) { ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("COSH"); return ex_expr::EXPR_ERROR; } break; case ITM_EXP: *(double *)op_data[0] = MathExp(*(double *)op_data[1], err); // Check for overflow. if (err) // if (*(double *)op_data[0] == HUGE_VAL_REAL64) { // Overflow ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("EXP"); return ex_expr::EXPR_ERROR; } break; case ITM_FLOOR: // No error checks, all numeric values allowed. *(double *)op_data[0] = MathFloor(*(double *)op_data[1], err); break; case ITM_LOG: if (*(double *)op_data[1] <= 0) { ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("LOG"); return ex_expr::EXPR_ERROR; } *(double *)op_data[0] = MathLog(*(double *)op_data[1], err); break; case ITM_LOG10: if (*(double *)op_data[1] <= 0) { ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("LOG10"); return ex_expr::EXPR_ERROR; } *(double *)op_data[0] = MathLog10(*(double *)op_data[1], err); break; case ITM_SIN: *(double *)op_data[0] = MathSin(*(double *)op_data[1], err); break; case ITM_SINH: *(double *)op_data[0] = MathSinh(*(double *)op_data[1], err); if (*(double *)op_data[0] == HUGE_VAL) { ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("SINH"); return ex_expr::EXPR_ERROR; } break; case ITM_SQRT: if (*(double *)op_data[1] < 0) { ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("SQRT"); return ex_expr::EXPR_ERROR; } *(double *)op_data[0] = MathSqrt(*(double *)op_data[1], err); break; case ITM_TAN: *(double *)op_data[0] = MathTan(*(double *)op_data[1], err); break; case ITM_TANH: // No error checks, all numeric values allowed. *(double *)op_data[0] = MathTanh(*(double *)op_data[1], err); break; case ITM_EXPONENT: case ITM_POWER: if (((*(double *)op_data[1] == 0) && (*(double *)op_data[2] <= 0)) || ((*(double *)op_data[1] < 0) && (MathFloor(*(double *)op_data[2], err) != *(double *)op_data[2]))) { ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("POWER"); return ex_expr::EXPR_ERROR; } *(double *)op_data[0] = MathPow(*(double *)op_data[1], *(double *)op_data[2], err); if (errno == ERANGE) { // Overflow ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC); **diagsArea << DgString0("POWER"); return ex_expr::EXPR_ERROR; } break; default: { ExRaiseSqlError(heap, diagsArea, EXE_INTERNAL_ERROR); retcode = ex_expr::EXPR_ERROR; } break; } return retcode; }