equation-solver.cpp 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #include "equation-solver.h"
  2. #define _USE_MATH_DEFINES
  3. #include <cmath>
  4. #define TOO_LARGE_RATIO 1e12
  5. namespace msdfgen {
  6. int solveQuadratic(double x[2], double a, double b, double c) {
  7. // a = 0 -> linear equation
  8. if (a == 0 || fabs(b)+fabs(c) > TOO_LARGE_RATIO*fabs(a)) {
  9. // a, b = 0 -> no solution
  10. if (b == 0 || fabs(c) > TOO_LARGE_RATIO*fabs(b)) {
  11. if (c == 0)
  12. return -1; // 0 = 0
  13. return 0;
  14. }
  15. x[0] = -c/b;
  16. return 1;
  17. }
  18. double dscr = b*b-4*a*c;
  19. if (dscr > 0) {
  20. dscr = sqrt(dscr);
  21. x[0] = (-b+dscr)/(2*a);
  22. x[1] = (-b-dscr)/(2*a);
  23. return 2;
  24. } else if (dscr == 0) {
  25. x[0] = -b/(2*a);
  26. return 1;
  27. } else
  28. return 0;
  29. }
  30. static int solveCubicNormed(double x[3], double a, double b, double c) {
  31. double a2 = a*a;
  32. double q = (a2 - 3*b)/9;
  33. double r = (a*(2*a2-9*b) + 27*c)/54;
  34. double r2 = r*r;
  35. double q3 = q*q*q;
  36. double A, B;
  37. if (r2 < q3) {
  38. double t = r/sqrt(q3);
  39. if (t < -1) t = -1;
  40. if (t > 1) t = 1;
  41. t = acos(t);
  42. a /= 3; q = -2*sqrt(q);
  43. x[0] = q*cos(t/3)-a;
  44. x[1] = q*cos((t+2*M_PI)/3)-a;
  45. x[2] = q*cos((t-2*M_PI)/3)-a;
  46. return 3;
  47. } else {
  48. A = -pow(fabs(r)+sqrt(r2-q3), 1/3.);
  49. if (r < 0) A = -A;
  50. B = A == 0 ? 0 : q/A;
  51. a /= 3;
  52. x[0] = (A+B)-a;
  53. x[1] = -0.5*(A+B)-a;
  54. x[2] = 0.5*sqrt(3.)*(A-B);
  55. if (fabs(x[2]) < 1e-14)
  56. return 2;
  57. return 1;
  58. }
  59. }
  60. int solveCubic(double x[3], double a, double b, double c, double d) {
  61. if (a != 0) {
  62. double bn = b/a, cn = c/a, dn = d/a;
  63. // Check that a isn't "almost zero"
  64. if (fabs(bn) < TOO_LARGE_RATIO && fabs(cn) < TOO_LARGE_RATIO && fabs(dn) < TOO_LARGE_RATIO)
  65. return solveCubicNormed(x, bn, cn, dn);
  66. }
  67. return solveQuadratic(x, b, c, d);
  68. }
  69. }