/* * COMPLEX ROOTS */ // deg0 public static void RootsAll(double a, out int numRoot, out int numRootReal, out CNum[] root) { numRoot=(Math.Abs(a)>MConsts.EPS_DEC)? 0: Equation.NumRootInfinite; numRootReal=numRoot; root=null; }
public CNum Pow(double power) { if (this.IsZero) return new CNum(0,0); CNum res=new CNum(); res.FromRadiusAngle(Math.Pow(this.Radius,power),this.Angle*power); return res; }
public CNum Pow(double power) { if (this.IsZero) { return(new CNum(0, 0)); } CNum res = new CNum(); res.FromRadiusAngle(Math.Pow(this.Radius, power), this.Angle * power); return(res); }
// deg1 public static void RootsAll(double a, double b, out int numRoot, out int numRootReal, out CNum[] root) { if (Math.Abs(a) < MConsts.EPS_DEC) { Equation.RootsAll(b, out numRoot, out numRootReal, out root); } else { numRoot = 1; numRootReal = numRoot; root = new CNum[1]; root[0] = new CNum(-b / a, 0); } }
// deg1 public static void RootsAll(double a, double b, out int numRoot, out int numRootReal, out CNum[] root) { if (Math.Abs(a)<MConsts.EPS_DEC) { Equation.RootsAll(b,out numRoot,out numRootReal,out root); } else { numRoot=1; numRootReal=numRoot; root=new CNum[1]; root[0]=new CNum(-b/a,0); } }
// deg2 public static void RootsAll(double a, double b, double c, out int numRoot, out int numRootReal, out CNum[] root) { // multiply root is referred as different roots; // in case of multiply roots output: // numRoot=2; root[0]=root[1]; // root[0].Multiplicity=root[1].Multiplicity=2 // TODO: check LOGIC above !!! if (Math.Abs(a) < MConsts.EPS_DEC) { Equation.RootsAll(b, c, out numRoot, out numRootReal, out root); } else { numRoot = 2; root = new CNum[2]; double D = b * b - 4.0 * a * c; if (D < 0) // TODO: check D<=-MConsts.EPS_DEC { numRootReal = 0; double sqrtD = Math.Sqrt(Math.Abs(D)); root[0] = new CNum(-b / (2.0 * a), -sqrtD / (2.0 * a)); root[1] = new CNum(-b / (2.0 * a), sqrtD / (2.0 * a)); } else { numRootReal = 2; if (D == 0) { root[0] = new CNum(-b / (2.0 * a), 0.0, 2); // TODO: CHECK MULTIPLICITY !!! root[1] = new CNum(-b / (2.0 * a), 0.0, 2); } else { double sqrtD = Math.Sqrt(D); root[0] = new CNum((-b - sqrtD) / (2.0 * a), 0); root[1] = new CNum((-b + sqrtD) / (2.0 * a), 0); } } } }
// deg2 public static void RootsAll(double a, double b, double c, out int numRoot, out int numRootReal, out CNum[] root) { // multiply root is referred as different roots; // in case of multiply roots output: // numRoot=2; root[0]=root[1]; // root[0].Multiplicity=root[1].Multiplicity=2 // TODO: check LOGIC above !!! if (Math.Abs(a)<MConsts.EPS_DEC) { Equation.RootsAll(b,c,out numRoot, out numRootReal, out root); } else { numRoot = 2; root=new CNum[2]; double D = b*b - 4.0*a*c; if (D < 0) // TODO: check D<=-MConsts.EPS_DEC { numRootReal = 0; double sqrtD = Math.Sqrt(Math.Abs(D)); root[0]=new CNum(-b/(2.0*a),-sqrtD/(2.0*a)); root[1]=new CNum(-b/(2.0*a), sqrtD/(2.0*a)); } else { numRootReal = 2; if (D==0) { root[0]=new CNum(-b/(2.0*a), 0.0, 2); // TODO: CHECK MULTIPLICITY !!! root[1]=new CNum(-b/(2.0*a), 0.0, 2); } else { double sqrtD = Math.Sqrt(D); root[0]=new CNum((-b-sqrtD)/(2.0*a), 0); root[1]=new CNum((-b+sqrtD)/(2.0*a), 0); } } } }
/* * INITIALIZERS */ public void From(CNum z) { this.re = z.Re; this.im = z.Im; this.multiplicity = z.Multiplicity; }
public CNum(CNum z) : this(z.Re, z.Im, z.Multiplicity) { }
// deg3 public static void RootsAll(double a, double b, double c, double d, out int numRoot, out int numRootReal, out CNum[] root) { // output: // case of 3 real roots => // the roots are sorted in increasing order // case of 1 real root => real, complex-, complex+ // // multiply real roots referred as different roots /* * Catch EXACT TANGENTS when they are not obvious * from the control points specification */ double rootToAdd = -1.0; // asign an invalid parametric value int numRootRed = -1, numRootRealRed = -1; // roots after reduction CNum[] rootRed = null; if (Equation.Evaluate(0.0, a, b, c, d) == 0.0) { rootToAdd = 0.0; Equation.RootsAll(a, b, c, out numRootRed, out numRootRealRed, out rootRed); } if (Equation.Evaluate(1.0, a, b, c, d) == 0.0) { rootToAdd = 1.0; Equation.RootsAll(a, a + b, a + b + c, out numRootRed, out numRootRealRed, out rootRed); } if (rootToAdd != -1.0) { root = new CNum[numRootRed + 1]; numRoot = numRootRed + 1; numRootReal = numRootRealRed + 1; // // two complex roots of the reduced (quadratic) equation // if ((numRootRed - numRootRealRed) == 2) { root[0] = new CNum(rootToAdd, 0.0); root[1] = new CNum(rootRed[0]); root[2] = new CNum(rootRed[1]); return; } // // all roots of the reduced equation are real // CNum rootNew = new CNum(rootToAdd, 0.0); // adjust multiplicities for (int iRootRed = 0; iRootRed < numRootRed; iRootRed++) { if (rootToAdd == rootRed[iRootRed].Re) { rootNew.Multiplicity += 1; rootRed[iRootRed].Multiplicity += 1; } } if (numRootRed == 0) { root[0] = new CNum(rootNew); return; } if (numRootRed == 1) { if (rootToAdd <= rootRed[0].Re) { root[0] = new CNum(rootNew); root[1] = new CNum(rootRed[0]); } else { root[0] = new CNum(rootRed[0]); root[1] = new CNum(rootNew); } } if (numRootRed == 2) { if (rootToAdd <= rootRed[0].Re) { root[0] = new CNum(rootNew); root[1] = new CNum(rootRed[0]); root[2] = new CNum(rootRed[1]); } else if (rootToAdd <= rootRed[1].Re) { root[0] = new CNum(rootRed[0]); root[1] = new CNum(rootNew); root[2] = new CNum(rootRed[1]); } else { root[0] = new CNum(rootRed[0]); root[1] = new CNum(rootRed[1]); root[2] = new CNum(rootNew); } } return; // end - catch EXACT TANGENTS } if (Math.Abs(a) < MConsts.EPS_DEC) { Equation.RootsAll(b, c, d, out numRoot, out numRootReal, out root); } else { numRoot = 3; root = new CNum[3]; double bb, cc, dd, pp, qq, D; bb = b / a; cc = c / a; dd = d / a; pp = -(bb * bb / 3.0) + cc; qq = (2.0 * bb * bb * bb / 27.0) - (bb * cc / 3.0) + dd; // solve quadratic equation (1,qq,-pp^3/27) D = qq * qq + (4.0 * pp * pp * pp / 27.0); D = (Math.Abs(D) < MConsts.EPS_DEC * MConsts.EPS_DEC) ? 0.0 : D; //tolerancing for double roots if (D > 0) //D>0, => 1 real & 2 complex roots { numRootReal = 1; double zp = 0.5 * (-qq + Math.Sqrt(D)); // two real roots of the quadratic equation double zm = 0.5 * (-qq - Math.Sqrt(D)); double zpRoot3 = Math.Sign(zp) * Math.Pow(Math.Abs(zp), (double)(1.0 / 3.0)); double zmRoot3 = Math.Sign(zm) * Math.Pow(Math.Abs(zm), (double)(1.0 / 3.0)); double sumRoots = zpRoot3 + zmRoot3; double difRoots = zpRoot3 - zmRoot3; root[0] = new CNum(-bb / 3.0 + sumRoots, 0); root[1] = new CNum(-bb / 3.0 - 0.5 * sumRoots, -0.5 * Math.Sqrt(3.0) * difRoots); root[2] = new CNum(-bb / 3.0 - 0.5 * sumRoots, 0.5 * Math.Sqrt(3.0) * difRoots); } else //D<=0, => 3 real roots { numRootReal = 3; ArrayList arr = new ArrayList(); // roots of the depressed equation, root = y-bb/3 int i; if (D < 0) { CNum z = new CNum(-0.5 * qq, 0.5 * Math.Sqrt(-D)); // root of the quartatic equation if (z.IsZero) { throw new ExceptionGMath("Equation", "RootsAll", "Degree 3"); } double zRadius = z.Radius; double zAngle = z.Angle; double zRadiusRoot3 = Math.Pow(zRadius, 1.0 / 3.0); for (i = 0; i <= 2; i++) { arr.Add(2.0 * zRadiusRoot3 * Math.Cos((zAngle + 2.0 * i * Math.PI) / 3.0)); } arr.Sort(); // TODO: check for (i = 0; i <= 2; i++) { root[i] = new CNum(-bb / 3.0 + (double)arr[i], 0); } } if (D == 0) // case of the multiply roots { double z = -0.5 * qq; // double real root of the quadratic equation double zRoot3 = Math.Sign(z) * Math.Pow(Math.Abs(z), 1.0 / 3.0); arr.Add(2.0 * zRoot3); arr.Add(-zRoot3); arr.Add(-zRoot3); if (qq > 0) { root[0] = new CNum(-bb / 3.0 + (double)arr[0], 0, 1); root[1] = new CNum(-bb / 3.0 + (double)arr[1], 0, 2); root[2] = new CNum(root[1]); } else if (qq == 0) { root[0] = new CNum(-bb / 3.0, 0, 3); root[1] = new CNum(root[0]); root[2] = new CNum(root[0]); } else { root[0] = new CNum(-bb / 3.0 + (double)arr[1], 0, 2); root[1] = new CNum(root[0]); root[2] = new CNum(-bb / 3.0 + (double)arr[0], 0, 2); } } } } }
/* * REAL ROOTS */ private static void RootsAllToReal(int numRootReal, CNum[] croot, out double[] root) { root=null; if (numRootReal>0) { root=new double[numRootReal]; for (int i=0; i<numRootReal; i++) { root[i]=croot[i].Re; } } }
// deg3 public static void RootsAll(double a, double b, double c, double d, out int numRoot, out int numRootReal, out CNum[] root) { // output: // case of 3 real roots => // the roots are sorted in increasing order // case of 1 real root => real, complex-, complex+ // // multiply real roots referred as different roots /* * Catch EXACT TANGENTS when they are not obvious * from the control points specification */ double rootToAdd=-1.0; // asign an invalid parametric value int numRootRed=-1, numRootRealRed=-1; // roots after reduction CNum[] rootRed=null; if (Equation.Evaluate(0.0,a,b,c,d)==0.0) { rootToAdd=0.0; Equation.RootsAll(a,b,c, out numRootRed, out numRootRealRed, out rootRed); } if (Equation.Evaluate(1.0,a,b,c,d)==0.0) { rootToAdd=1.0; Equation.RootsAll(a,a+b,a+b+c, out numRootRed, out numRootRealRed, out rootRed); } if (rootToAdd!=-1.0) { root=new CNum[numRootRed+1]; numRoot=numRootRed+1; numRootReal=numRootRealRed+1; // // two complex roots of the reduced (quadratic) equation // if ((numRootRed-numRootRealRed)==2) { root[0]=new CNum(rootToAdd,0.0); root[1]=new CNum(rootRed[0]); root[2]=new CNum(rootRed[1]); return; } // // all roots of the reduced equation are real // CNum rootNew=new CNum(rootToAdd,0.0); // adjust multiplicities for (int iRootRed=0; iRootRed<numRootRed; iRootRed++) { if (rootToAdd==rootRed[iRootRed].Re) { rootNew.Multiplicity+=1; rootRed[iRootRed].Multiplicity+=1; } } if (numRootRed==0) { root[0]=new CNum(rootNew); return; } if (numRootRed==1) { if (rootToAdd<=rootRed[0].Re) { root[0]=new CNum(rootNew); root[1]=new CNum(rootRed[0]); } else { root[0]=new CNum(rootRed[0]); root[1]=new CNum(rootNew); } } if (numRootRed==2) { if (rootToAdd<=rootRed[0].Re) { root[0]=new CNum(rootNew); root[1]=new CNum(rootRed[0]); root[2]=new CNum(rootRed[1]); } else if (rootToAdd<=rootRed[1].Re) { root[0]=new CNum(rootRed[0]); root[1]=new CNum(rootNew); root[2]=new CNum(rootRed[1]); } else { root[0]=new CNum(rootRed[0]); root[1]=new CNum(rootRed[1]); root[2]=new CNum(rootNew); } } return; // end - catch EXACT TANGENTS } if (Math.Abs(a)<MConsts.EPS_DEC) { Equation.RootsAll(b,c,d,out numRoot, out numRootReal, out root); } else { numRoot = 3; root=new CNum[3]; double bb, cc, dd, pp, qq, D; bb = b/a; cc = c/a; dd = d/a; pp = -(bb*bb/3.0)+cc; qq = (2.0*bb*bb*bb/27.0)-(bb*cc/3.0)+dd; // solve quadratic equation (1,qq,-pp^3/27) D = qq*qq+(4.0*pp*pp*pp/27.0); D = (Math.Abs(D)<MConsts.EPS_DEC*MConsts.EPS_DEC) ? 0.0 : D; //tolerancing for double roots if (D>0) //D>0, => 1 real & 2 complex roots { numRootReal = 1; double zp = 0.5*(-qq+Math.Sqrt(D)); // two real roots of the quadratic equation double zm = 0.5*(-qq-Math.Sqrt(D)); double zpRoot3 = Math.Sign(zp)*Math.Pow(Math.Abs(zp),(double)(1.0/3.0)); double zmRoot3 = Math.Sign(zm)*Math.Pow(Math.Abs(zm),(double)(1.0/3.0)); double sumRoots = zpRoot3+zmRoot3; double difRoots = zpRoot3-zmRoot3; root[0]=new CNum(-bb/3.0+sumRoots,0); root[1]=new CNum(-bb/3.0-0.5*sumRoots, -0.5*Math.Sqrt(3.0)*difRoots); root[2]=new CNum(-bb/3.0-0.5*sumRoots, 0.5*Math.Sqrt(3.0)*difRoots); } else //D<=0, => 3 real roots { numRootReal = 3; ArrayList arr=new ArrayList(); // roots of the depressed equation, root = y-bb/3 int i; if (D<0) { CNum z=new CNum(-0.5*qq, 0.5*Math.Sqrt(-D)); // root of the quartatic equation if (z.IsZero) { throw new ExceptionGMath("Equation","RootsAll","Degree 3"); } double zRadius=z.Radius; double zAngle=z.Angle; double zRadiusRoot3 = Math.Pow(zRadius,1.0/3.0); for (i=0; i<=2; i++) { arr.Add(2.0*zRadiusRoot3*Math.Cos((zAngle+2.0*i*Math.PI)/3.0)); } arr.Sort(); // TODO: check for (i=0; i<=2; i++) { root[i]=new CNum(-bb/3.0+(double)arr[i],0); } } if (D==0) // case of the multiply roots { double z = -0.5*qq; // double real root of the quadratic equation double zRoot3 = Math.Sign(z)*Math.Pow(Math.Abs(z),1.0/3.0); arr.Add(2.0*zRoot3); arr.Add(-zRoot3); arr.Add(-zRoot3); if (qq>0) { root[0]=new CNum(-bb/3.0+(double)arr[0],0,1); root[1]=new CNum(-bb/3.0+(double)arr[1],0,2); root[2]=new CNum(root[1]); } else if (qq==0) { root[0]=new CNum(-bb/3.0,0,3); root[1]=new CNum(root[0]); root[2]=new CNum(root[0]); } else { root[0]=new CNum(-bb/3.0+(double)arr[1],0,2); root[1]=new CNum(root[0]); root[2]=new CNum(-bb/3.0+(double)arr[0],0,2); } } } } }
public CNum(CNum z): this(z.Re,z.Im,z.Multiplicity) { }
/* * INITIALIZERS */ public void From(CNum z) { this.re=z.Re; this.im=z.Im; this.multiplicity=z.Multiplicity; }