You can write your own complex decimal struct. The way I would do this is to look at the System.Numerics.Complex - Struct and copy the definitions, so that you have the same functionality and naming. You can leave out some functions if you're not going to need them, like maybe trigonometric functions, conversion operators, or even the polar coordinate functionality.
I implemented some of the functionality in the code below. Note that you may want to add the interfaces, and maybe some input checking for the functions.
public struct DecComplex
{
// Member variables.
private decimal real;
private decimal imaginary;
// Read-only properties.
public decimal Real { get { return real; } }
public decimal Imaginary { get { return imaginary; } }
// Constructors.
public DecComplex(decimal real, decimal imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
public DecComplex(double real, double imaginary)
{
this.real = (decimal)real;
this.imaginary = (decimal)imaginary;
}
// Arithmetic operators.
public static DecComplex operator -(DecComplex value)
{
return new DecComplex(-value.real, -value.imaginary);
}
public static DecComplex operator +(DecComplex left, DecComplex right)
{
return new DecComplex(left.real + right.real, left.imaginary + right.imaginary);
}
public static DecComplex operator -(DecComplex left, DecComplex right)
{
return new DecComplex(left.real - right.real, left.imaginary - right.imaginary);
}
public static DecComplex operator *(DecComplex left, DecComplex right)
{
return new DecComplex(left.real * right.real - left.imaginary * right.imaginary, left.real * right.imaginary + left.imaginary * right.real);
}
public static DecComplex operator /(DecComplex left, DecComplex right)
{
var denominator = right.real * right.real + right.imaginary * right.imaginary;
var real = (left.real / denominator * right.real + left.imaginary / denominator * right.imaginary);
var imaginary = (left.imaginary / denominator * right.real - left.real / denominator * right.imaginary);
return new DecComplex(real, imaginary);
}
public static DecComplex operator /(decimal left, DecComplex right)
{
var denominator = right.real * right.real + right.imaginary * right.imaginary;
var real = left * right.real / denominator;
var imaginary = - left * right.imaginary / denominator;
return new DecComplex(real, imaginary);
}
// Conversion operators.
public static explicit operator System.Numerics.Complex(DecComplex value)
{
return new System.Numerics.Complex((double)value.Real, (double)value.Imaginary);
}
// Methods.
public static decimal Abs(DecComplex value)
{
return Sqrt(value.real * value.real + value.imaginary * value.imaginary);
}
public static DecComplex Pow(DecComplex value, int exponent)
{
if (exponent == 0)
return new DecComplex(1.0, 0.0);
var result = value;
for (var i = 1; i < exponent; i++)
{
result = result * value;
}
if (exponent < 0)
return 1.0M / result;
else
return result;
}
public override string ToString()
{
return string.Format("({0}; {1})", this.real, this.imaginary);
}
// Sqrt-Method for the decimal class (by SLenik, http://stackoverflow.com/a/6755197/4469336).
public static decimal Sqrt(decimal x, decimal epsilon = 0.0M)
{
if (x < 0) throw new OverflowException("Cannot calculate square root from a negative number");
decimal current = (decimal)Math.Sqrt((double)x), previous;
do
{
previous = current;
if (previous == 0.0M) return 0;
current = (previous + x / previous) / 2;
}
while (Math.Abs(previous - current) > epsilon);
return current;
}
}