TPCCLIB
Loading...
Searching...
No Matches
roots.c File Reference

Finding the real roots of equations. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "tpcextensions.h"
#include "tpclinopt.h"

Go to the source code of this file.

Functions

int rootsCubic (const double a, const double b, const double c, double *x1, double *x2, double *x3)
int rootsQuadratic (const double a, const double b, const double c, double *x1, double *x2)

Detailed Description

Finding the real roots of equations.

Author
Vesa Oikonen

Definition in file roots.c.

Function Documentation

◆ rootsCubic()

int rootsCubic ( const double a,
const double b,
const double c,
double * x1,
double * x2,
double * x3 )

Find the real roots of cubic equation x^3 + a x^2 + b x + c = 0.

The number of real roots can be 1 or 3, but coincident roots are possible. Root values, excluding duplicates and triplicates, will be placed in pointers x1, x2, and x3 in ascending order, or set to NaN.

Based on GNU Scientific Library function gsl_poly_solve_cubic.

See also
rootsQuadratic, fitLine
Returns
Returns the number of real individual roots, and zero in case of an error.
Parameters
aInput: Parameter a of the cubic equation.
bInput: Parameter b of the cubic equation.
cInput: Parameter c of the cubic equation.
x1Output: Pointer for root 1 value. Will be set to NaN if there are no real roots.
x2Output: Pointer for root 2 value. Will be set to NaN if there is only one individual real root.
x3Output: Pointer for root 3 value. Will be set to NaN if there are only two individual real roots.

Definition at line 30 of file roots.c.

43 {
44 if(x1==NULL || x2==NULL || x3==NULL) return(0);
45 *x1=*x2=*x3=nan("");
46
47 if(a==0 && b==0 && c==0) return(0);
48 if(!isfinite(a) || !isfinite(b) || !isfinite(c)) return(0);
49
50 long double q=(a*a - 3*b);
51 long double r=(2*a*a*a - 9*a*b + 27*c);
52
53 long double Q=q/9;
54 long double R=r/54;
55
56 long double Q3=Q*Q*Q;
57 long double R2=R*R;
58
59 long double CR2=729*r*r;
60 long double CQ3=2916*q*q*q;
61
62 if(R==0 && Q==0) {
63 *x1=-a/3; // *x2=-a/3; *x3=-a/3;
64 return(1);
65 } else if(CR2==CQ3) {
66 long double sqrtQ=sqrt(Q);
67 if(R>0) {
68 *x1=-2*sqrtQ - a/3;
69 *x2=sqrtQ - a/3; // *x3=sqrtQ - a/3;
70 } else {
71 *x1=-sqrtQ - a/3; // *x2=-sqrtQ - a/3; *x3=2*sqrtQ - a/3;
72 *x2=2*sqrtQ - a/3;
73 }
74 return(2);
75 } else if(R2<Q3) {
76 double ratio=copysign(sqrt(R2/Q3), R);
77 //if(!isfinite(ratio)) return(0);
78 double theta=acos(ratio);
79 double norm=-2*sqrt(Q);
80 //if(!isfinite(norm)) return(0);
81 *x1=norm*cos(theta/3) - a/3;
82 *x2=norm*cos((theta + 2.0*M_PI)/3) - a/3;
83 *x3=norm*cos((theta - 2.0*M_PI)/3) - a/3;
84 if(*x1>*x2) {double s=*x1; *x1=*x2; *x2=s;}
85 if(*x2>*x3) {
86 double s=*x2; *x2=*x3; *x3=s;
87 if(*x1>*x2) {double s=*x1; *x1=*x2; *x2=s;}
88 }
89 return(3);
90 } else {
91 long double A = -copysign(pow(fabsl(R) + sqrt(R2-Q3), 1.0/3.0), R);
92 long double B=Q/A;
93 *x1=A + B - a/3;
94 return(1);
95 }
96}

◆ rootsQuadratic()

int rootsQuadratic ( const double a,
const double b,
const double c,
double * x1,
double * x2 )

Find the real roots of quadratic equation a x^2 + b x + c = 0.

The number of real roots can be 0, 1, or 2, but coincident roots are possible. Root values, excluding duplicate value, will be placed in pointers x1 and x2 in ascending order, or set to NaN.

Based on GNU Scientific Library function gsl_poly_solve_quadratic.

See also
rootsCubic, fitLine
Returns
Returns the number of real roots, excluding duplicate solutions.
Parameters
aInput: Parameter a of the quadratic equation.
bInput: Parameter b of the quadratic equation.
cInput: Parameter c of the quadratic equation.
x1Output: Pointer for root 1 value. Will be set to NaN if there are no real roots.
x2Output: Pointer for root 2 value. Will be set to NaN if there is only one individual real root.

Definition at line 111 of file roots.c.

122 {
123 if(x1==NULL || x2==NULL) return(0);
124 *x1=*x2=nan("");
125
126 if(!isfinite(a) || !isfinite(b) || !isfinite(c)) return(0);
127
128 if(a==0) {
129 if(b==0) return(0);
130 else {*x1=-c/b; /* *x2=-c/b;*/ return(1);}
131 }
132 long double d=b*b - 4*a*c;
133 if(d>0) {
134 if(b==0) {
135 long double r=fabs(sqrt(-c/a));
136 *x1=-r; *x2=r;
137 } else {
138 long double t=-0.5*(b + copysign(sqrt(d), b));
139 long double r1=t/a;
140 long double r2=c/t;
141 if(r1<r2) {*x1=r1; *x2=r2;} else {*x1=r2; *x2=r1;}
142 }
143 return(2);
144 } else if(d==0) {
145 *x1=-0.5*b/a; // *x2=-0.5*b/a;
146 return(1);
147 } else {
148 return(0);
149 }
150}