blob: 7d122c0304b65dc0f5a4a772e8506e966a226975 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/base/SkQuads.h"
#include "include/private/base/SkFloatingPoint.h"
#include <cmath>
// Solve 0 = M * x + B. If M is 0, there are no solutions, unless B is also 0,
// in which case there are infinite solutions, so we just return 1 of them.
static int solve_linear(const double M, const double B, double solution[2]) {
if (sk_double_nearly_zero(M)) {
solution[0] = 0;
if (sk_double_nearly_zero(B)) {
return 1;
}
return 0;
}
solution[0] = -B / M;
if (!std::isfinite(solution[0])) {
return 0;
}
return 1;
}
int SkQuads::RootsReal(const double A, const double B, const double C, double solution[2]) {
if (sk_double_nearly_zero(A)) {
return solve_linear(B, C, solution);
}
const double p = B / (2 * A);
const double q = C / A;
/* normal form: x^2 + px + q = 0 */
const double p2 = p * p;
if (!std::isfinite(p2 - q) ||
(!sk_double_nearly_zero(p2 - q) && p2 < q)) {
return 0;
}
double sqrt_D = 0;
if (p2 > q) {
sqrt_D = sqrt(p2 - q);
}
solution[0] = sqrt_D - p;
solution[1] = -sqrt_D - p;
if (sk_double_nearly_zero(sqrt_D) ||
sk_doubles_nearly_equal_ulps(solution[0], solution[1])) {
return 1;
}
return 2;
}