blob: 0e04d20fc5f95f86266c04398f3d9cb35d15b4d5 [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;
return 1;
}
int SkQuads::RootsReal(const double A, const double B, const double C, double solution[2]) {
if (!A) {
return solve_linear(B, C, solution);
}
const double p = B / (2 * A);
const double q = C / A;
if (sk_double_nearly_zero(A)) {
return solve_linear(B, C, solution);
}
/* normal form: x^2 + px + q = 0 */
const double p2 = p * p;
if (!sk_doubles_nearly_equal_ulps(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_doubles_nearly_equal_ulps(solution[0], solution[1])) {
return 1;
}
return 2;
}