/**
* Universidad de La Laguna
* Escuela Superior de Ingeniería y Tecnología
* Grado en Ingeniería Informática
* Procesadores de Lenguajes
*
* @author Juan Rodríguez Suárez
* @since Mar 04 2024
* @desc Contains some support functions to work with complex numbers.
*/
const Complex = require('complex.js');
Complex.prototype.factorial = function() {
if (this.im !== 0) throw new Error(`Imaginary part must be zero. Instead is ${this.im}`);
let n = this.re;
if (!Number.isInteger(n)) throw new Error(`Not an Integer number ${n}`);
if ( n < 0) throw new Error(`Factorial of negative number ${n}`);
let result = Complex(1);
if (n === 0) return result;
for (let i = 1; i <= n; i++) {
result = result.mul(i);
}
return Complex({re: result.re, im: this.im});
};
/**
* @brief Returns the maximum of two complex numbers
* @param {Complex} a - The first number
* @param {Complex} b - The second number
* @returns {Complex} The maximum
*/
const max = function(a, b) {
return a.re > b.re ? a : a.re === b.re && a.im >= b.im ? a : b;
}
/**
* @brief Returns the minimum of two complex numbers
* @param {Complex} a - The first number
* @param {Complex} b - The second number
* @returns {Complex} The minimum
*/
const min = function(a, b) {
return a.re < b.re ? a : a.re === b.re && a.im <= b.im ? a : b;
}
/**
* @brief Prints a complex number
* @param {Complex} x - The input
* @returns {Complex} The input
*/
const print = x => { console.log(x.toString()); return x; }
Complex.prototype.lessThan = function(other) {
return this.re < other.re || (this.re === other.re && this.im < other.im);
}
const OPERATORS = new Set(['add', 'sub', 'mul', 'div', 'pow', 'equals', 'neg', 'lessThan']);
let oldComplex = Object.create(null);
for (let op of OPERATORS) {
oldComplex[op] = Complex.prototype[op];
Complex.prototype[op] = function(other) {
try {
if (typeof other === 'function') return other[op](this);
if (typeof other === 'boolean') return this[op](Complex(Number(other)));
return oldComplex[op].call(this, other);
}
catch (e) {
throw new Error(`Complex numbers do not support the operation ${op} for ${other}\n${e}`);
}
}
}
for (let op of OPERATORS) {
Boolean.prototype[op] = function(other) {
return Complex(Number(this))[op](other);
}
Function.prototype[op] = function(other) {
switch (typeof other) {
case 'boolean':
return (...args) => this(...args)[op](Complex(Number(other)));
case 'object':
if (other instanceof Complex) {
return (...args) => this(...args)[op](other);
} else {
throw new Error(`Function does not support the operation ${op} for ${other}`);
}
case 'function':
try {
return (...args) => this(...args)[op](other(...args));
} catch (e) {
throw new Error(`Function does not support the operation ${op} for function ${other}`);
}
case 'undefined':
return (...args) => this(...args)[op]();
default:
throw new Error(`Unsupported ${op} for type ${typeof other}`);
}
}
}
module.exports = {
print,
max,
min,
Complex
};