From 47ff3c08f1ecb19c2b7ea24d68bbe2222cc76043 Mon Sep 17 00:00:00 2001 From: Aryan2727-debug <78311368+Aryan2727-debug@users.noreply.github.com> Date: Sat, 25 Oct 2025 13:33:29 +0530 Subject: [PATCH 1/2] Add test environment for problem 3bb58079-5c0a-4d86-b55d-45b0057883e4-v4 --- Dockerfile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..3ed7b301d4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM public.ecr.aws/x8v8d7g8/mars-base:latest + +WORKDIR /app + +ENV NODE_ENV=development + +COPY package*.json ./ + +RUN npm install +RUN npm install mocha + +COPY . . + +CMD ["/bin/bash"] From d3ae1d4ff1e769bf85ebe22876a120a151dab7b3 Mon Sep 17 00:00:00 2001 From: Aryan2727-debug <78311368+Aryan2727-debug@users.noreply.github.com> Date: Sat, 25 Oct 2025 14:10:12 +0530 Subject: [PATCH 2/2] feature_request: implemented mod() support for complex numbers --- src/function/arithmetic/mod.js | 108 +++++++++++++++++- .../function/arithmetic/mod.test.js | 47 +++++++- 2 files changed, 146 insertions(+), 9 deletions(-) diff --git a/src/function/arithmetic/mod.js b/src/function/arithmetic/mod.js index dee0b97e4a..5f3c8c9166 100644 --- a/src/function/arithmetic/mod.js +++ b/src/function/arithmetic/mod.js @@ -16,10 +16,11 @@ const dependencies = [ 'equalScalar', 'zeros', 'DenseMatrix', - 'concat' + 'concat', + 'Complex' ] -export const createMod = /* #__PURE__ */ factory(name, dependencies, ({ typed, config, round, matrix, equalScalar, zeros, DenseMatrix, concat }) => { +export const createMod = /* #__PURE__ */ factory(name, dependencies, ({ typed, config, round, matrix, equalScalar, zeros, DenseMatrix, concat, Complex }) => { const floor = createFloor({ typed, config, round, matrix, equalScalar, zeros, DenseMatrix }) const matAlgo02xDS0 = createMatAlgo02xDS0({ typed, equalScalar }) const matAlgo03xDSf = createMatAlgo03xDSf({ typed }) @@ -37,6 +38,10 @@ export const createMod = /* #__PURE__ */ factory(name, dependencies, ({ typed, c * * x - y * floor(x / y) * + * For complex numbers, the function implements Gaussian integer division. + * Given complex numbers w and z, it finds the Gaussian integer q (complex number + * with integer real and imaginary parts) such that the norm of (w - z*q) is minimized. + * * See https://en.wikipedia.org/wiki/Modulo_operation. * * Syntax: @@ -47,6 +52,7 @@ export const createMod = /* #__PURE__ */ factory(name, dependencies, ({ typed, c * * math.mod(8, 3) // returns 2 * math.mod(11, 2) // returns 1 + * math.mod(math.complex(5, 3), math.complex(2, 1)) // returns complex remainder * * function isOdd(x) { * return math.mod(x, 2) != 0 @@ -59,15 +65,19 @@ export const createMod = /* #__PURE__ */ factory(name, dependencies, ({ typed, c * * divide * - * @param {number | BigNumber | bigint | Fraction | Array | Matrix} x Dividend - * @param {number | BigNumber | bigint | Fraction | Array | Matrix} y Divisor - * @return {number | BigNumber | bigint | Fraction | Array | Matrix} Returns the remainder of `x` divided by `y`. + * @param {number | BigNumber | bigint | Fraction | Complex | Array | Matrix} x Dividend + * @param {number | BigNumber | bigint | Fraction | Complex | Array | Matrix} y Divisor + * @return {number | BigNumber | bigint | Fraction | Complex | Array | Matrix} Returns the remainder of `x` divided by `y`. */ return typed( name, { 'number, number': _modNumber, + 'Complex, Complex': function (x, y) { + return _modComplex(x, y) + }, + 'BigNumber, BigNumber': function (x, y) { return y.isZero() ? x : x.sub(y.mul(floor(x.div(y)))) }, @@ -114,4 +124,92 @@ export const createMod = /* #__PURE__ */ factory(name, dependencies, ({ typed, c // precision float approximation return (y === 0) ? x : x - y * floor(x / y) } + + /** + * Calculate the modulus of two complex numbers using Gaussian integer division + * @param {Complex} x dividend + * @param {Complex} y divisor + * @returns {Complex} remainder + * @private + */ + function _modComplex (x, y) { + // Handle division by zero + if (y.re === 0 && y.im === 0) { + return x + } + + // Calculate the exact quotient x/y + const quotient = x.div(y) + + // Round to the nearest Gaussian integer + const roundedQuotient = _roundToNearestGaussianInteger(quotient) + + // Calculate remainder: r = x - y * q + const remainder = x.sub(y.mul(roundedQuotient)) + + return remainder + } + + /** + * Round a complex number to the nearest Gaussian integer (complex number with integer real and imaginary parts) + * If there are ties, choose the one that results in the quotient with smallest norm + * @param {Complex} z complex number to round + * @returns {Complex} nearest Gaussian integer + * @private + */ + function _roundToNearestGaussianInteger (z) { + const re = z.re + const im = z.im + + // Get the four candidate Gaussian integers (floor and ceil for both parts) + const floorRe = Math.floor(re) + const ceilRe = Math.ceil(re) + const floorIm = Math.floor(im) + const ceilIm = Math.ceil(im) + + const candidates = [ + new Complex(floorRe, floorIm), + new Complex(floorRe, ceilIm), + new Complex(ceilRe, floorIm), + new Complex(ceilRe, ceilIm) + ] + + // Find the candidate with minimum distance to z + let bestCandidate = candidates[0] + let minDistance = _complexDistanceSquared(z, candidates[0]) + + for (let i = 1; i < candidates.length; i++) { + const distance = _complexDistanceSquared(z, candidates[i]) + if (distance < minDistance || + (distance === minDistance && _complexNormSquared(candidates[i]) < _complexNormSquared(bestCandidate))) { + minDistance = distance + bestCandidate = candidates[i] + } + } + + return bestCandidate + } + + /** + * Calculate the squared distance between two complex numbers + * @param {Complex} a first complex number + * @param {Complex} b second complex number + * @returns {number} squared distance + * @private + */ + function _complexDistanceSquared (a, b) { + const deltaRe = a.re - b.re + const deltaIm = a.im - b.im + return deltaRe * deltaRe + deltaIm * deltaIm + } + + /** + * Calculate the squared norm (modulus squared) of a complex number + * @param {Complex} z complex number + * @returns {number} squared norm + * @private + */ + function _complexNormSquared (z) { + return z.re * z.re + z.im * z.im + } }) diff --git a/test/unit-tests/function/arithmetic/mod.test.js b/test/unit-tests/function/arithmetic/mod.test.js index 5055a0f0b5..f2895a1fbd 100644 --- a/test/unit-tests/function/arithmetic/mod.test.js +++ b/test/unit-tests/function/arithmetic/mod.test.js @@ -112,10 +112,49 @@ describe('mod', function () { assert.deepStrictEqual(mod(false, bignumber(3)), bignumber(0)) }) - it('should throw an error if used on complex numbers', function () { - assert.throws(function () { mod(math.complex(1, 2), 3) }, TypeError) - assert.throws(function () { mod(3, math.complex(1, 2)) }, TypeError) - assert.throws(function () { mod(bignumber(3), math.complex(1, 2)) }, TypeError) + it('should calculate the modulus of two complex numbers', function () { + // Test basic complex modulus operations using Gaussian integer division + + // Simple case: mod(5+3i, 2+1i) should return -1+0i + approxDeepEqual(mod(math.complex(5, 3), math.complex(2, 1)), math.complex(-1, 0)) + + // Test with negative components + approxDeepEqual(mod(math.complex(-5, 3), math.complex(2, 1)), math.complex(-1, 0)) + + // Test pure imaginary case: mod(0+4i, 0+2i) should return 0+0i + approxDeepEqual(mod(math.complex(0, 4), math.complex(0, 2)), math.complex(0, 0)) + + // Test real divisor: mod(7+3i, 3+0i) should return 1+0i + approxDeepEqual(mod(math.complex(7, 3), math.complex(3, 0)), math.complex(1, 0)) + + // Test with division by zero (should return the dividend) + assert.deepStrictEqual(mod(math.complex(1, 2), math.complex(0, 0)), math.complex(1, 2)) + + // Test case where quotient is already a Gaussian integer + approxDeepEqual(mod(math.complex(4, 6), math.complex(2, 3)), math.complex(0, 0)) + + // Test with fractional results + const result1 = mod(math.complex(3, 4), math.complex(1, 1)) + assert(result1.re !== undefined && result1.im !== undefined) + + // Verify the fundamental property: w = z*q + r where norm(r) < norm(z) + const w = math.complex(7, 5) + const z = math.complex(3, 2) + const r = mod(w, z) + + // The remainder should have smaller norm than the divisor + const normR = r.re * r.re + r.im * r.im + const normZ = z.re * z.re + z.im * z.im + assert(normR <= normZ, `Remainder norm ${normR} should be <= divisor norm ${normZ}`) + }) + + it('should handle mixed complex and real arguments', function () { + // Math.js should automatically convert types for mixed operations + const result1 = mod(math.complex(5, 3), 2) + assert(result1.isComplex === true, 'Result should be complex') + + const result2 = mod(3, math.complex(2, 1)) + assert(result2.isComplex === true, 'Result should be complex') }) it('should convert string to number', function () {