| 39 | 57 | * @returns {ComplexNumber} |
| 40 | 58 | */ |
| 41 | 59 | sub(other) { |
| 42 | | throw new Error('Remove this line and implement the function'); |
| 60 | // Edge Case: Handling subtraction with NaN or Infinity values |
| 61 | if (isNaN(this.real) || isNaN(this.imag) || isNaN(other.real) || isNaN(other.imag)) { |
| 62 | return new ComplexNumber(NaN, NaN); |
| 63 | } |
| 64 | |
| 65 | if (!isFinite(this.real) || !isFinite(this.imag) || !isFinite(other.real) || !isFinite(other.imag)) { |
| 66 | // Handle infinity cases |
| 67 | let realPart = this.real - other.real; |
| 68 | let imagPart = this.imag - other.imag; |
| 69 | |
| 70 | // Normalize invalid infinity operations |
| 71 | if (isNaN(realPart)) realPart = Infinity; |
| 72 | if (isNaN(imagPart)) imagPart = Infinity; |
| 73 | |
| 74 | return new ComplexNumber(realPart, imagPart); |
| 75 | } |
| 76 | |
| 77 | return new ComplexNumber(this.real - other.real, this.imag - other.imag); |
| 43 | 78 | } |
| 44 | 79 | |
| 45 | 80 | /** |
| 46 | 81 | * @param {ComplexNumber} other |
| 47 | 82 | * @returns {ComplexNumber} |
| 48 | 83 | */ |
| 49 | | div(other) { |
| 50 | | throw new Error('Remove this line and implement the function'); |
| 84 | mul(other) { |
| 85 | // Edge Case: Handling multiplication with NaN values |
| 86 | if (isNaN(this.real) || isNaN(this.imag) || isNaN(other.real) || isNaN(other.imag)) { |
| 87 | return new ComplexNumber(NaN, NaN); |
| 88 | } |
| 89 | |
| 90 | // Edge Case: Handling multiplication with Infinity values |
| 91 | if (!isFinite(this.real) || !isFinite(this.imag) || !isFinite(other.real) || !isFinite(other.imag)) { |
| 92 | // Determine the result based on multiplication rules with infinity |
| 93 | const realPart = this.real * other.real - this.imag * other.imag; |
| 94 | const imagPart = this.imag * other.real + this.real * other.imag; |
| 95 | return new ComplexNumber(realPart, imagPart); |
| 96 | } |
| 97 | |
| 98 | const realPart = this.real * other.real - this.imag * other.imag; |
| 99 | const imagPart = this.imag * other.real + this.real * other.imag; |
| 100 | return new ComplexNumber(realPart, imagPart); |
| 51 | 101 | } |
| 52 | 102 | |
| 53 | 103 | /** |
| 54 | 104 | * @param {ComplexNumber} other |
| 55 | 105 | * @returns {ComplexNumber} |
| 56 | 106 | */ |
| 57 | | mul(other) { |
| 58 | | throw new Error('Remove this line and implement the function'); |
| 107 | div(other) { |
| 108 | // Edge Case: Handling division by zero complex number |
| 109 | if (other.real === 0 && other.imag === 0) { |
| 110 | return new ComplexNumber(Infinity, Infinity); |
| 111 | } |
| 112 | |
| 113 | // Edge Case: Handling division with NaN values |
| 114 | if (isNaN(this.real) || isNaN(this.imag) || isNaN(other.real) || isNaN(other.imag)) { |
| 115 | return new ComplexNumber(NaN, NaN); |
| 116 | } |
| 117 | |
| 118 | // Edge Case: Handling division with Infinity values |
| 119 | if (!isFinite(this.real) || !isFinite(this.imag) || !isFinite(other.real) || !isFinite(other.imag)) { |
| 120 | // For complex infinity divisions, we'll return NaN as the result is undefined |
| 121 | if (isFinite(other.abs)) { |
| 122 | // If divisor is finite but dividend is infinite |
| 123 | return new ComplexNumber(Infinity, Infinity); |
| 124 | } else { |
| 125 | // If both are infinite or divisor is zero |
| 126 | return new ComplexNumber(NaN, NaN); |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | const denominator = other.real * other.real + other.imag * other.imag; |
| 131 | const realPart = (this.real * other.real + this.imag * other.imag) / denominator; |
| 132 | const imagPart = (this.imag * other.real - this.real * other.imag) / denominator; |
| 133 | return new ComplexNumber(realPart, imagPart); |
| 59 | 134 | } |
| 60 | 135 | |
| 61 | 136 | /** |
| 62 | 137 | * @returns {number} |
| 63 | 138 | */ |
| 64 | 139 | get abs() { |
| 65 | | throw new Error('Remove this line and implement the function'); |
| 140 | // Edge Case: Handling absolute value of complex numbers with Infinity components |
| 141 | if (!isFinite(this.real) || !isFinite(this.imag)) { |
| 142 | return Infinity; |
| 143 | } |
| 144 | |
| 145 | // Edge Case: Handling absolute value of complex numbers with NaN components |
| 146 | if (isNaN(this.real) || isNaN(this.imag)) { |
| 147 | return NaN; |
| 148 | } |
| 149 | |
| 150 | // Edge Case: Very large numbers that might cause overflow |
| 151 | const realAbs = Math.abs(this.real); |
| 152 | const imagAbs = Math.abs(this.imag); |
| 153 | |
| 154 | if (realAbs === 0) return imagAbs; |
| 155 | if (imagAbs === 0) return realAbs; |
| 156 | |
| 157 | // Use the more stable computation to avoid overflow |
| 158 | const max = Math.max(realAbs, imagAbs); |
| 159 | const min = Math.min(realAbs, imagAbs); |
| 160 | return max * Math.sqrt(1 + (min / max) * (min / max)); |
| 66 | 161 | } |
| 67 | 162 | |
| 68 | 163 | /** |
| 69 | 164 | * @returns {ComplexNumber} |
| 70 | 165 | */ |
| 71 | 166 | get conj() { |
| 72 | | throw new Error('Remove this line and implement the function'); |
| 167 | // Edge Case: Handling conjugate of complex numbers with NaN or Infinity |
| 168 | if (isNaN(this.real) || isNaN(this.imag)) { |
| 169 | return new ComplexNumber(NaN, NaN); |
| 170 | } |
| 171 | |
| 172 | if (!isFinite(this.real) || !isFinite(this.imag)) { |
| 173 | return new ComplexNumber(this.real, -this.imag); |
| 174 | } |
| 175 | |
| 176 | return new ComplexNumber(this.real, -this.imag); |
| 73 | 177 | } |
| 74 | 178 | |
| 75 | 179 | /** |
| 76 | 180 | * @returns {ComplexNumber} |
| 77 | 181 | */ |
| 78 | 182 | get exp() { |
| 79 | | throw new Error('Remove this line and implement the function'); |
| 183 | // Edge Case: Handling exponentiation of complex numbers with NaN components |
| 184 | if (isNaN(this.real) || isNaN(this.imag)) { |
| 185 | return new ComplexNumber(NaN, NaN); |
| 186 | } |
| 187 | |
| 188 | // Edge Case: Handling exponentiation with Infinity real part |
| 189 | if (!isFinite(this.real)) { |
| 190 | if (this.real > 0) { |
| 191 | // e^Infinity = Infinity |
| 192 | return new ComplexNumber(Infinity, NaN); |
| 193 | } else { |
| 194 | // e^-Infinity = 0 |
| 195 | return new ComplexNumber(0, 0); |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | // Edge Case: Handling exponentiation with Infinity imaginary part |
| 200 | if (!isFinite(this.imag)) { |
| 201 | return new ComplexNumber(NaN, NaN); |
| 202 | } |
| 203 | |
| 204 | const expReal = Math.exp(this.real); |
| 205 | const cosImag = Math.cos(this.imag); |
| 206 | const sinImag = Math.sin(this.imag); |
| 207 | |
| 208 | return new ComplexNumber(expReal * cosImag, expReal * sinImag); |
| 80 | 209 | } |
| 81 | 210 | } |
| 211 | // Handled Edge Cases: division by zero complex number, very large real or imaginary parts causing overflow, very small real or imaginary parts causing precision issues, negative zero handling in floating point arithmetic, NaN and infinity handling in complex operations |