using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Math2 { unsafe public class Math2 { public class SquareEquation { private object[] sol = new object[0]; private bool isComplex = false; public object[] Solutions { get { return sol; } } public bool SolutionIsComplex { get { return isComplex; } } public SquareEquation(double* a, double* b, double* c, bool allowcomplex) { if (*a == 0) { sol = new object[] { -*c / *b }; } else { double discr = *b * *b - 4 * *a * *c; if (discr < 0) { isComplex = true; if (allowcomplex) { double p1 = -1 * *b; double discr2 = -1 * discr; double p2 = 2 * *a; Complex.Z z1 = new Complex.Z(&p1, &discr); Complex.Z z2 = new Complex.Z(&p1, &discr2); Complex.Z zdivisor = new Complex.Z(&p2); z1.Divide(&zdivisor); z2.Divide(&zdivisor); sol = new object[] { z1.ToString(false, 'j', 3), z2.ToString(false, 'j', 3) }; } } else if (discr == 0) { sol = new object[] { -*b / 2 * *a }; } else { sol = new object[] { getresult(a, b, &discr, 1), getresult(a, b, &discr, -1) }; } } } private static double getresult(double* a, double* b, double* discr, sbyte mod) { return (-*b + mod * *discr) / 2 * *a; } } class Complex { public struct Z { private double _a, _b, _r; private float _p; public double A { get { return _a; } set { _a = value; fixed (double* _B = &_b) { _r = rFromCart(&value, _B); _p = phiFromCart(&value, _B); } } } public double B { get { return _b; } set { _b = value; fixed (double* _A = &_a) { _r = rFromCart(_A, &value); _p = phiFromCart(_A, &value); } } } public double R { get { return _r; } set { _r = value; fixed (float* _P = &_p) { _a = aFromPol(&value, _P); _b = bFromPol(&value, _P); } } } public float Phi { get { return _p; } set { _p = value; fixed (double* _R = &_r) { _a = aFromPol(_R, &value); _b = bFromPol(_R, &value); } } } public string ToString(bool PolarForm, char iChar, byte digits) { fixed (Z* z = &this) { return stringify(z, PolarForm, iChar, digits); } } public string ToString(bool PolarForm, char iChar) { return ToString(PolarForm, iChar, 2); } public string ToString(bool PolarForm) { return ToString(PolarForm, 'i'); } public Z(double* a, double* b) { _a = *a; _b = *b; _r = rFromCart(a, b); _p = phiFromCart(a, b); } public Z(double* r, float* p) { _r = *r; _p = *p; _a = aFromPol(r, p); _b = bFromPol(r, p); } public Z(double* n) { _a = *n; _b = 0; _r = *n; _p = 0; } public void Set(double* a, double* b) { _a = *a; _b = *b; _r = rFromCart(a, b); _p = phiFromCart(a, b); } public void Set(double* r, float* phi) { _r = *r; _p = *phi; _a = aFromPol(r, phi); _b = bFromPol(r, phi); } public void Divide(Z* Divisor) { fixed (Z* dividend = &this) { this = divide(dividend, Divisor, true); } } public void Multiply(Z* Operand2) { fixed (Z* op1 = &this) { this = multiply(op1, Operand2, true); } } public void Add(Z* Operand2) { fixed (Z* op1 = &this) { this = add(op1, Operand2, 1); } } public void Sub(Z* Operand2) { fixed (Z* op1 = &this) { this = add(op1, Operand2, -1); } } public void ValidateAngle() { fixed (float* f = &_p) { Angle.ValidateDeg(f); } } } private static Z add(Z* op1, Z* op2, sbyte mod) { double a = op1->A + mod * (op2->A); double b = op1->B + mod * (op2->B); return new Z(&a, &b); } private static Z divide(Z* dividend, Z* divisor, bool anglecheck) { double r = dividend->R / divisor->R; float p = dividend->Phi - divisor->Phi; Z z = new Z(&r, &p); if (anglecheck) z.ValidateAngle(); return z; } private static Z multiply(Z* op1, Z* op2, bool anglecheck) { double r = op1->R * op2->R; float p = op1->Phi + op1->Phi; Z z = new Z(&r, &p); if (anglecheck) z.ValidateAngle(); return z; } private static string stringify(Z* c, bool polar, char imag, byte digits) { string result = ""; if (polar) { result += c->R + " <" + c->Phi + "°"; } else { result += c->A + " "; if (c->B < 0) { string s = c->B.ToString().Remove(0, 1); result += "- " + s; } else { result += "+ " + c->B.ToString(); } result += imag; } return result; } private static double aFromPol(double* r, float* phi) { return *r * Math2.CosDeg(phi); } private static double bFromPol(double* r, float* phi) { return *r * Math2.SinDeg(phi); } private static double rFromCart(double* a, double* b) { return Math.Sqrt(*a * *a + *b * *b); } private static float phiFromCart(double* a, double* b) { float f = (float)(*b / *a); f = (float)Math2.ATanDeg(&f); correctangle(&f, a, b); return f; } private static void correctangle(float* targetAngle, double* a, double* b) { switch (Coord2D.GetQuadrantXY(a, b)) { case 2: *targetAngle += 180f; break; case 3: goto case 2; } Angle.ValidateDeg(targetAngle); } } public class Coord2D { public static byte GetQuadrantDeg(float* degAnglePtr) { float f = *degAnglePtr; Math2.Angle.ValidateDeg(&f); for (byte b = 0; b < 4; b++) { if (f >= 90 * b) return (byte)(b + 1); } return 0; } public static byte GetQuadrantXY(double* x, double* y) { if (*x > 0) { if (*y >= 0) return 1; if (*y < 0) return 4; } else if (*x < 0) { if (*y >= 0) return 2; if (*y < 0) return 3; } else { if (*y > 0) return 1; if (*y < 0) return 3; } return 0; } } public class Angle { public static float DegToRad(float* deg) { return (float)((Math.PI * *deg) / 180); } public static float RadToDeg(float* rad) { return (float)((180 * *rad) / Math.PI); } public static void ValidateDeg(float* angle) { if (*angle > 360) { *angle -= 360; ValidateDeg(angle); return; } if (*angle < 0) { *angle += 360; ValidateDeg(angle); return; } } } public static double SinDeg(float* f) { return Math.Sin(Angle.DegToRad(f)); } public static double CosDeg(float* f) { return Math.Cos(Angle.DegToRad(f)); } public static double TanDeg(float* f) { return Math.Tan(Angle.DegToRad(f)); } public static double ASinDeg(float* f) { return Math.Asin(Angle.DegToRad(f)); } public static double ACosDeg(float* f) { return Math.Acos(Angle.DegToRad(f)); } public static double ATanDeg(float* f) { return Math.Atan(Angle.DegToRad(f)); } } }