#[no_std]
type @complex
PI = 3.14159265358979323846
impl @complex {
new: (re, im = 0) {
return @complex::{re, im}
},
from_polar: (r, phi) {
return @complex::new($.cos(phi), $.sin(phi)) * r
},
I: (coef: @number = 1) {
return @complex::new(0,coef)
},
zero: () {
return @complex::new(0, 0)
},
print: (self) {
if self.re == 0 && self.im == 0 { $.print(0); return }
let c_string = ""
if self.re != 0 {
c_string += self.re as @string
if self.im > 0 {
c_string += "+"
}
}
if self.im != 0 {
c_string += (self.im as @string) + "i"
}
$.print(c_string)
},
polar: (self) {
return [self.abs(), self.phase()];
},
_assign_: (self, other: @number | @complex) {
if other.type == @number {
self.re = other
self.im = 0
} else if other.type == @complex {
self.re = other.re
self.im = other.im
}
},
_plus_: (self, other: @number | @complex) {
let new = self;
if other.type == @number {
new.re += other;
} else if other.type == @complex {
new.re += other.re;
new.im += other.im;
}
return new;
},
_add_: (self, other: @number | @complex) {
if other.type == @number {
self.re += other;
} else if other.type == @complex {
self.re += other.re;
self.im += other.im;
}
},
_minus_: (self, other: @number | @complex) {
let new = self;
if other.type == @number {
new.re -= other;
} else if other.type == @complex {
new.re -= other.re;
new.im -= other.im;
}
return new;
},
_subtract_: (self, other: @number | @complex) {
if other.type == @number {
self.re -= other;
} else if other.type == @complex {
self.re -= other.re;
self.im -= other.im;
}
},
_times_: (self, other: @number | @complex) {
let new = self;
if other.type == @number {
new.re *= other;
new.im *= other;
} else if other.type == @complex {
new.re = self.re * other.re - self.im * other.im;
new.im = self.re * other.im + self.im * other.re;
}
return new;
},
_multiply_: (self, other: @number | @complex) {
if other.type == @number {
self.re *= other;
self.im *= other;
} else if other.type == @complex {
prev_re = self.re
self.re = self.re * other.re - self.im * other.im;
self.im = prev_re * other.im + self.im * other.re;
}
},
_divided_by_: (self, other: @number | @complex) {
let new = self;
if other.type == @number {
new.re /= other;
new.im /= other;
} else if other.type == @complex {
new = self * other.conj() / other.abs_sq()
}
return new;
},
_divide_: (self, other: @number | @complex) {
if other.type == @number {
self.re /= other;
self.im /= other;
} else if other.type == @complex {
self = self * other.conj() / other.abs_sq()
}
},
_pow_: (self, other: @complex | @number) {
if other.type == @number {
r = self.abs()
angle = self.arg()
return @complex::from_polar(r ^ other, angle * other)
} else {
return self ^ other.re * (@complex::I() * self.ln() * other.im).exp()
}
},
_exponate_: (self, other: @complex | @number) {
result = self ^ other
self.re = result.re
self.im = result.im
},
_mod_: (self, other: @complex | @number) {
let operand = @complex::zero()
if other.type == @number {
operand = @complex::new(other)
} else {
operand = other
}
let result = self / operand
result.re = $.floor(result.re)
result.im = $.floor(result.im)
return self - operand * result
},
_modulate_: (self, other: @complex | @number) {
result = self % other
self.re = result.re
self.im = result.im
},
_equal_: (self, other: @complex | @number) {
if other.type == @number {
return self.re == other && self.im == 0
} else {
return self.re == other.re && self.im == other.im
}
},
conj: (self) {
return @complex::new(self.re,-self.im)
},
abs: (self) {
return $.sqrt(self.re**2 + self.im**2)
},
abs_sq: (self) {
return self.re**2 + self.im**2
},
arg: (self) {
return $.atan2(self.im,self.re)
},
phase: (self) { //alias ig
return arg(self)
},
invert: (self) {
return @complex::new(1) / self
},
sqrt: (self) {
return self ** 0.5
},
ln: (self) {
return @complex::new($.ln(self.abs()), self.arg())
},
log: (self, base: @complex | @number) {
if base.type == @number {
return self.ln() / @complex::new(base).ln()
}
return self.ln() / base.ln()
},
exp: (self) {
return @complex::from_polar(1, self.im) * $.exp(self.re)
},
//
sin: (self) {
return @complex::new(
$.sin(self.re) * $.cosh(self.im),
$.cos(self.re) * $.sinh(self.im)
);
},
cos: (self) {
return (@complex::new(PI/2) - self).sin()
},
tan: (self) {
return self.sin() / self.cos();
},
cot: (self) {
return self.tan().invert();
},
sec: (self) {
return self.cos().invert();
},
csc: (self) {
return self.sin().invert();
},
sinh: (self) {
return (@complex::I() * self).sin() * @complex::I(-1)
},
cosh: (self) {
return (@complex::I() * self).cos()
},
tanh: (self) {
return (@complex::I() * self).tan() * @complex::I(-1)
},
coth: (self) {
return (@complex::I() * self).cot() * @complex::I()
},
sech: (self) {
return (@complex::I() * self).sec()
},
csch: (self) {
return (@complex::I() * self).csc() * @complex::I()
},
asin: (self) {
return @complex::I() * ((@complex::new(1) - self^2).sqrt() - @complex::I() * self ).ln()
},
acos: (self) {
return @complex::new(PI/2) - self.asin()
},
atan: (self) {
return @complex::new(0,-1/2) * ( (@complex::new(1) + @complex::I()*self) / (@complex::new(1) - @complex::I()*self) ).ln()
},
acot: (self) {
return self.invert().atan()
},
asec: (self) {
return self.invert().acos()
},
acsc: (self) {
return self.invert().asin()
}
}