Path: blob/master/3rdparty/openexr/Imath/ImathRoots.h
16337 views
///////////////////////////////////////////////////////////////////////////1//2// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas3// Digital Ltd. LLC4//5// All rights reserved.6//7// Redistribution and use in source and binary forms, with or without8// modification, are permitted provided that the following conditions are9// met:10// * Redistributions of source code must retain the above copyright11// notice, this list of conditions and the following disclaimer.12// * Redistributions in binary form must reproduce the above13// copyright notice, this list of conditions and the following disclaimer14// in the documentation and/or other materials provided with the15// distribution.16// * Neither the name of Industrial Light & Magic nor the names of17// its contributors may be used to endorse or promote products derived18// from this software without specific prior written permission.19//20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.31//32///////////////////////////////////////////////////////////////////////////33343536#ifndef INCLUDED_IMATHROOTS_H37#define INCLUDED_IMATHROOTS_H3839//---------------------------------------------------------------------40//41// Functions to solve linear, quadratic or cubic equations42//43//---------------------------------------------------------------------4445#include <ImathMath.h>46#include <complex>4748namespace Imath {4950//--------------------------------------------------------------------------51// Find the real solutions of a linear, quadratic or cubic equation:52//53// function equation solved54//55// solveLinear (a, b, x) a * x + b == 056// solveQuadratic (a, b, c, x) a * x*x + b * x + c == 057// solveNormalizedCubic (r, s, t, x) x*x*x + r * x*x + s * x + t == 058// solveCubic (a, b, c, d, x) a * x*x*x + b * x*x + c * x + d == 059//60// Return value:61//62// 3 three real solutions, stored in x[0], x[1] and x[2]63// 2 two real solutions, stored in x[0] and x[1]64// 1 one real solution, stored in x[1]65// 0 no real solutions66// -1 all real numbers are solutions67//68// Notes:69//70// * It is possible that an equation has real solutions, but that the71// solutions (or some intermediate result) are not representable.72// In this case, either some of the solutions returned are invalid73// (nan or infinity), or, if floating-point exceptions have been74// enabled with Iex::mathExcOn(), an Iex::MathExc exception is75// thrown.76//77// * Cubic equations are solved using Cardano's Formula; even though78// only real solutions are produced, some intermediate results are79// complex (std::complex<T>).80//81//--------------------------------------------------------------------------8283template <class T> int solveLinear (T a, T b, T &x);84template <class T> int solveQuadratic (T a, T b, T c, T x[2]);85template <class T> int solveNormalizedCubic (T r, T s, T t, T x[3]);86template <class T> int solveCubic (T a, T b, T c, T d, T x[3]);878889//---------------90// Implementation91//---------------9293template <class T>94int95solveLinear (T a, T b, T &x)96{97if (a != 0)98{99x = -b / a;100return 1;101}102else if (b != 0)103{104return 0;105}106else107{108return -1;109}110}111112113template <class T>114int115solveQuadratic (T a, T b, T c, T x[2])116{117if (a == 0)118{119return solveLinear (b, c, x[0]);120}121else122{123T D = b * b - 4 * a * c;124125if (D > 0)126{127T s = Math<T>::sqrt (D);128T q = -(b + (b > 0 ? 1 : -1) * s) / T(2);129130x[0] = q / a;131x[1] = c / q;132return 2;133}134if (D == 0)135{136x[0] = -b / (2 * a);137return 1;138}139else140{141return 0;142}143}144}145146147template <class T>148int149solveNormalizedCubic (T r, T s, T t, T x[3])150{151T p = (3 * s - r * r) / 3;152T q = 2 * r * r * r / 27 - r * s / 3 + t;153T p3 = p / 3;154T q2 = q / 2;155T D = p3 * p3 * p3 + q2 * q2;156157if (D == 0 && p3 == 0)158{159x[0] = -r / 3;160x[1] = -r / 3;161x[2] = -r / 3;162return 1;163}164165std::complex<T> u = std::pow (-q / 2 + std::sqrt (std::complex<T> (D)),166T (1) / T (3));167168std::complex<T> v = -p / (T (3) * u);169170const T sqrt3 = T (1.73205080756887729352744634150587); // enough digits171// for long double172std::complex<T> y0 (u + v);173174std::complex<T> y1 (-(u + v) / T (2) +175(u - v) / T (2) * std::complex<T> (0, sqrt3));176177std::complex<T> y2 (-(u + v) / T (2) -178(u - v) / T (2) * std::complex<T> (0, sqrt3));179180if (D > 0)181{182x[0] = y0.real() - r / 3;183return 1;184}185else if (D == 0)186{187x[0] = y0.real() - r / 3;188x[1] = y1.real() - r / 3;189return 2;190}191else192{193x[0] = y0.real() - r / 3;194x[1] = y1.real() - r / 3;195x[2] = y2.real() - r / 3;196return 3;197}198}199200201template <class T>202int203solveCubic (T a, T b, T c, T d, T x[3])204{205if (a == 0)206{207return solveQuadratic (b, c, d, x);208}209else210{211return solveNormalizedCubic (b / a, c / a, d / a, x);212}213}214215216} // namespace Imath217218#endif219220221