Vivek1106-04 opened a new pull request, #58242:
URL: https://github.com/apache/spark/pull/58242

   ### What changes were proposed in this pull request?
   
   This PR adds two new built-in math functions, `gcd` and `lcm`:
   
   ```sql
   gcd(expr1, expr2) -- returns BIGINT
   lcm(expr1, expr2) -- returns BIGINT
   ```
   
   Both arguments are implicitly cast to BIGINT and the result is BIGINT, 
matching the existing
   `factorial` expression, which likewise takes an integral argument and 
returns BIGINT.
   
   Semantics:
   
   | Case | `gcd` | `lcm` |
   |---|---|---|
   | either argument is NULL | NULL | NULL |
   | both arguments are 0 | 0 | 0 |
   | one argument is 0 | `abs(other)` | 0 |
   | negative arguments | result is non-negative | result is non-negative |
   | result not representable as BIGINT | `ARITHMETIC_OVERFLOW` under ANSI 
mode, NULL otherwise | `ARITHMETIC_OVERFLOW` under ANSI mode, NULL otherwise |
   
   The greatest common divisor is computed with the Euclidean algorithm. The 
least common multiple
   divides by the greatest common divisor before multiplying, so a 
representable result never
   overflows on the way there — for example `lcm(4611686018427387904, 2)` 
returns `4611686018427387904`
   even though the naive product `4611686018427387904 * 2` would not fit.
   
   Overflow arises in exactly two places, and in both PostgreSQL raises as well:
   
   * `gcd` where the result would be `-Long.MinValue`, which is not 
representable — that is, the
     input pairs `(0, x)`, `(x, 0)` and `(x, x)` for `x = Long.MinValue`.
   * `lcm` where `abs(a) / gcd(a, b) * abs(b)` exceeds `Long.MaxValue`.
   
   Both are reported with the existing `ARITHMETIC_OVERFLOW` error condition, 
so no new error
   condition is introduced. Overflow is gated on ANSI mode as it is elsewhere 
in Spark — `conv` in the
   same file takes the same approach — raising under ANSI mode and returning 
NULL otherwise.
   
   Both helpers live in `MathUtils` and are shared by the interpreted and 
codegen paths so the two
   cannot diverge.
   
   The functions are exposed through SQL, the Scala/Java `functions` API, 
PySpark, and Spark Connect.
   
   ### Why are the changes needed?
   
   Spark SQL currently has no way to compute either value. There is no 
expression for it, and no
   combination of existing built-ins produces the result, so users have to fall 
back to a UDF — which
   for PySpark means a Python round trip per row and no whole-stage codegen.
   
   Both functions are standard in comparable engines:
   
   * PostgreSQL 13+: `gcd(a, b)`, `lcm(a, b)` for `integer`, `bigint` and 
`numeric`
   * DuckDB: `gcd(a, b)`, `lcm(a, b)` (aliases `greatest_common_divisor`, 
`least_common_multiple`)
   
   Common uses include reducing fractions and ratios to lowest terms, aligning 
batch or partition
   sizes, computing the repeat period of overlapping schedules, and normalizing 
denominators before
   aggregation.
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes. Two new built-in functions are available in SQL, the Scala/Java 
`functions` API, PySpark and
   Spark Connect. Previously `gcd` and `lcm` were unresolved function names:
   
   ```sql
   -- Before
   spark-sql> SELECT gcd(24, 36);
   [UNRESOLVED_ROUTINE] Cannot resolve routine `gcd` on search path
   [`system`.`builtin`, `system`.`session`, `spark_catalog`.`default`]. 
SQLSTATE: 42883
   
   -- After
   spark-sql> SELECT gcd(24, 36);
   12
   spark-sql> SELECT lcm(4, 6);
   12
   ```
   
   No existing behavior changes; the change is purely additive.
   
   ### How was this patch tested?
   
   New tests:
   
   * `MathExpressionsSuite` — unit tests for both expressions covering ordinary 
values, negative
     inputs, zero, NULL, the boundary values around `Long.MinValue` / 
`Long.MaxValue`, and overflow in
     both ANSI and non-ANSI mode, plus interpreted-vs-codegen consistency 
checks.
   * `math.sql` golden-file tests, regenerated for the ANSI and non-ANSI 
results and the analyzer
     results.
   * `PlanGenerationTestSuite` function tests, with the regenerated Spark 
Connect plan and explain
     golden files.
   * PySpark doctests for `gcd` and `lcm`.
   
   Existing suites re-run and passing: `MathExpressionsSuite`, 
`SQLQueryTestSuite` (`math.sql`),
   `ExpressionsSchemaSuite`, `PlanGenerationTestSuite`, 
`ProtoToParsedPlanTestSuite`.
   
   `dev/lint-scala` and `dev/lint-python` both pass.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Claude Opus 5)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to