FLOAT /*{ ret - floor(x)}*/ _floorf( FLOAT x /*{ (i) - value for which to compute floorf }*/ ) { FLOAT y; /*{ y = |x| }*/ y = x; if (x < (FLOAT)0.0) { y = -y; } /*{ if x > 2^24 (max 23-bit int), result = x }*/ if (y >= (FLOAT)16777216.0) { return x; } /*{ y = truncate(x) }*/ y = TO_FLOAT(TO_LONG(x)); /*{ if y > x, result = result - 1.0 }*/ if (y > x) { y = SUB(y, 1.0); } return y; }
FLOAT /*{ ret - modf(x)}*/ _modff( FLOAT x, /*{ (i) - value for which to compute modff }*/ FLOAT *i /*{ (o) - address to which integer part is written }*/ ) { FLOAT y; FLOAT fract; /*{ y = |x| }*/ y = x; if (x < (FLOAT)0.0) { y = -y; } /*{ if |x| > 2^24 (max 23-bit int) }*/ if (y >= (FLOAT)16777216.0) { /*{ int = x }*/ /*{ return fract = 0.0 }*/ *i = x; return (FLOAT)0.0; } /*{ if |x| < 1 }*/ if (y < (FLOAT)1.0) { /*{ int = 0 }*/ /*{ return fract = x }*/ *i = (FLOAT)0.0; return x; } /*{ y = truncate(|x|) }*/ y = TO_FLOAT(TO_LONG(y)); /*{ if x < 0, y = -y }*/ if (x < (FLOAT)0.0) { y = -y; } /*{ fract = x - y }*/ fract = SUB(x, y); /*{ *i = y }*/ *i = y; return fract; }
DOUBLE /*{ ret - cotd(x) }*/ cotd ( DOUBLE x /*{ (i) - input value x }*/ ) { LONG n; DOUBLE xn; DOUBLE f, g; DOUBLE x_int, x_fract; DOUBLE result; DOUBLE xnum, xden; /*{ If x is outside the domain or zero, return 0.0 }*/ if ((x > COT64_X_MAX) || (x < -COT64_X_MAX) || (x == 0.0L)) { return 0.0L; } /*{ split x into x_int and x_fract for better argument reduction }*/ x_int = TO_DOUBLE(TO_LONG(x)); x_fract = SUBD(x, x_int); /*{ Reduce the input to range between -PI/4, PI/4 }*/ /*{!INDENT}*/ /*{ n = Rounded long x/(PI/2) }*/ if (x > 0.0) { n = TO_LONG(ADDD(MPYD(x, INV_PI_2), 0.5)); } else { n = TO_LONG(ADDD(MPYD(x, INV_PI_2), -0.5)); } /*{ xn = (double)n }*/ xn = TO_DOUBLE(n); /*{ f = x - xn*PI }*/ /* (using higher precision computation) */ f = SUBD(x_int, MPYD(xn, PI_2_DC1)); f = ADDD(f, x_fract); f = SUBD(f, MPYD(xn, PI_2_DC2)); f = SUBD(f, MPYD(xn, PI_2_DC3)); /*{!OUTDENT}*/ if (f < 0.0L) { g = -f; } else { g = f; } /*{ If |f| < eps }*/ if (g < EPS_DOUBLE) { /*{ if n is odd, return -f }*/ if (n & 0x0001) { result = -f; } /*{ if n is even, return 1/f }*/ else { result = DIVD(1.0L, f); } return result; } /*{ g = f * f }*/ g = MPYD(f, f); /*{ Compute sin approximation on reduced argument }*/ /*{!INDENT}*/ /*{ xnum = (((g * p3 + p2) * g + p1) * g * f + f }*/ xnum = MPYD(g, TANDP_COEF3); xnum = ADDD(xnum, TANDP_COEF2); xnum = MPYD(xnum, g); xnum = ADDD(xnum, TANDP_COEF1); xnum = MPYD(xnum, g); xnum = MPYD(xnum, f); xnum = ADDD(xnum, f); /*{ xden = (((g * q4 + q3) * g + q2) * g +q1) * g + q0 }*/ xden = MPYD(g, TANDQ_COEF4); xden = ADDD(xden, TANDQ_COEF3); xden = MPYD(xden, g); xden = ADDD(xden, TANDQ_COEF2); xden = MPYD(xden, g); xden = ADDD(xden, TANDQ_COEF1); xden = MPYD(xden, g); xden = ADDD(xden, TANDQ_COEF0); /*{!OUTDENT}*/ /*{ if n is odd, result = -xnum/xden }*/ if (n & 0x0001) { xnum = -xnum; } /*{ else n is even, result = xden/xnum }*/ else { result = xden; xden = xnum; xnum = result; } result = DIVD(xnum, xden); /*{ return result }*/ return result; }
DOUBLE /*{ ret - cosd(x) }*/ cosd ( DOUBLE x /*{ (i) - input value x }*/ ) { LONG n; DOUBLE y; DOUBLE xn; DOUBLE x_int, x_fract; DOUBLE f, g, result; int sign = 1; /*{ x = |x| (since cos(-x) == cos(x)) }*/ if (x < 0.0L) { x = -x; } /*{ y = |x| + PI/2 }*/ y = ADDD(x, PI_2); /*{ If x is outside domain, return 0.0 }*/ if (y > COS64_X_MAX) { return 0.0L; } /*{ Reduce the input to range between -PI/2, PI/2 }*/ /*{!INDENT}*/ /*{ split x into x_int and x_fract for better argument reduction }*/ x_int = TO_DOUBLE(TO_LONG(x)); x_fract = SUBD(x, x_int); /*{ xn = Rounded long y/PI }*/ n = TO_LONG(ADDD(MPYD(y, INV_PI), 0.5)); xn = TO_DOUBLE(n); /*{ subtract 0.5 from xn }*/ /* (more accurate than adding PI/2 to input argument) */ xn = SUBD(xn, 0.5L); /*{ f = x - xn*PI }*/ /* (using higher precision computation) */ f = SUBD(x_int, MPYD(xn, PI_DC1)); f = ADDD(f, x_fract); f = SUBD(f, MPYD(xn, PI_DC2)); f = SUBD(f, MPYD(xn, PI_DC3)); /*{!OUTDENT}*/ /*{ sign = 1 }*/ /*{ If n is odd, sign = -1 }*/ if (n & 0x0001) { sign = -sign; } /*{ If |f| < eps, return f }*/ if (f < 0.0L) { g = -f; } else { g = f; } if (g < EPS_DOUBLE) { result = f; if (sign < 0) { result = -result; } return result; } /*{ g = f * f }*/ g = MPYD(f, f); /*{ Compute sin approximation }*/ /*{!INDENT}*/ /*{ result = ((((((((g * C8 + C7) * g + C6) * g + C5) * g + C4) * g + C3) * g + C2) * g + C1) * g) * f + f }*/ result = MPYD(g, SIND_COEF8); result = ADDD(result, SIND_COEF7); result = MPYD(result, g); result = ADDD(result, SIND_COEF6); result = MPYD(result, g); result = ADDD(result, SIND_COEF5); result = MPYD(result, g); result = ADDD(result, SIND_COEF4); result = MPYD(result, g); result = ADDD(result, SIND_COEF3); result = MPYD(result, g); result = ADDD(result, SIND_COEF2); result = MPYD(result, g); result = ADDD(result, SIND_COEF1); result = MPYD(result, g); result = MPYD(result, f); result = ADDD(result, f); /*{!OUTDENT}*/ /*{ if sign < 0, result = -result }*/ if (sign < 0) { result = -result; } /* make sure -1.0 <= result <= 1.0 */ if (result > 1.0L) { result = 1.0L; } else if (result < -1.0L) { result = -1.0L; } /*{ return result }*/ return (result); }
/** * Evaluate the code and return the value * @return */ QVariant PythonScript::evaluateImpl() { ScopedPythonGIL lock; PyObject *compiledCode = this->compileToByteCode(true); if (!compiledCode) { return QVariant(""); } PyObject *pyret; beginStdoutRedirect(); if (PyCallable_Check(compiledCode)) { PyObject *empty_tuple = PyTuple_New(0); pyret = PyObject_Call(compiledCode, empty_tuple, localDict); Py_DECREF(empty_tuple); } else { pyret = PyEval_EvalCode(CODE_OBJECT(compiledCode), localDict, localDict); } endStdoutRedirect(); if (!pyret) { if (PyErr_ExceptionMatches(PyExc_ValueError) || PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { PyErr_Clear(); // silently ignore errors return QVariant(""); } else { emit_error(); return QVariant(); } } QVariant qret = QVariant(); /* None */ if (pyret == Py_None) { qret = QVariant(""); } /* numeric types */ else if (PyFloat_Check(pyret)) { qret = QVariant(PyFloat_AS_DOUBLE(pyret)); } else if (INT_CHECK(pyret)) { qret = QVariant((qlonglong)TO_LONG(pyret)); } #if !defined(IS_PY3K) else if (PyLong_Check(pyret)) { qret = QVariant((qlonglong)PyLong_AsLongLong(pyret)); } #endif else if (PyNumber_Check(pyret)) { PyObject *number = PyNumber_Float(pyret); if (number) { qret = QVariant(PyFloat_AS_DOUBLE(number)); Py_DECREF(number); } } /* bool */ else if (PyBool_Check(pyret)) { qret = QVariant(pyret == Py_True); } // could handle advanced types (such as PyList->QValueList) here if needed /* fallback: try to convert to (unicode) string */ if (!qret.isValid()) { #if defined(IS_PY3K) // In 3 everything is unicode PyObject *pystring = PyObject_Str(pyret); if (pystring) { qret = QVariant(QString::fromUtf8(_PyUnicode_AsString(pystring))); } #else PyObject *pystring = PyObject_Unicode(pyret); if (pystring) { PyObject *asUTF8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(pystring), (int)PyUnicode_GET_DATA_SIZE(pystring), nullptr); Py_DECREF(pystring); if (asUTF8) { qret = QVariant(QString::fromUtf8(PyString_AS_STRING(asUTF8))); Py_DECREF(asUTF8); } else if ((pystring = PyObject_Str(pyret))) { qret = QVariant(QString(PyString_AS_STRING(pystring))); Py_DECREF(pystring); } } #endif } Py_DECREF(pyret); if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_ValueError) || PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { PyErr_Clear(); // silently ignore errors return QVariant(""); } else { emit_error(); } return QVariant(); } return qret; }
/** * This emits the error signal and resets the error state * of the python interpreter. */ void PythonScript::emit_error() { // gil is necessary so other things don't continue ScopedPythonGIL lock; // return early if nothing happened if (!PyErr_Occurred()) { emit finished(MSG_FINISHED); return; } // get the error information out PyObject *exception(nullptr), *value(nullptr), *traceback(nullptr); PyErr_Fetch(&exception, &value, &traceback); // special check for system exceptions if (bool(exception) && PyErr_GivenExceptionMatches(exception, PyExc_SystemExit) && PyObject_HasAttrString(exception, "code")) { // value is the return code handed to sys.exit long code = 0; if (bool(value) && INT_CHECK(value)) { code = TO_LONG(value); } // if we are returning 0 then cleanup and return if (code == 0) { // maybe shouldn't clear the error, but for now this // is the agreed upon behavior PyErr_Clear(); Py_XDECREF(traceback); Py_XDECREF(exception); Py_XDECREF(value); emit finished(MSG_FINISHED); return; } } // prework on the exception handling PyErr_NormalizeException(&exception, &value, &traceback); PyErr_Clear(); // convert the traceback into something useful int lineNumber = 0; QString filename; if (traceback) { PyTracebackObject *tb = (PyTracebackObject *)traceback; lineNumber = tb->tb_lineno; filename = TO_CSTRING(tb->tb_frame->f_code->co_filename); } // the error message is the full (formated) traceback PyObject *str_repr = PyObject_Str(value); QString message; QTextStream msgStream(&message); if (value && str_repr) { if (exception == PyExc_SyntaxError) { msgStream << constructSyntaxErrorStr(value); } else { QString excTypeName( value->ob_type ->tp_name); // This is fully qualified with the module name excTypeName = excTypeName.section(".", -1); msgStream << excTypeName << ": " << TO_CSTRING(str_repr); } } else { msgStream << "Unknown exception has occurred."; } tracebackToMsg(msgStream, (PyTracebackObject *)(traceback)); msgStream << "\n"; Py_XDECREF(traceback); Py_XDECREF(exception); Py_XDECREF(value); emit error(msgStream.readAll(), filename, lineNumber); }