QmlCompiler: Implement Math.pow()
Also, add missing positive infinity to test data. Pick-to: 6.4 Fixes: QTBUG-104745 Change-Id: I958aca672cca8cc83c540ed3ea75b08e70eb90fd Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
eed7b3f4e7
commit
e97f8cabc8
|
@ -280,5 +280,16 @@ QString QJSPrimitiveValue::toString(double d)
|
|||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn double QQmlPrivate::jsExponentiate(double base, double exponent)
|
||||
\internal
|
||||
\since 6.4
|
||||
|
||||
Performs JavaScript's Number::exponentiate operation on \a base and
|
||||
\a exponent, and returns the result.
|
||||
|
||||
See https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-exponentiate
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
|
|
@ -783,6 +783,37 @@ private:
|
|||
QJSPrimitiveValuePrivate d;
|
||||
};
|
||||
|
||||
namespace QQmlPrivate {
|
||||
// TODO: Make this constexpr once std::isnan is constexpr.
|
||||
inline double jsExponentiate(double base, double exponent)
|
||||
{
|
||||
constexpr double qNaN = std::numeric_limits<double>::quiet_NaN();
|
||||
constexpr double inf = std::numeric_limits<double>::infinity();
|
||||
|
||||
if (qIsNull(exponent))
|
||||
return 1.0;
|
||||
|
||||
if (std::isnan(exponent))
|
||||
return qNaN;
|
||||
|
||||
if (QJSNumberCoercion::equals(base, 1.0) || QJSNumberCoercion::equals(base, -1.0))
|
||||
return std::isinf(exponent) ? qNaN : std::pow(base, exponent);
|
||||
|
||||
if (!qIsNull(base))
|
||||
return std::pow(base, exponent);
|
||||
|
||||
if (std::copysign(1.0, base) > 0.0)
|
||||
return exponent < 0.0 ? inf : std::pow(base, exponent);
|
||||
|
||||
if (exponent < 0.0)
|
||||
return QJSNumberCoercion::equals(std::fmod(-exponent, 2.0), 1.0) ? -inf : inf;
|
||||
|
||||
return QJSNumberCoercion::equals(std::fmod(exponent, 2.0), 1.0)
|
||||
? std::copysign(0, -1.0)
|
||||
: 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QJSPRIMITIVEVALUE_H
|
||||
|
|
|
@ -1320,6 +1320,7 @@ bool QQmlJSCodeGenerator::inlineMathMethod(const QString &name, int argc, int ar
|
|||
addInclude(u"limits"_s);
|
||||
addInclude(u"qalgorithms.h"_s);
|
||||
addInclude(u"qrandom.h"_s);
|
||||
addInclude(u"qjsprimitivevalue.h"_s);
|
||||
|
||||
// If the result is not stored, we don't need to generate any code. All the math methods are
|
||||
// conceptually pure functions.
|
||||
|
@ -1403,8 +1404,7 @@ bool QQmlJSCodeGenerator::inlineMathMethod(const QString &name, int argc, int ar
|
|||
"? arg2 "
|
||||
": ((arg2 < arg1 || std::isnan(arg2)) ? arg2 : arg1)"_s;
|
||||
} else if (name == u"pow"_s) {
|
||||
// TODO: complicated
|
||||
return false;
|
||||
expression = u"QQmlPrivate::jsExponentiate(arg1, arg2)"_s;
|
||||
} else if (name == u"random"_s && argc == 0) {
|
||||
expression = u"QRandomGenerator::global()->generateDouble()"_s;
|
||||
} else if (name == u"round"_s && argc == 1) {
|
||||
|
|
|
@ -32,7 +32,7 @@ QtObject {
|
|||
property double log2: Math.log2(a)
|
||||
property double max: Math.max(a, b)
|
||||
property double min: Math.min(a, b)
|
||||
// property double pow: Math.pow(a, b)
|
||||
property double pow: Math.pow(a, b)
|
||||
property double random: Math.random()
|
||||
property double round: Math.round(a)
|
||||
property double sign: Math.sign(a)
|
||||
|
|
|
@ -1606,6 +1606,7 @@ void tst_QmlCppCodegen::jsMathObject()
|
|||
std::numeric_limits<quint32>::max(),
|
||||
std::numeric_limits<float>::max(),
|
||||
std::numeric_limits<double>::max(),
|
||||
qInf()
|
||||
};
|
||||
|
||||
QJSManagedValue math(engine.globalObject().property(QStringLiteral("Math")), &engine);
|
||||
|
|
Loading…
Reference in New Issue