const Complex = require('./complex.js')
/**
* Calculates the factorial of a given number.
*
* @param {number} num - The number to calculate the factorial of.
* @returns {Complex} The factorial of the given number.
* @throws {Error} If the number has a non-zero imaginary part.
* @throws {Error} If the number is not an integer.
* @throws {Error} If the number is negative.
*/
const factorial = function(num) {
if (num?.im && num?.im !== 0) throw new Error(`Imaginary part must be zero. Instead is ${num.im}`);
let n = Number(num?.re) || Number(num);
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: num.im});
};
/**
* Returns the maximum of two complex numbers.
*
* @param {Object} a - The first complex number.
* @param {number} a.re - The real part of the first complex number.
* @param {number} a.im - The imaginary part of the first complex number.
* @param {Object} b - The second complex number.
* @param {number} b.re - The real part of the second complex number.
* @param {number} b.im - The imaginary part of the second complex number.
* @returns {Object} - The maximum complex number.
*/
const max = function(a, b) {
if (a.re > b.re) return a;
if (a.re < b.re) return b;
// If we reached here is a.re === b.re
if (a.im > b.im) return a;
if (a.im < b.im) return b;
return a;
}
/**
* Returns the minimum of two complex numbers.
*
* @param {Complex} a - The first complex number.
* @param {Complex} b - The second complex number.
* @returns {Complex} The minimum of the two complex numbers.
*/
const min = function(a, b) {
if (a.re < b.re) return a;
if (a.re > b.re) return b;
// If we reached here is a.re === b.re
if (a.im < b.im) return a;
if (a.im > b.im) return b;
return a;
}
/**
* Prints the given values to the console.
* @param {...*} x - The values to be printed.
* @returns {Array} - An array containing the printed values.
*/
const print = (...x) => { console.log(...x); return x; }
/**
* Writes the provided arguments to the console.
* @param {...*} x - The values to be written to the console.
* @returns {Array} - An array containing the string representations of the provided values.
*/
const write = (...x) => { let r = x.map(s => s.toString()); console.log(...r); return r; }
module.exports = {
Complex,
print,
write,
factorial,
max,
min
};