spwn 0.0.6

A language for Geometry Dash triggers
Documentation
#[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()
    }

}