{"version":3,"sources":["../../../src/core/decimal/decimal-utils.ts"],"sourcesContent":["/**\r\n * Decimal Utility Functions\r\n *\r\n * Core utility functions for decimal arithmetic operations following KISS principles.\r\n * All functions use BigInt-only calculations and avoid JavaScript Number class.\r\n */\r\nimport { DecimalError } from './decimal';\r\n\r\n/**\r\n * Result of precision and scale validation\r\n */\r\nexport interface ValidationResult {\r\n    valid: boolean;\r\n    reason?: string;\r\n}\r\n\r\n/**\r\n * Cache for powers of 10\r\n */\r\nconst POW10_CACHE: Map<number, bigint> = new Map();\r\n\r\n/**\r\n * Gets a power of 10 as BigInt, using cache for performance.\r\n * @param exponent The exponent for the power of 10\r\n * @returns 10^exponent as BigInt\r\n */\r\nexport function getPow10(exponent: number): bigint {\r\n    if (exponent < 0) {\r\n        throw new Error('Exponent must be non-negative');\r\n    }\r\n    if (!POW10_CACHE.has(exponent)) {\r\n        POW10_CACHE.set(exponent, 10n ** BigInt(exponent));\r\n    }\r\n    return POW10_CACHE.get(exponent)!;\r\n}\r\n\r\n/**\r\n * Scales up a coefficient by multiplying by powers of 10.\r\n * Effectively moves the decimal point to the right.\r\n *\r\n * @param coefficient The BigInt coefficient to scale up\r\n * @param scaleFactor The number of decimal places to scale up (must be non-negative)\r\n * @returns The scaled up coefficient\r\n * @throws Error if scaleFactor is negative\r\n */\r\nexport function scaleUp(coefficient: bigint, scaleFactor: number): bigint {\r\n    if (scaleFactor < 0) {\r\n        throw new Error(`Scale factor must be non-negative, got ${scaleFactor}`);\r\n    }\r\n    if (scaleFactor === 0) {\r\n        return coefficient;\r\n    }\r\n    return coefficient * getPow10(scaleFactor);\r\n}\r\n\r\n/**\r\n * Scales down a coefficient by dividing by powers of 10 with basic truncation.\r\n * Effectively moves the decimal point to the left.\r\n *\r\n * @param coefficient The BigInt coefficient to scale down\r\n * @param scaleFactor The number of decimal places to scale down (must be non-negative)\r\n * @returns The scaled down coefficient (truncated, not rounded)\r\n * @throws Error if scaleFactor is negative\r\n */\r\nexport function scaleDown(coefficient: bigint, scaleFactor: number): bigint {\r\n    if (scaleFactor < 0) {\r\n        throw new Error('Scale factor must be non-negative');\r\n    }\r\n\r\n    if (scaleFactor === 0) {\r\n        return coefficient;\r\n    }\r\n\r\n    return coefficient / getPow10(scaleFactor);\r\n}\r\n\r\n/**\r\n * Rounds a coefficient using round-half-up behavior when scaling down.\r\n *\r\n * @param coefficient The BigInt coefficient to round\r\n * @param currentScale The current scale of the coefficient\r\n * @param targetScale The target scale after rounding\r\n * @returns The rounded coefficient\r\n * @throws Error if targetScale is negative or currentScale is negative\r\n */\r\nexport function roundHalfUp(coefficient: bigint, currentScale: number, targetScale: number): bigint {\r\n    if (currentScale < 0 || targetScale < 0) {\r\n        throw new Error('Scales must be non-negative');\r\n    }\r\n\r\n    if (currentScale <= targetScale) {\r\n        // Scale up by padding zeros\r\n        return scaleUp(coefficient, targetScale - currentScale);\r\n    }\r\n\r\n    // Scale down with rounding\r\n    const scaleDiff = currentScale - targetScale;\r\n    const divisor = getPow10(scaleDiff);\r\n    const quotient = coefficient / divisor;\r\n    const remainder = coefficient % divisor;\r\n\r\n    // Round half up logic\r\n    const halfDivisor = divisor / 2n;\r\n    const absRemainder = remainder < 0n ? -remainder : remainder;\r\n\r\n    if (absRemainder >= halfDivisor) {\r\n        return quotient + (coefficient >= 0n ? 1n : -1n);\r\n    }\r\n\r\n    return quotient;\r\n}\r\n\r\n/**\r\n * Rounds a coefficient using ceiling behavior (always round up) when scaling down.\r\n *\r\n * @param coefficient The BigInt coefficient to round\r\n * @param currentScale The current scale of the coefficient\r\n * @param targetScale The target scale after rounding\r\n * @returns The ceiling rounded coefficient\r\n * @throws Error if targetScale is negative or currentScale is negative\r\n */\r\nexport function ceilRound(coefficient: bigint, currentScale: number, targetScale: number): bigint {\r\n    if (currentScale < 0 || targetScale < 0) {\r\n        throw new Error('Scales must be non-negative');\r\n    }\r\n\r\n    if (currentScale <= targetScale) {\r\n        // Scale up by padding zeros\r\n        return scaleUp(coefficient, targetScale - currentScale);\r\n    }\r\n\r\n    // Scale down with ceiling\r\n    const scaleDiff = currentScale - targetScale;\r\n    const divisor = getPow10(scaleDiff);\r\n    const quotient = coefficient / divisor;\r\n    const remainder = coefficient % divisor;\r\n\r\n    // Ceiling logic: if there's any remainder and coefficient is positive, round up\r\n    // If coefficient is negative and there's remainder, don't round (towards zero)\r\n    if (remainder !== 0n && coefficient > 0n) {\r\n        return quotient + 1n;\r\n    }\r\n\r\n    return quotient;\r\n}\r\n\r\n/**\r\n * Rounds a coefficient using floor behavior (always round down) when scaling down.\r\n *\r\n * @param coefficient The BigInt coefficient to round\r\n * @param currentScale The current scale of the coefficient\r\n * @param targetScale The target scale after rounding\r\n * @returns The floor rounded coefficient\r\n * @throws Error if targetScale is negative or currentScale is negative\r\n */\r\nexport function floorRound(coefficient: bigint, currentScale: number, targetScale: number): bigint {\r\n    if (currentScale < 0 || targetScale < 0) {\r\n        throw new Error('Scales must be non-negative');\r\n    }\r\n\r\n    if (currentScale <= targetScale) {\r\n        // Scale up by padding zeros\r\n        return scaleUp(coefficient, targetScale - currentScale);\r\n    }\r\n\r\n    // Scale down with floor\r\n    const scaleDiff = currentScale - targetScale;\r\n    const divisor = getPow10(scaleDiff);\r\n    const quotient = coefficient / divisor;\r\n    const remainder = coefficient % divisor;\r\n\r\n    // Floor logic: if there's any remainder and coefficient is negative, round down\r\n    // If coefficient is positive and there's remainder, don't round (towards zero)\r\n    if (remainder !== 0n && coefficient < 0n) {\r\n        return quotient - 1n;\r\n    }\r\n\r\n    return quotient;\r\n}\r\n\r\n/**\r\n * Formats a BigInt coefficient as a decimal string with the specified scale and precision.\r\n * Uses normalization utilities for proper coefficient handling and decimal point placement.\r\n *\r\n * @param coefficient The BigInt coefficient to format\r\n * @param scale The number of decimal places\r\n * @param precision Optional. The total number of significant digits. If provided, validates that the coefficient fits within precision.\r\n * @returns The formatted decimal string\r\n * @throws Error if the coefficient exceeds the specified precision\r\n */\r\nexport function formatBigIntAsDecimal(coefficient: bigint, scale: number, precision?: number): string {\r\n    // Handle zero case\r\n    if (coefficient === 0n) {\r\n        return scale > 0 ? `0.${'0'.repeat(scale)}` : '0';\r\n    }\r\n\r\n    // Validate precision and scale if precision is provided\r\n    if (precision !== undefined) {\r\n        const validationResult = validatePrecisionScale(coefficient, precision, scale);\r\n        if (!validationResult.valid) {\r\n            throw new DecimalError(`Coefficient validation failed: ${validationResult.reason}`);\r\n        }\r\n    }\r\n\r\n    // Extract sign and work with absolute value\r\n    const sign = coefficient < 0n ? '-' : '';\r\n    const absCoeff = coefficient < 0n ? -coefficient : coefficient;\r\n    let coeffStr = absCoeff.toString();\r\n\r\n    // Pad with leading zeros if needed\r\n    while (coeffStr.length <= scale) {\r\n        coeffStr = '0' + coeffStr;\r\n    }\r\n\r\n    // Split into integer and fractional parts\r\n    const integerPart = coeffStr.slice(0, coeffStr.length - scale) || '0';\r\n    const fractionalPart = scale > 0 ? coeffStr.slice(-scale) : '';\r\n\r\n    // Validate that the formatted number fits within precision constraints\r\n    // This is a check on the significant digits in the formatted result\r\n    if (precision !== undefined) {\r\n        // Count significant digits (ignore leading zeros in integer part)\r\n        const significantIntegerDigits = integerPart === '0' ? 0 : integerPart.replace(/^0+/, '').length;\r\n\r\n        // For fractional part, count all digits except trailing zeros if integer part is 0\r\n        let significantFractionalDigits = fractionalPart.length;\r\n        if (significantIntegerDigits === 0) {\r\n            // For values less than 1, ignore leading zeros in fractional part\r\n            const significantFractionalPart = fractionalPart.replace(/^0+/, '');\r\n            significantFractionalDigits = significantFractionalPart.length || 0;\r\n        }\r\n\r\n        const totalSignificantDigits = significantIntegerDigits + significantFractionalDigits;\r\n\r\n        if (totalSignificantDigits > precision) {\r\n            throw new DecimalError(`Formatted value exceeds specified precision (${precision}). Value has ${totalSignificantDigits} significant digits.`);\r\n        }\r\n    }\r\n\r\n    return sign + integerPart + (scale > 0 ? '.' + fractionalPart : '');\r\n}\r\n\r\n/**\r\n * Fits a coefficient to the specified precision by truncating and rounding if necessary.\r\n * Uses the specified rounding mode to handle precision overflow.\r\n *\r\n * @param coefficient The BigInt coefficient to fit to precision\r\n * @param precision The maximum number of significant digits allowed\r\n * @param scale The current scale of the coefficient\r\n * @param roundingMode The rounding mode to use ('round', 'ceil', 'floor')\r\n * @returns The coefficient fitted to the specified precision\r\n * @throws DecimalError if the coefficient cannot be fitted to the precision\r\n */\r\nexport function fitToPrecision(\r\n    coefficient: bigint,\r\n    precision: number,\r\n    scale: number,\r\n    roundingMode: 'round' | 'ceil' | 'floor' = 'round'\r\n): bigint {\r\n    // Handle zero coefficient\r\n    if (coefficient === 0n) {\r\n        return 0n;\r\n    }\r\n\r\n    // Get absolute value for digit counting (inlined for performance)\r\n    const absCoeff = coefficient < 0n ? -coefficient : coefficient;\r\n    const coeffStr = absCoeff.toString();\r\n\r\n    // If already fits within precision, return unchanged\r\n    if (coeffStr.length <= precision) {\r\n        return coefficient;\r\n    }\r\n\r\n    // Calculate how many digits to remove\r\n    const excessDigits = coeffStr.length - precision;\r\n\r\n    // If excess digits are more than scale, we can't fit without losing integer part\r\n    if (excessDigits > scale) {\r\n        // We would lose digits from the integer part, which is not allowed\r\n        throw new DecimalError(\r\n            `Cannot fit coefficient to precision ${precision}. ` +\r\n            `Coefficient has ${coeffStr.length} digits with scale ${scale}. ` +\r\n            `Would lose ${excessDigits - scale} digits from integer part.`\r\n        );\r\n    }\r\n\r\n    // Calculate target scale after truncation\r\n    const targetScale = scale - excessDigits;\r\n\r\n    // Apply appropriate rounding based on mode\r\n    let result: bigint;\r\n    switch (roundingMode) {\r\n        case 'round':\r\n            result = roundHalfUp(coefficient, scale, targetScale);\r\n            break;\r\n        case 'ceil':\r\n            result = ceilRound(coefficient, scale, targetScale);\r\n            break;\r\n        case 'floor':\r\n            result = floorRound(coefficient, scale, targetScale);\r\n            break;\r\n        default:\r\n            throw new DecimalError(`Invalid rounding mode: ${roundingMode}`);\r\n    }\r\n\r\n    // Verify the result fits within precision\r\n    const resultStr = (result < 0n ? -result : result).toString();\r\n    if (resultStr.length > precision) {\r\n        // This can happen with rounding (e.g., 999 rounded to 2 digits becomes 1000)\r\n        // In this case, we need to adjust scale again\r\n        if (targetScale > 0) {\r\n            // Use the same rounding mode for consistency\r\n            switch (roundingMode) {\r\n                case 'round':\r\n                    return roundHalfUp(result, targetScale, targetScale - 1);\r\n                case 'ceil':\r\n                    return ceilRound(result, targetScale, targetScale - 1);\r\n                case 'floor':\r\n                    return floorRound(result, targetScale, targetScale - 1);\r\n                default:\r\n                    throw new DecimalError(`Invalid rounding mode: ${roundingMode}`);\r\n            }\r\n        } else {\r\n            // Special case for rounding that causes overflow (e.g., 9999 -> 10000)\r\n            // If the result ends with zeros, we can remove them to fit precision\r\n            if (result % 10n === 0n) {\r\n                // Count trailing zeros\r\n                let tempResult = result;\r\n                let zerosToRemove = 0;\r\n                while (tempResult % 10n === 0n && zerosToRemove < resultStr.length - precision) {\r\n                    tempResult = tempResult / 10n;\r\n                    zerosToRemove++;\r\n                }\r\n\r\n                if ((tempResult < 0n ? -tempResult : tempResult).toString().length <= precision) {\r\n                    return tempResult;\r\n                }\r\n            }\r\n\r\n            throw new DecimalError(\r\n                `Rounding resulted in precision overflow. ` +\r\n                `Result has ${resultStr.length} digits, but precision is ${precision}.`\r\n            );\r\n        }\r\n    }\r\n\r\n    return result;\r\n}\r\n\r\n/**\r\n * Validates if a coefficient fits within the specified precision and scale constraints.\r\n *\r\n * @param coefficient The BigInt coefficient to validate\r\n * @param precision The maximum number of significant digits allowed\r\n * @param scale The number of decimal places\r\n * @returns A ValidationResult object indicating if the coefficient is valid and why if not\r\n */\r\nexport function validatePrecisionScale(\r\n    coefficient: bigint,\r\n    precision: number,\r\n    scale: number\r\n): ValidationResult {\r\n    // Validate precision and scale parameters\r\n    if (precision <= 0) {\r\n        return { valid: false, reason: 'Precision must be positive' };\r\n    }\r\n\r\n    if (scale < 0) {\r\n        return { valid: false, reason: 'Scale must be non-negative' };\r\n    }\r\n\r\n    if (scale > precision) {\r\n        return { valid: false, reason: 'Scale must be less than or equal to precision' };\r\n    }\r\n\r\n    // Handle zero coefficient (always valid)\r\n    if (coefficient === 0n) {\r\n        return { valid: true };\r\n    }\r\n\r\n    // Get absolute value for digit counting (inlined for performance)\r\n    const absCoeff = coefficient < 0n ? -coefficient : coefficient;\r\n    const coeffStr = absCoeff.toString();\r\n\r\n    // Check if coefficient fits within precision\r\n    if (coeffStr.length > precision) {\r\n        return {\r\n            valid: false,\r\n            reason: `Coefficient has ${coeffStr.length} digits, exceeding precision of ${precision}`\r\n        };\r\n    }\r\n\r\n    // Calculate integer part digits\r\n    const integerDigits = coeffStr.length - scale;\r\n\r\n    // If integer part is negative, we have leading zeros in fractional part\r\n    if (integerDigits < 0) {\r\n        // This is valid, as it means we have leading zeros in fractional part\r\n        // For example: 0.001 with scale 3 has integerDigits = -2\r\n        return { valid: true };\r\n    }\r\n\r\n    // If we get here, the coefficient fits within precision and scale constraints\r\n    return { valid: true };\r\n}\r\n\r\n/**\r\n * Result of operand alignment\r\n */\r\nexport interface AlignedOperands {\r\n    a: bigint;\r\n    b: bigint;\r\n    targetScale: number;\r\n    scaleAdjustment: number;\r\n}\r\n\r\n/**\r\n * Aligns two decimal operands to have the same scale for arithmetic operations.\r\n * Scales up the operand with the smaller scale to match the larger scale.\r\n *\r\n * @param aCoefficient First operand coefficient\r\n * @param aScale Scale of the first operand\r\n * @param bCoefficient Second operand coefficient\r\n * @param bScale Scale of the second operand\r\n * @param maxScale Optional maximum scale to limit the result scale (default: no limit)\r\n * @param roundingMode The rounding mode to use when scaling down ('round', 'ceil', 'floor')\r\n * @returns An AlignedOperands object with aligned coefficients and the target scale\r\n */\r\nexport function alignOperands(\r\n    aCoefficient: bigint,\r\n    aScale: number,\r\n    bCoefficient: bigint,\r\n    bScale: number,\r\n    maxScale?: number,\r\n    roundingMode: 'round' | 'ceil' | 'floor' = 'round'\r\n): AlignedOperands {\r\n    // Handle zero operands\r\n    if (aCoefficient === 0n) {\r\n        return {\r\n            a: 0n,\r\n            b: bCoefficient,\r\n            targetScale: bScale,\r\n            scaleAdjustment: 0\r\n        };\r\n    }\r\n\r\n    if (bCoefficient === 0n) {\r\n        return {\r\n            a: aCoefficient,\r\n            b: 0n,\r\n            targetScale: aScale,\r\n            scaleAdjustment: 0\r\n        };\r\n    }\r\n\r\n    // Determine target scale (the larger of the two scales)\r\n    let targetScale = Math.max(aScale, bScale);\r\n\r\n    // Apply maximum scale constraint if provided\r\n    if (maxScale !== undefined && targetScale > maxScale) {\r\n        targetScale = maxScale;\r\n    }\r\n\r\n    // Calculate scale adjustments\r\n    const aAdjustment = targetScale - aScale;\r\n    const bAdjustment = targetScale - bScale;\r\n\r\n    // Scale up operands as needed\r\n    let adjustedA = aCoefficient;\r\n    let adjustedB = bCoefficient;\r\n\r\n    if (aAdjustment > 0) {\r\n        adjustedA = scaleUp(aCoefficient, aAdjustment);\r\n    }\r\n\r\n    if (bAdjustment > 0) {\r\n        adjustedB = scaleUp(bCoefficient, bAdjustment);\r\n    }\r\n\r\n    // If maxScale is less than either original scale, we need to scale down\r\n    if (maxScale !== undefined) {\r\n        if (aScale > maxScale) {\r\n            // Use the specified rounding mode\r\n            switch (roundingMode) {\r\n                case 'round':\r\n                    adjustedA = roundHalfUp(aCoefficient, aScale, maxScale);\r\n                    break;\r\n                case 'ceil':\r\n                    adjustedA = ceilRound(aCoefficient, aScale, maxScale);\r\n                    break;\r\n                case 'floor':\r\n                    adjustedA = floorRound(aCoefficient, aScale, maxScale);\r\n                    break;\r\n                default:\r\n                    throw new DecimalError(`Invalid rounding mode: ${roundingMode}`);\r\n            }\r\n        }\r\n\r\n        if (bScale > maxScale) {\r\n            // Use the specified rounding mode\r\n            switch (roundingMode) {\r\n                case 'round':\r\n                    adjustedB = roundHalfUp(bCoefficient, bScale, maxScale);\r\n                    break;\r\n                case 'ceil':\r\n                    adjustedB = ceilRound(bCoefficient, bScale, maxScale);\r\n                    break;\r\n                case 'floor':\r\n                    adjustedB = floorRound(bCoefficient, bScale, maxScale);\r\n                    break;\r\n                default:\r\n                    throw new DecimalError(`Invalid rounding mode: ${roundingMode}`);\r\n            }\r\n        }\r\n    }\r\n\r\n    return {\r\n        a: adjustedA,\r\n        b: adjustedB,\r\n        targetScale,\r\n        scaleAdjustment: Math.max(aAdjustment, bAdjustment)\r\n    };\r\n}\r\n\r\n/**\r\n * RDBMS-compliant precision and scale calculation result\r\n */\r\nexport interface RdbmsArithmeticResult {\r\n    precision: number;\r\n    scale: number;\r\n}\r\n\r\n/**\r\n * Calculates the result precision and scale for addition/subtraction operations\r\n * following RDBMS/SQL standards.\r\n *\r\n * RDBMS Standard for Addition/Subtraction:\r\n * - Result Scale = max(scale1, scale2)\r\n * - Result Precision = max(precision1 - scale1, precision2 - scale2) + result_scale + 1\r\n *\r\n * The +1 accounts for potential carry in addition or borrow in subtraction.\r\n *\r\n * @param precision1 Precision of first operand\r\n * @param scale1 Scale of first operand\r\n * @param precision2 Precision of second operand\r\n * @param scale2 Scale of second operand\r\n * @returns RdbmsArithmeticResult with calculated precision and scale\r\n * @throws DecimalError if parameters are invalid\r\n */\r\nexport function calculateAdditionResultPrecisionScale(\r\n    precision1: number,\r\n    scale1: number,\r\n    precision2: number,\r\n    scale2: number\r\n): RdbmsArithmeticResult {\r\n    // Validate input parameters\r\n    if (precision1 <= 0 || precision2 <= 0) {\r\n        throw new DecimalError('Precision must be positive');\r\n    }\r\n    if (scale1 < 0 || scale2 < 0) {\r\n        throw new DecimalError('Scale must be non-negative');\r\n    }\r\n    if (scale1 > precision1 || scale2 > precision2) {\r\n        throw new DecimalError('Scale must not exceed precision');\r\n    }\r\n\r\n    // Calculate result scale (maximum of input scales)\r\n    const resultScale = Math.max(scale1, scale2);\r\n\r\n    // Calculate integer digits for each operand\r\n    const integerDigits1 = precision1 - scale1;\r\n    const integerDigits2 = precision2 - scale2;\r\n\r\n    // Calculate result precision\r\n    // max(integer_digits) + result_scale + 1 (for potential carry/borrow)\r\n    const maxIntegerDigits = Math.max(integerDigits1, integerDigits2);\r\n    const resultPrecision = maxIntegerDigits + resultScale + 1;\r\n\r\n    return {\r\n        precision: resultPrecision,\r\n        scale: resultScale\r\n    };\r\n}\r\n\r\n/**\r\n * Calculates the result precision and scale for multiplication operations\r\n * following RDBMS/SQL standards.\r\n *\r\n * RDBMS Standard for Multiplication:\r\n * - Result Scale = scale1 + scale2\r\n * - Result Precision = precision1 + precision2 + 1\r\n *\r\n * The +1 accounts for potential overflow in multiplication.\r\n *\r\n * @param precision1 Precision of first operand\r\n * @param scale1 Scale of first operand\r\n * @param precision2 Precision of second operand\r\n * @param scale2 Scale of second operand\r\n * @returns RdbmsArithmeticResult with calculated precision and scale\r\n * @throws DecimalError if parameters are invalid\r\n */\r\nexport function calculateMultiplicationResultPrecisionScale(\r\n    precision1: number,\r\n    scale1: number,\r\n    precision2: number,\r\n    scale2: number\r\n): RdbmsArithmeticResult {\r\n    // Validate input parameters\r\n    if (precision1 <= 0 || precision2 <= 0) {\r\n        throw new DecimalError('Precision must be positive');\r\n    }\r\n    if (scale1 < 0 || scale2 < 0) {\r\n        throw new DecimalError('Scale must be non-negative');\r\n    }\r\n    if (scale1 > precision1 || scale2 > precision2) {\r\n        throw new DecimalError('Scale must not exceed precision');\r\n    }\r\n\r\n    // Calculate result scale (sum of input scales)\r\n    const resultScale = scale1 + scale2;\r\n\r\n    // Calculate result precision (sum of input precisions + 1 for overflow)\r\n    const resultPrecision = precision1 + precision2 + 1;\r\n\r\n    return {\r\n        precision: resultPrecision,\r\n        scale: resultScale\r\n    };\r\n}\r\n\r\n/**\r\n * Calculates the result precision and scale for division operations\r\n * following RDBMS/SQL standards.\r\n *\r\n * RDBMS Standard for Division (varies by system, this follows common approach):\r\n * - Result Scale = max(6, scale1 + precision2 + 1)\r\n * - Result Precision = precision1 - scale1 + scale2 + max(6, scale1 + precision2 + 1)\r\n *\r\n * Different RDBMS systems handle division differently:\r\n * - SQL Server: Uses a complex formula with minimum scale of 6\r\n * - PostgreSQL: Uses configurable precision\r\n * - Oracle: Uses maximum available precision\r\n *\r\n * This implementation follows a conservative approach similar to SQL Server.\r\n *\r\n * @param precision1 Precision of dividend\r\n * @param scale1 Scale of dividend\r\n * @param precision2 Precision of divisor\r\n * @param scale2 Scale of divisor\r\n * @param minScale Minimum scale for result (default: 6, following SQL Server)\r\n * @returns RdbmsArithmeticResult with calculated precision and scale\r\n * @throws DecimalError if parameters are invalid\r\n */\r\nexport function calculateDivisionResultPrecisionScale(\r\n    precision1: number,\r\n    scale1: number,\r\n    precision2: number,\r\n    scale2: number,\r\n    minScale: number = 6\r\n): RdbmsArithmeticResult {\r\n    // Validate input parameters\r\n    if (precision1 <= 0 || precision2 <= 0) {\r\n        throw new DecimalError('Precision must be positive');\r\n    }\r\n    if (scale1 < 0 || scale2 < 0) {\r\n        throw new DecimalError('Scale must be non-negative');\r\n    }\r\n    if (scale1 > precision1 || scale2 > precision2) {\r\n        throw new DecimalError('Scale must not exceed precision');\r\n    }\r\n    if (minScale < 0) {\r\n        throw new DecimalError('Minimum scale must be non-negative');\r\n    }\r\n\r\n    // Calculate result scale\r\n    const calculatedScale = scale1 + precision2 + 1;\r\n    const resultScale = Math.max(minScale, calculatedScale);\r\n\r\n    // Calculate result precision\r\n    const integerDigits1 = precision1 - scale1;\r\n    const resultPrecision = integerDigits1 + scale2 + resultScale;\r\n\r\n    return {\r\n        precision: resultPrecision,\r\n        scale: resultScale\r\n    };\r\n}\r\n\r\n/**\r\n * Validates that the calculated precision and scale are within reasonable limits\r\n * and adjusts them if necessary to prevent overflow or excessive memory usage.\r\n *\r\n * @param precision The calculated precision\r\n * @param scale The calculated scale\r\n * @param maxPrecision Maximum allowed precision (default: 38, SQL Server limit)\r\n * @param maxScale Maximum allowed scale (default: same as maxPrecision)\r\n * @returns Adjusted RdbmsArithmeticResult within limits\r\n * @throws DecimalError if the result cannot be represented within limits\r\n */\r\nexport function validateAndAdjustPrecisionScale(\r\n    precision: number,\r\n    scale: number,\r\n    maxPrecision: number = 38,\r\n    maxScale?: number\r\n): RdbmsArithmeticResult {\r\n    const effectiveMaxScale = maxScale ?? maxPrecision;\r\n\r\n    // Validate basic constraints\r\n    if (precision <= 0) {\r\n        throw new DecimalError('Precision must be positive');\r\n    }\r\n    if (scale < 0) {\r\n        throw new DecimalError('Scale must be non-negative');\r\n    }\r\n    if (scale > precision) {\r\n        throw new DecimalError('Scale must not exceed precision');\r\n    }\r\n\r\n    // Check if within limits\r\n    if (precision <= maxPrecision && scale <= effectiveMaxScale) {\r\n        return { precision, scale };\r\n    }\r\n\r\n    // Adjust if exceeding limits\r\n    let adjustedPrecision = Math.min(precision, maxPrecision);\r\n    let adjustedScale = Math.min(scale, effectiveMaxScale);\r\n\r\n    // Ensure scale doesn't exceed adjusted precision\r\n    if (adjustedScale > adjustedPrecision) {\r\n        // Prioritize scale, but ensure we have at least 1 integer digit\r\n        adjustedScale = Math.max(0, adjustedPrecision - 1);\r\n    }\r\n\r\n    // Ensure we have at least 1 integer digit\r\n    if (adjustedScale >= adjustedPrecision) {\r\n        adjustedScale = Math.max(0, adjustedPrecision - 1);\r\n    }\r\n\r\n    return {\r\n        precision: adjustedPrecision,\r\n        scale: adjustedScale\r\n    };\r\n}\r\n\r\n/**\r\n * Determines the appropriate precision and scale for a decimal result\r\n * based on the operation type and operand characteristics.\r\n *\r\n * This is a convenience function that combines the specific calculation\r\n * functions with validation and adjustment.\r\n *\r\n * @param operation The arithmetic operation type\r\n * @param precision1 Precision of first operand\r\n * @param scale1 Scale of first operand\r\n * @param precision2 Precision of second operand\r\n * @param scale2 Scale of second operand\r\n * @param options Optional configuration for limits and division behavior\r\n * @returns RdbmsArithmeticResult with final precision and scale\r\n */\r\nexport function calculateRdbmsArithmeticResult(\r\n    operation: 'add' | 'subtract' | 'multiply' | 'divide',\r\n    precision1: number,\r\n    scale1: number,\r\n    precision2: number,\r\n    scale2: number,\r\n    options?: {\r\n        maxPrecision?: number;\r\n        maxScale?: number;\r\n        divisionMinScale?: number;\r\n    }\r\n): RdbmsArithmeticResult {\r\n    let result: RdbmsArithmeticResult;\r\n\r\n    // Calculate based on operation type\r\n    switch (operation) {\r\n        case 'add':\r\n        case 'subtract':\r\n            result = calculateAdditionResultPrecisionScale(precision1, scale1, precision2, scale2);\r\n            break;\r\n        case 'multiply':\r\n            result = calculateMultiplicationResultPrecisionScale(precision1, scale1, precision2, scale2);\r\n            break;\r\n        case 'divide':\r\n            result = calculateDivisionResultPrecisionScale(\r\n                precision1, scale1, precision2, scale2, options?.divisionMinScale\r\n            );\r\n            break;\r\n        default:\r\n            throw new DecimalError(`Unsupported operation: ${operation}`);\r\n    }\r\n\r\n    // Validate and adjust if necessary\r\n    return validateAndAdjustPrecisionScale(\r\n        result.precision,\r\n        result.scale,\r\n        options?.maxPrecision,\r\n        options?.maxScale\r\n    );\r\n}"],"mappings":"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","names":[]}