equation-solver.cpp 1.6 KB

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