public static void Main(){
ComplexInt z1 = 7479 + 10667 * i;
ComplexInt z2 = 5274 + 9553 * i;
ComplexFraction zF1 = new ComplexFraction(z1, z2);
Console.WriteLine(z2 * z2);
Console.WriteLine(z2.SquaredNorm());
Console.WriteLine(zF1.reciprocal());
Console.WriteLine((ComplexDouble) zF1);
Console.WriteLine((ComplexDouble) zF1.reciprocal());
public class ComplexDouble {
public double A { get; set; }
public ImaginaryDouble B { get; set; }
public ComplexDouble(double real_, double imag_) {
public ComplexDouble(double real_, ImaginaryDouble imag_) {
public static implicit operator ComplexDouble(int real_) => new ComplexDouble(real_, 0);
public static implicit operator ComplexDouble(ImaginaryInt imag_) => new ComplexDouble(0, imag_);
public static implicit operator ComplexDouble(float real_) => new ComplexDouble(real_, 0);
public static implicit operator ComplexDouble(ImaginaryFloat imag_) => new ComplexDouble(0, imag_);
public static implicit operator ComplexDouble(double real_) => new ComplexDouble(real_, 0);
public static implicit operator ComplexDouble(ImaginaryDouble imag_) => new ComplexDouble(0, imag_);
public static implicit operator ComplexDouble(ComplexInt z) => new ComplexDouble(z.A, z.B);
public static implicit operator ComplexDouble(ComplexFloat z) => new ComplexDouble(z.A, z.B);
public static explicit operator int(ComplexDouble z) => (int)Math.Sqrt(z.SquaredNorm());
public static explicit operator float(ComplexDouble z) => (float)Math.Sqrt(z.SquaredNorm());
public static explicit operator double(ComplexDouble z) => (double)Math.Sqrt(z.SquaredNorm());
public static explicit operator ComplexInt(ComplexDouble z) => new ComplexInt((int)z.A, (int)z.B);
public static explicit operator ComplexFloat(ComplexDouble z) => new ComplexFloat((float)z.A, (float)z.B);
public static ComplexDouble operator +(ComplexDouble z1, ComplexDouble z2) => new ComplexDouble(z1.A + z2.A, z1.B + z2.B);
public static ComplexDouble operator ++(ComplexDouble z) {
return z + new ComplexDouble(Math.Abs(z.A) / ((double)z), ComplexMath.Abs(z.B) / ((double)z));
public static ComplexDouble operator +(ComplexDouble z) => z;
public static ComplexDouble operator -(ComplexDouble z1, ComplexDouble z2) => new ComplexDouble(z1.A - z2.A, z1.B - z2.B);
public static ComplexDouble operator --(ComplexDouble z) {
return z - new ComplexDouble(Math.Abs(z.A) / ((double)z), ComplexMath.Abs(z.B) / ((double)z));
public static ComplexDouble operator -(ComplexDouble z) => new ComplexDouble(-z.A, -z.B);
public static ComplexDouble operator *(ComplexDouble z1, ComplexDouble z2) => new ComplexDouble(z1.A * z2.A + z1.B * z2.B, z1.B * z2.A + z1.A * z2.B);
public static ComplexDouble operator /(ComplexDouble z1, ComplexDouble z2) => new ComplexDouble((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexDouble operator %(ComplexDouble z1, ComplexDouble z2) => z1 - ((ComplexInt)(z1 / z2)) * z2;
public ComplexDouble Conjugate() => new ComplexDouble(A, -B);
public double SquaredNorm() => A * A - B * B;
public double SquaredNormSigns() => Math.Abs(A) * A + Math.Abs(B.Value) * B.Value;
public static bool operator ==(ComplexDouble z1, ComplexDouble z2) => z1.A == z2.A && z1.B == z2.B;
public static bool operator !=(ComplexDouble z1, ComplexDouble z2) => !(z1 == z2);
public static bool operator >=(ComplexDouble z1, ComplexDouble z2) => z1.SquaredNorm() >= z2.SquaredNorm();
public static bool operator <=(ComplexDouble z1, ComplexDouble z2) => z1.SquaredNorm() <= z2.SquaredNorm();
public static bool operator >(ComplexDouble z1, ComplexDouble z2) => z1.SquaredNorm() > z2.SquaredNorm();
public static bool operator <(ComplexDouble z1, ComplexDouble z2) => z1.SquaredNorm() < z2.SquaredNorm();
public override bool Equals(object obj) {
if (obj is ComplexDouble z) {
return new ComplexDouble(A, B) == z;
public void GetRealAndImag(out double a, out double b) {
public override int GetHashCode() => (int)A & (int)B;
public void Deconstruct(out double real_, out ImaginaryDouble imag_) {
public override string ToString() {
string sign = B < 0 ? "-" : (B > 0 ? "+" : "-");
return B == 0 ? "0" : $"{B}";
return B == 0 ? $"{A}" : Math.Abs(B.Value) == 1 ? $"{A} {sign} i" : $"{A} {sign} {Math.Abs(B.Value)}i";
public class ImaginaryDouble {
public double Value { get; set; }
private ImaginaryDouble(double imag_) {
public static implicit operator ImaginaryDouble(double num) => new ImaginaryDouble(num);
public static implicit operator ImaginaryDouble(ImaginaryInt z) => new ImaginaryDouble(z.Value);
public static implicit operator ImaginaryDouble(ImaginaryFloat z) => new ImaginaryDouble(z.Value);
public static explicit operator int(ImaginaryDouble num) => (int)num.Value;
public static explicit operator float(ImaginaryDouble num) => (float)num.Value;
public static explicit operator double(ImaginaryDouble num) => num.Value;
public static explicit operator decimal(ImaginaryDouble num) => (decimal)num.Value;
public static explicit operator ImaginaryInt(ImaginaryDouble num) => (int)num.Value;
public static explicit operator ImaginaryFloat(ImaginaryDouble num) => (float)num.Value;
public static ImaginaryDouble operator +(ImaginaryDouble i1, ImaginaryDouble i2) => new ImaginaryDouble(i1.Value + i2.Value);
public static ComplexDouble operator +(ImaginaryDouble i, double r) => new ComplexDouble(r, i);
public static ComplexDouble operator +(double r, ImaginaryDouble i) => new ComplexDouble(r, i);
public static ImaginaryDouble operator +(ImaginaryDouble i) => i;
public static ImaginaryDouble operator ++(ImaginaryDouble z1) => new ImaginaryDouble(z1.Value + 1);
public static ImaginaryDouble operator -(ImaginaryDouble i1, ImaginaryDouble i2) => new ImaginaryDouble(i1.Value - i2.Value);
public static ComplexDouble operator -(ImaginaryDouble i, double r) => new ComplexDouble(-r, i);
public static ComplexDouble operator -(double r, ImaginaryDouble i) => new ComplexDouble(r, -i);
public static ImaginaryDouble operator --(ImaginaryDouble z1) => new ImaginaryDouble(z1.Value - 1);
public static ImaginaryDouble operator -(ImaginaryDouble i) => new ImaginaryDouble(-i.Value);
public static double operator *(ImaginaryDouble i1, ImaginaryDouble i2) => -i1.Value * i2.Value;
public static ImaginaryDouble operator *(ImaginaryDouble i, double other) => new ImaginaryDouble(i.Value * other);
public static ImaginaryDouble operator *(double other, ImaginaryDouble i) => new ImaginaryDouble(i.Value * other);
public static double operator /(ImaginaryDouble i1, ImaginaryDouble i2) => i1.Value / i2.Value;
public static ImaginaryDouble operator /(ImaginaryDouble i, double other) => new ImaginaryDouble(i.Value / other);
public static ImaginaryDouble operator /(double other, ImaginaryDouble i) => new ImaginaryDouble(-other / i.Value);
public static bool operator <(ImaginaryDouble i1, ImaginaryDouble i2) => i1.Value < i2.Value;
public static bool operator >(ImaginaryDouble i1, ImaginaryDouble i2) => i1.Value > i2.Value;
public static bool operator ==(ImaginaryDouble i1, ImaginaryDouble i2) => i1.Value == i2.Value;
public static bool operator !=(ImaginaryDouble i1, ImaginaryDouble i2) => i1.Value != i2.Value;
public static bool operator <=(ImaginaryDouble i1, ImaginaryDouble i2) => i1.Value <= i2.Value;
public static bool operator >=(ImaginaryDouble i1, ImaginaryDouble i2) => i1.Value >= i2.Value;
public override bool Equals(object obj) => obj is ImaginaryDouble @doubleObj && Value == @doubleObj;
public override int GetHashCode() => (int)Value;
public override string ToString() => Value == 0 ? "0" : (Math.Abs(Value) == 1 ? $"{(Value < 0 ? "-" : "")}i" : $"{(Value < 0 ? "-" : "")}{Math.Abs(Value)}i");
public class ComplexFloat {
public float A { get; set; }
public ImaginaryFloat B { get; set; }
public ComplexFloat(float real_, float imag_) {
public ComplexFloat(float real_, ImaginaryFloat imag_) {
public static implicit operator ComplexFloat(int real_) => new ComplexFloat(real_, 0);
public static implicit operator ComplexFloat(ImaginaryInt imag_) => new ComplexFloat(0, imag_);
public static implicit operator ComplexFloat(float real_) => new ComplexFloat(real_, 0);
public static implicit operator ComplexFloat(ImaginaryFloat imag_) => new ComplexFloat(0, imag_);
public static implicit operator ComplexFloat(ComplexInt z) => new ComplexFloat(z.A, z.B);
public static explicit operator int(ComplexFloat z) => (int)Math.Sqrt(z.SquaredNorm());
public static explicit operator float(ComplexFloat z) => (float)Math.Sqrt(z.SquaredNorm());
public static explicit operator double(ComplexFloat z) => Math.Sqrt(z.SquaredNorm());
public static explicit operator ComplexInt(ComplexFloat z) => new ComplexInt((int)z.A, (int)z.B);
public static ComplexFloat operator +(ComplexFloat z1, ComplexFloat z2) => new ComplexFloat(z1.A + z2.A, z1.B + z2.B);
public static ComplexDouble operator +(ComplexFloat z1, ComplexDouble z2) => new ComplexDouble(z1.A + z2.A, z1.B + z2.B);
public static ComplexDouble operator +(ComplexDouble z1, ComplexFloat z2) => new ComplexDouble(z1.A + z2.A, z1.B + z2.B);
public static ComplexFloat operator ++(ComplexFloat z) {
return z + new ComplexFloat(Math.Abs(z.A) / ((float)z), (float)(ComplexMath.Abs(z.B) / ((float)z)));
public static ComplexFloat operator +(ComplexFloat z) => z;
public static ComplexFloat operator -(ComplexFloat z1, ComplexFloat z2) => new ComplexFloat(z1.A - z2.A, z1.B - z2.B);
public static ComplexDouble operator -(ComplexFloat z1, ComplexDouble z2) => new ComplexDouble(z1.A - z2.A, z1.B - z2.B);
public static ComplexDouble operator -(ComplexDouble z1, ComplexFloat z2) => new ComplexDouble(z1.A - z2.A, z1.B - z2.B);
public static ComplexFloat operator --(ComplexFloat z) {
return z - new ComplexFloat(Math.Abs(z.A) / ((float)z), (float)(ComplexMath.Abs(z.B) / ((float)z)));
public static ComplexFloat operator -(ComplexFloat z) => new ComplexFloat(-z.A, -z.B);
public static ComplexFloat operator *(ComplexFloat z1, ComplexFloat z2) => new ComplexFloat(z1.A * z2.A + z1.B * z2.B, z1.B * z2.A + z1.A * z2.B);
public static ComplexDouble operator *(ComplexFloat z1, ComplexDouble z2) => new ComplexDouble(z1.A * z2.A + z1.B * z2.B, z1.B * z2.A + z1.A * z2.B);
public static ComplexDouble operator *(ComplexDouble z1, ComplexFloat z2) => new ComplexDouble(z1.A * z2.A + z1.B * z2.B, z1.B * z2.A + z1.A * z2.B);
public static ComplexFloat operator /(ComplexFloat z1, ComplexFloat z2) => new ComplexFloat((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexDouble operator /(ComplexFloat z1, ComplexDouble z2) => new ComplexDouble((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexDouble operator /(ComplexDouble z1, ComplexFloat z2) => new ComplexDouble((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexFloat operator %(ComplexFloat z1, ComplexFloat z2) => z1 - ((ComplexInt)(z1 / z2)) * z2;
public ComplexDouble Conjugate() => new ComplexDouble(A, -B);
public float SquaredNorm() => A * A - B * B;
public float SquaredNormSigns() => Math.Abs(A) * A + Math.Abs(B.Value) * B.Value;
public static bool operator ==(ComplexFloat z1, ComplexFloat z2) => z1.A == z2.A && z1.B == z2.B;
public static bool operator !=(ComplexFloat z1, ComplexFloat z2) => !(z1 == z2);
public static bool operator >=(ComplexFloat z1, ComplexFloat z2) => z1.SquaredNorm() >= z2.SquaredNorm();
public static bool operator <=(ComplexFloat z1, ComplexFloat z2) => z1.SquaredNorm() <= z2.SquaredNorm();
public static bool operator >(ComplexFloat z1, ComplexFloat z2) => z1.SquaredNorm() > z2.SquaredNorm();
public static bool operator <(ComplexFloat z1, ComplexFloat z2) => z1.SquaredNorm() < z2.SquaredNorm();
public override bool Equals(object obj) {
if (obj is ComplexDouble z) {
return new ComplexDouble(A, B) == z;
public void GetRealAndImag(out float a, out float b) {
public override int GetHashCode() => (int)A & (int)B;
public void Deconstruct(out float real_, out ImaginaryFloat imag_) {
public override string ToString() {
string sign = B < 0 ? "-" : (B > 0 ? "+" : "-");
return B == 0 ? "0" : $"{B}";
return B == 0 ? $"{A}" : Math.Abs(B.Value) == 1 ? $"{A} {sign} i" : $"{A} {sign} {Math.Abs(B.Value)}i";
public class ImaginaryFloat {
public float Value { get; set; }
private ImaginaryFloat(float imag_) {
public static implicit operator ImaginaryFloat(float num) => new ImaginaryFloat(num);
public static implicit operator ImaginaryFloat(ImaginaryInt num) => new ImaginaryFloat(num.Value);
public static explicit operator int(ImaginaryFloat num) => (int)num.Value;
public static explicit operator float(ImaginaryFloat num) => num.Value;
public static explicit operator double(ImaginaryFloat num) => num.Value;
public static explicit operator decimal(ImaginaryFloat num) => (decimal)num.Value;
public static ImaginaryFloat operator +(ImaginaryFloat i1, ImaginaryFloat i2) => new ImaginaryFloat(i1.Value + i2.Value);
public static ComplexFloat operator +(ImaginaryFloat i, float r) => new ComplexFloat(r, i);
public static ComplexFloat operator +(float r, ImaginaryFloat i) => new ComplexFloat(r, i);
public static ComplexDouble operator +(ImaginaryFloat i, double r) => new ComplexDouble(r, i);
public static ComplexDouble operator +(double r, ImaginaryFloat i) => new ComplexDouble(r, i);
public static ImaginaryFloat operator ++(ImaginaryFloat z1) => new ImaginaryFloat(z1.Value + 1);
public static ImaginaryFloat operator +(ImaginaryFloat i) => i;
public static ImaginaryFloat operator -(ImaginaryFloat i1, ImaginaryFloat i2) => new ImaginaryFloat(i1.Value - i2.Value);
public static ComplexFloat operator -(ImaginaryFloat i, float r) => new ComplexFloat(-r, i);
public static ComplexFloat operator -(float r, ImaginaryFloat i) => new ComplexFloat(r, -i);
public static ComplexDouble operator -(ImaginaryFloat i, double r) => new ComplexDouble(-r, i);
public static ComplexDouble operator -(double r, ImaginaryFloat i) => new ComplexDouble(r, -i);
public static ImaginaryFloat operator --(ImaginaryFloat z1) => new ImaginaryFloat(z1.Value - 1);
public static ImaginaryFloat operator -(ImaginaryFloat i) => new ImaginaryFloat(-i.Value);
public static float operator *(ImaginaryFloat i1, ImaginaryFloat i2) => -i1.Value * i2.Value;
public static ImaginaryFloat operator *(ImaginaryFloat i, float other) => new ImaginaryFloat(i.Value * other);
public static ImaginaryFloat operator *(float other, ImaginaryFloat i) => new ImaginaryFloat(i.Value * other);
public static ImaginaryDouble operator *(ImaginaryFloat i, double other) => i.Value * other;
public static ImaginaryDouble operator *(double other, ImaginaryFloat i) => i.Value * other;
public static float operator /(ImaginaryFloat i1, ImaginaryFloat i2) => i1.Value / i2.Value;
public static ImaginaryFloat operator /(ImaginaryFloat i, float other) => new ImaginaryFloat(i.Value / other);
public static ImaginaryFloat operator /(float other, ImaginaryFloat i) => new ImaginaryFloat(-other / i.Value);
public static ImaginaryDouble operator /(ImaginaryFloat i, double other) => i.Value / other;
public static ImaginaryDouble operator /(double other, ImaginaryFloat i) => -other / i.Value;
public static bool operator <(ImaginaryFloat i1, ImaginaryFloat i2) => i1.Value < i2.Value;
public static bool operator >(ImaginaryFloat i1, ImaginaryFloat i2) => i1.Value > i2.Value;
public static bool operator ==(ImaginaryFloat i1, ImaginaryFloat i2) => i1.Value == i2.Value;
public static bool operator !=(ImaginaryFloat i1, ImaginaryFloat i2) => i1.Value != i2.Value;
public static bool operator <=(ImaginaryFloat i1, ImaginaryFloat i2) => i1.Value <= i2.Value;
public static bool operator >=(ImaginaryFloat i1, ImaginaryFloat i2) => i1.Value >= i2.Value;
public override bool Equals(object obj) => obj is ImaginaryDouble @doubleObj && Value == @doubleObj;
public override int GetHashCode() => (int)Value;
public override string ToString() => Value == 0 ? "0" : (Math.Abs(Value) == 1 ? $"{(Value < 0 ? "-" : "")}i" : $"{(Value < 0 ? "-" : "")}{Math.Abs(Value)}i");
public class ComplexInt {
public int A { get; set; }
public ImaginaryInt B { get; set; }
public ComplexInt(int a_, int b_) {
public ComplexInt(int a_, ImaginaryInt b_) {
public static implicit operator ComplexInt(int d) => new ComplexInt(d, 0);
public static implicit operator ComplexInt(ImaginaryInt d) => new ComplexInt(0, d);
public static explicit operator int(ComplexInt d) => (int)Math.Sqrt(d.A * ((double)d.A) + ((double)d.B) * ((double)d.B));
public static explicit operator float(ComplexInt d) => (float)Math.Sqrt(d.A * ((double)d.A) + ((double)d.B) * ((double)d.B));
public static explicit operator double(ComplexInt d) => Math.Sqrt(d.A * ((double)d.A) + ((double)d.B) * ((double)d.B));
public static ComplexInt operator +(ComplexInt z1, ComplexInt z2) => new ComplexInt(z1.A + z2.A, z1.B + z2.B);
public static ComplexFloat operator +(ComplexInt z1, ComplexFloat z2) => new ComplexFloat(z1.A + z2.A, z1.B + z2.B);
public static ComplexFloat operator +(ComplexFloat z1, ComplexInt z2) => new ComplexFloat(z1.A + z2.A, z1.B + z2.B);
public static ComplexDouble operator +(ComplexInt z1, ComplexDouble z2) => new ComplexDouble(z1.A + z2.A, z1.B + z2.B);
public static ComplexDouble operator +(ComplexDouble z1, ComplexInt z2) => new ComplexDouble(z1.A + z2.A, z1.B + z2.B);
public static ComplexInt operator ++(ComplexInt z1) {
return z1 + (ComplexInt)(new ComplexDouble((int)(Math.Abs(z1.A) * 1.99999999), (int)(z1.B * 1.99999999)) / ((double)z1));
public static ComplexInt operator +(ComplexInt i) => i;
public static ComplexInt operator --(ComplexInt z1) => z1 - new ComplexInt((int)(Math.Abs(z1.A) * 1.99999999), (int)(z1.B * 1.99999999)) / ((int)z1);
public static ComplexInt operator -(ComplexInt z1, ComplexInt z2) => new ComplexInt(z1.A - z2.A, z1.B - z2.B);
public static ComplexFloat operator -(ComplexInt z1, ComplexFloat z2) => new ComplexFloat(z1.A - z2.A, z1.B - z2.B);
public static ComplexFloat operator -(ComplexFloat z1, ComplexInt z2) => new ComplexFloat(z1.A - z2.A, z1.B - z2.B);
public static ComplexDouble operator -(ComplexInt z1, ComplexDouble z2) => new ComplexDouble(z1.A - z2.A, z1.B - z2.B);
public static ComplexDouble operator -(ComplexDouble z1, ComplexInt z2) => new ComplexDouble(z1.A - z2.A, z1.B - z2.B);
public static ComplexInt operator -(ComplexInt z1) => new ComplexInt(-z1.A, -z1.B);
public static ComplexInt operator *(ComplexInt z1, ComplexInt z2) => new ComplexInt(z1.B * z2.B + z1.A * z2.A, z1.A * z2.B + z1.B * z2.A);
public static ComplexFloat operator *(ComplexInt z1, ComplexFloat z2) => new ComplexFloat(z1.B * z2.B + z1.A * z2.A, z1.A * z2.B + z1.B * z2.A);
public static ComplexFloat operator *(ComplexFloat z1, ComplexInt z2) => new ComplexFloat(z1.B * z2.B + z1.A * z2.A, z1.A * z2.B + z1.B * z2.A);
public static ComplexDouble operator *(ComplexInt z1, ComplexDouble z2) => new ComplexDouble(z1.B * z2.B + z1.A * z2.A, z1.A * z2.B + z1.B * z2.A);
public static ComplexDouble operator *(ComplexDouble z1, ComplexInt z2) => new ComplexDouble(z1.B * z2.B + z1.A * z2.A, z1.A * z2.B + z1.B * z2.A);
public static ComplexInt operator /(ComplexInt z1, ComplexInt z2) => new ComplexInt((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexFloat operator /(ComplexInt z1, ComplexFloat z2) => new ComplexFloat((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexFloat operator /(ComplexFloat z1, ComplexInt z2) => new ComplexFloat((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexDouble operator /(ComplexInt z1, ComplexDouble z2) => new ComplexDouble((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexDouble operator /(ComplexDouble z1, ComplexInt z2) => new ComplexDouble((z1.A * z2.A - z1.B * z2.B) / z2.SquaredNorm(), (z1.B * z2.A - z1.A * z2.B) / z2.SquaredNorm());
public static ComplexInt operator %(ComplexInt z1, ComplexInt z2) => z1 - (z1 / z2) * z2;
public static ComplexInt operator <<(ComplexInt z, int d) => new ComplexInt(z.A << d, z.B << d);
public static ComplexInt operator >>(ComplexInt z, int d) => new ComplexInt(z.A >> d, z.B >> d);
public ComplexInt Conjugate() => new ComplexInt(A, -B);
public int SquaredNorm() => A * A - B * B;
public int SquaredNormSigns() => Math.Abs(A) * A + Math.Abs(B.Value) * B.Value;
public static bool operator ==(ComplexInt z1, ComplexInt z2) => z1.A == z2.A && z1.B == z2.B;
public static bool operator !=(ComplexInt z1, ComplexInt z2) => !(z1 == z2);
public static bool operator >=(ComplexInt z1, ComplexInt z2) => z1.SquaredNorm() >= z2.SquaredNorm();
public static bool operator <=(ComplexInt z1, ComplexInt z2) => z1.SquaredNorm() <= z2.SquaredNorm();
public static bool operator >(ComplexInt z1, ComplexInt z2) => z1.SquaredNorm() > z2.SquaredNorm();
public static bool operator <(ComplexInt z1, ComplexInt z2) => z1.SquaredNorm() < z2.SquaredNorm();
public override bool Equals(object obj) {
if (obj is ComplexInt z) {
return new ComplexInt(A, B) == z;
public void GetRealAndImag(out int a, out int b) {
public override int GetHashCode() => A & (int)B;
public void Deconstruct(out int real_, out ImaginaryInt imag_) {
public override string ToString() {
string sign = B < 0 ? "-" : (B > 0 ? "+" : "-");
return B == 0 ? "0" : $"{B}";
return B == 0 ? $"{A}" : Math.Abs(B.Value) == 1 ? $"{A} {sign} i" : $"{A} {sign} {Math.Abs(B.Value)}i";
public class ImaginaryInt {
public int Value { get; set; }
private ImaginaryInt(int b_) {
public static implicit operator ImaginaryInt(int d) => new ImaginaryInt(d);
public static explicit operator ImaginaryInt(float a) => new ImaginaryInt((int)a);
public static explicit operator ImaginaryInt(double a) => new ImaginaryInt((int)a);
public static explicit operator int(ImaginaryInt a) => a.Value;
public static explicit operator float(ImaginaryInt a) => a.Value;
public static explicit operator double(ImaginaryInt a) => a.Value;
public static ImaginaryInt operator +(ImaginaryInt a1, ImaginaryInt a2) => a1.Value + a2.Value;
public static ComplexInt operator +(ImaginaryInt a, int r) => new ComplexInt(r, a.Value);
public static ComplexInt operator +(int r, ImaginaryInt a) => new ComplexInt(r, a.Value);
public static ComplexFloat operator +(ImaginaryInt a, float r) => new ComplexFloat(r, a.Value);
public static ComplexFloat operator +(float r, ImaginaryInt a) => new ComplexFloat(r, a.Value);
public static ComplexDouble operator +(ImaginaryInt a, double r) => new ComplexDouble(r, a.Value);
public static ComplexDouble operator +(double r, ImaginaryInt a) => new ComplexDouble(r, a.Value);
public static ImaginaryInt operator +(ImaginaryInt i) => i;
public static ImaginaryInt operator ++(ImaginaryInt z1) => z1.Value + 1;
public static ImaginaryInt operator -(ImaginaryInt a1, ImaginaryInt a2) => a1.Value - a2.Value;
public static ComplexInt operator -(ImaginaryInt a, int r) => new ComplexInt(-r, a.Value);
public static ComplexInt operator -(int r, ImaginaryInt a) => new ComplexInt(r, -a.Value);
public static ComplexFloat operator -(ImaginaryInt a, float r) => new ComplexFloat(-r, a.Value);
public static ComplexFloat operator -(float r, ImaginaryInt a) => new ComplexFloat(r, -a.Value);
public static ComplexDouble operator -(ImaginaryInt a, double r) => new ComplexDouble(-r, a.Value);
public static ComplexDouble operator -(double r, ImaginaryInt a) => new ComplexDouble(r, -a.Value);
public static ImaginaryInt operator --(ImaginaryInt z1) => z1.Value - 1;
public static ImaginaryInt operator -(ImaginaryInt a) => -a.Value;
public static int operator *(ImaginaryInt a1, ImaginaryInt a2) => -a1.Value * a2.Value;
public static ImaginaryInt operator *(int d, ImaginaryInt a) => a.Value * d;
public static ImaginaryInt operator *(ImaginaryInt a, int d) => a.Value * d;
public static ImaginaryFloat operator *(float d, ImaginaryInt a) => a.Value * d;
public static ImaginaryFloat operator *(ImaginaryInt a, float d) => a.Value * d;
public static ImaginaryDouble operator *(double d, ImaginaryInt a) => a.Value * d;
public static ImaginaryDouble operator *(ImaginaryInt a, double d) => a.Value * d;
public static int operator /(ImaginaryInt a1, ImaginaryInt a2) => a1.Value / a2.Value;
public static ImaginaryInt operator /(ImaginaryInt a, int d) => a.Value / d;
public static ImaginaryInt operator /(int d, ImaginaryInt a) => -d / a.Value;
public static ImaginaryFloat operator /(ImaginaryInt a, float d) => a.Value / d;
public static ImaginaryFloat operator /(float d, ImaginaryInt a) => -d / a.Value;
public static ImaginaryDouble operator /(ImaginaryInt a, double d) => a.Value / d;
public static ImaginaryDouble operator /(double d, ImaginaryInt a) => -d / a.Value;
public static ImaginaryInt operator <<(ImaginaryInt a, int d) => a.Value << d;
public static ImaginaryInt operator >>(ImaginaryInt a, int d) => a.Value >> d;
public static bool operator ==(ImaginaryInt a1, ImaginaryInt a2) => a1.Value == a2.Value;
public static bool operator !=(ImaginaryInt a1, ImaginaryInt a2) => a1.Value != a2.Value;
public static bool operator >(ImaginaryInt a1, ImaginaryInt a2) => a1.Value > a2.Value;
public static bool operator <(ImaginaryInt a1, ImaginaryInt a2) => a1.Value < a2.Value;
public static bool operator >=(ImaginaryInt a1, ImaginaryInt a2) => a1.Value >= a2.Value;
public static bool operator <=(ImaginaryInt a1, ImaginaryInt a2) => a1.Value <= a2.Value;
public override bool Equals(object obj) => obj is ImaginaryInt intObj && Value == intObj;
public override int GetHashCode() => Value;
public override string ToString() => Value == 0 ? "0" : (Math.Abs(Value) == 1 ? $"{(Value < 0 ? "-" : "")}i" : $"{(Value < 0 ? "-" : "")}{Math.Abs(Value)}i");
public class ComplexFraction{
public readonly ComplexInt num;
private readonly ComplexInt originalNum;
private readonly ComplexInt originalDen;
public ComplexFraction(ComplexInt num, ComplexInt den){
this.num = (num * den.Conjugate());
largeDen = den.SquaredNorm();
while(largeDen > Int32.MaxValue){
this.den = (int)(largeDen);
int commonFactor = GCD(GCD(this.num.A, this.den), this.num.B.Value);
this.num /= commonFactor;
this.den /= commonFactor;
originalNum /= commonFactor;
originalDen /= commonFactor;
public static implicit operator ComplexFraction(int n) => new ComplexFraction(n, 1);
public static implicit operator ComplexFraction(ImaginaryInt n) => new ComplexFraction(n, 1);
public static implicit operator ComplexFraction(ComplexInt n) => new ComplexFraction(n, 1);
public static explicit operator ComplexDouble(ComplexFraction n) => n.num / (n.den * 1.0);
public static explicit operator ComplexFloat(ComplexFraction n) => n.num / (n.den * 1f);
public static ComplexFraction operator +(ComplexFraction a, ComplexFraction b) => new ComplexFraction(a.num * b.den + a.den * b.num, a.den * b.den);
public static ComplexFraction operator ++(ComplexFraction a) => a + 1;
public static ComplexFraction operator +(ComplexFraction a) => a;
public static ComplexFraction operator -(ComplexFraction a, ComplexFraction b) => new ComplexFraction(a.num * b.den - a.den * b.num, a.den * b.den);
public static ComplexFraction operator --(ComplexFraction a) => a - 1;
public static ComplexFraction operator -(ComplexFraction a) => new ComplexFraction(-a.num, -a.den);
public static ComplexFraction operator *(ComplexFraction a, ComplexFraction b) => new ComplexFraction(a.num * b.num, a.den * b.den);
public static ComplexFraction operator /(ComplexFraction a, ComplexFraction b) => new ComplexFraction(a.num * b.den, a.den * b.num);
public ComplexFraction reciprocal() => new ComplexFraction(originalDen, originalNum);
public static int GCD(int a, int b) => b == 0 ? a : GCD(b, a % b);
public override string ToString() => $"({num}){(den == 1 ? "" : $" / {den}")}";
public class ComplexMath {
public readonly ImaginaryInt I = 1;
public static int Abs(ImaginaryInt i) => Math.Abs(i.Value);
public static double Abs(ImaginaryDouble i) => Math.Abs(i.Value);
public static double Abs(ComplexDouble z) => (float)z;
public static ComplexDouble Log(ComplexDouble z) => Math.Log(z.SquaredNorm()) / 2 + (ImaginaryDouble)Math.Atan2(z.B.Value, z.A);
public static ComplexDouble Log(ComplexDouble z, ComplexDouble log_base) => Log(z) / Log(log_base);
public static ComplexDouble Exp(ComplexDouble z) => Math.Pow(Math.E, z.A) * new ComplexDouble(Math.Cos(z.B.Value), Math.Sin(z.B.Value));
public static ComplexDouble Pow(ComplexDouble z1, ComplexDouble z2) => Exp(Log(z1) * z2);
public static ComplexDouble Pow(ImaginaryDouble z, int n) {
return Math.Pow(z.Value, n) * (n % 4 == 0 ? 1 : -1);
return (ImaginaryDouble)(Math.Pow(z.Value, n) * (n % 4 == 1 ? 1 : -1));
public static ComplexDouble Sqrt(ComplexDouble z) {
return (ImaginaryDouble)Math.Sqrt(-z.A);
public static ComplexDouble Root(ComplexDouble z, int n) => Pow(z, 1.0 / n);
public static ComplexDouble Root(ComplexDouble z, int n, int rootID) => Pow(z, 1.0 / n) * Exp(((ImaginaryDouble) rootID * Math.PI * 2) / n);
public static ComplexDouble Sin(ComplexDouble z) => new ComplexDouble(Math.Sin(z.A) * Math.Cosh(z.B.Value), Math.Cos(z.A) * Math.Sinh(z.B.Value));
public static ComplexDouble Sinh(ComplexDouble z) => new ComplexDouble(Math.Sinh(z.A) * Math.Cos(z.B.Value), Math.Cosh(z.A) * Math.Sin(z.B.Value));
public static ComplexDouble Cos(ComplexDouble z) => new ComplexDouble(Math.Cos(z.A) * Math.Cosh(z.B.Value), -Math.Sin(z.A) * Math.Sinh(z.B.Value));
public static ComplexDouble Cosh(ComplexDouble z) => new ComplexDouble(Math.Cosh(z.A) * Math.Cos(z.B.Value), Math.Sinh(z.A) * Math.Sin(z.B.Value));
public static ComplexDouble Tan(ComplexDouble z) => Sin(z) / Cos(z);
public static ComplexDouble Tanh(ComplexDouble z) => Sinh(z) / Cosh(z);
public static ComplexInt Round(ComplexDouble z) => new ComplexInt((int)Math.Round(z.A), (int)Math.Round(z.B.Value));
public static ComplexInt Floor(ComplexDouble z) => new ComplexInt((int)z.A, (int)z.B.Value);
public static ComplexInt Ceiling(ComplexDouble z) => new ComplexInt((int)Math.Ceiling(z.A), (int)Math.Ceiling(z.B.Value));
public static ComplexInt IntSqrt(ComplexInt z) {
return (ComplexInt)(z.A >= 0 ? Math.Sqrt(z.A) : Math.Sqrt(-z.A));
return (ComplexInt)(Pow(z, 0.5) + (0.00000000001 + (ImaginaryDouble)0.00000000001));