summaryrefslogtreecommitdiffstats
path: root/src/system/Qt3DSCubicRootsImpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/system/Qt3DSCubicRootsImpl.h')
-rw-r--r--src/system/Qt3DSCubicRootsImpl.h177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/system/Qt3DSCubicRootsImpl.h b/src/system/Qt3DSCubicRootsImpl.h
new file mode 100644
index 0000000..8cca59f
--- /dev/null
+++ b/src/system/Qt3DSCubicRootsImpl.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants used by the functions
+//==============================================================================
+const FLOAT M_PHI = 3.14159265358979323846f;
+
+/* epsilon surrounding for near zero values */
+const FLOAT EQN_EPS = 1e-9f;
+
+#define ISZERO(x) ((x) > -EQN_EPS && (x) < EQN_EPS)
+
+// cube-root
+#ifndef CUBEROOT
+#define CUBEROOT(x) \
+ ((x) > 0.0 ? static_cast<FLOAT>(pow((x), 1.0f / 3.0f)) \
+ : ((x) < 0.0 ? -static_cast<FLOAT>(pow(-(x), 1.0f / 3.0f)) : 0.0f))
+#endif
+
+//==============================================================================
+/**
+ * Find the root/s to a quadratic equation.
+ *
+ * The equation is of the form: c[2]*x^2 + c[1]*x + c[0] = 0
+ * Note that this will fail if c[2] is zero, or this is a linear equation.
+ *
+ * @param inConstants The array of constants to the equation; see form above
+ * @param outSolutions The array of solutions to the equation
+ * @return the number of solutions for the equation
+ */
+INT32 CCubicRoots::SolveQuadric(FLOAT inConstants[3], FLOAT outSolutions[2])
+{
+#ifdef _PERF_LOG
+ PerfLogMathEvent1 thePerfLog(DATALOGGER_CUBICROOT);
+#endif
+ FLOAT theP, theQ, theD;
+ INT32 theResult = 0;
+
+ /* normal form: x^2 + px + theQ = 0 */
+
+ theP = inConstants[1] / (2 * inConstants[2]);
+ theQ = inConstants[0] / inConstants[2];
+
+ theD = theP * theP - theQ;
+
+ if (ISZERO(theD)) {
+ outSolutions[0] = -theP;
+ theResult = 1;
+ } else if (theD < 0.0f) {
+ theResult = 0;
+ } else if (theD > 0.0f) {
+ FLOAT theSquareRootD = sqrtf(theD);
+
+ outSolutions[0] = theSquareRootD - theP;
+ outSolutions[1] = -theSquareRootD - theP;
+ theResult = 2;
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Find the root/s to a cubic equation.
+ *
+ * The equation is of the form: c[3]*x^3 + c[2]*x^2 + c[1]*x + c[0] = 0
+ * Note that this will fail if c[3] is zero, or this is a quadratic equation.
+ *
+ * @param inConstants The array of constants to the equation; see form above
+ * @param outSolutions The array of solutions to the equation
+ * @return the number of solutions for the equation
+ */
+INT32 CCubicRoots::SolveCubic(FLOAT inConstants[4], FLOAT outSolutions[3])
+{
+#ifdef _PERF_LOG
+ PerfLogMathEvent1 thePerfLog(DATALOGGER_CUBICROOT);
+#endif
+
+ INT32 theResult;
+ FLOAT theSubstitute;
+ FLOAT theVariableA, theVariableB, theVariableC;
+ FLOAT theASquared, theVariableP, theVariableQ;
+ FLOAT thePCubed, theVariableD;
+
+ /* normal form: x^3 + Ax^2 + Bx + C = 0 */
+
+ theVariableA = inConstants[2] / inConstants[3];
+ theVariableB = inConstants[1] / inConstants[3];
+ theVariableC = inConstants[0] / inConstants[3];
+
+ /* substitute x = y - A/3 to eliminate quadric term:
+ x^3 +px + q = 0 */
+
+ theASquared = theVariableA * theVariableA;
+ theVariableP = 1.0f / 3.0f * (-1.0f / 3.0f * theASquared + theVariableB);
+ theVariableQ = 1.0f / 2.0f * (2.0f / 27.0f * theVariableA * theASquared
+ - 1.0f / 3.0f * theVariableA * theVariableB + theVariableC);
+
+ /* use Cardano's formula */
+
+ thePCubed = theVariableP * theVariableP * theVariableP;
+ theVariableD = theVariableQ * theVariableQ + thePCubed;
+
+ if (ISZERO(theVariableD)) {
+ if (ISZERO(theVariableQ)) /* one triple solution */
+ {
+ outSolutions[0] = 0;
+ theResult = 1;
+ } else /* one single and one double solution */
+ {
+ FLOAT theVariableU = CUBEROOT(-theVariableQ);
+ outSolutions[0] = 2.0f * theVariableU;
+ outSolutions[1] = -theVariableU;
+ theResult = 2;
+ }
+ } else if (theVariableD < 0.0f) /* Casus irreducibilis: three real solutions */
+ {
+ FLOAT thePhi = 1.0f / 3.0f * static_cast<FLOAT>(acos(-theVariableQ / sqrtf(-thePCubed)));
+ FLOAT theVariableT = 2.0f * sqrtf(-theVariableP);
+
+ outSolutions[0] = theVariableT * static_cast<FLOAT>(cos(thePhi));
+ outSolutions[1] = -theVariableT * static_cast<FLOAT>(cos(thePhi + M_PHI / 3.0f));
+ outSolutions[2] = -theVariableT * static_cast<FLOAT>(cos(thePhi - M_PHI / 3.0f));
+ theResult = 3;
+ } else /* one real solution */
+ {
+ FLOAT theSquareRootD = sqrtf(theVariableD);
+ FLOAT theVariableU = CUBEROOT(theSquareRootD - theVariableQ);
+ FLOAT theVariableV = -CUBEROOT(theSquareRootD + theVariableQ);
+
+ outSolutions[0] = theVariableU + theVariableV;
+ theResult = 1;
+ }
+
+ /* resubstitute */
+ theSubstitute = 1.0f / 3.0f * theVariableA;
+
+ for (INT32 theIndex = 0; theIndex < theResult; ++theIndex)
+ outSolutions[theIndex] -= theSubstitute;
+
+ return theResult;
+}
+
+}; // namespace Q3DStudio