james-willis opened a new pull request, #1223:
URL: https://github.com/apache/sedona-db/pull/1223

   Parity coverage for `RS_Rotation`, probe-first as usual. Branches off `main` 
— fully independent of #1219.
   
   ### The formulas
   
   SedonaDB computes `atan2(-skewX, scaleX)` (`GeoTransformEx::rotation`); 
Sedona Spark computes `acos(scaleX / sqrt(scaleX² + skewY²))`, negated when 
`skewY > 0` — note the different skew input. They coincide exactly when 
`|skewX| == |skewY|` (axis-aligned grids, rigid rotations of square pixels) and 
separate everywhere else.
   
   ### What agrees (3 passing tests, anchored)
   
   - **Axis-aligned** → 0. The query adds `+ 0.0` to normalize the zero's sign, 
which the engines disagree on (cataloged separately below).
   - **Rigid rotation of square pixels** (±30°) → −θ from both engines, 
anchored at `round(-theta, 12)`. The raw doubles differ by one ulp across 
runtimes (Rust `atan2` vs JVM `acos`), so the query rounds to 12 digits — the 
agreement under test is semantic, not bit-level.
   
   ### What diverges (4 xfails)
   
   - **Zero sign**: SedonaDB returns IEEE `-0.0` for north-up and south-up 
grids; Spark returns `+0.0`.
   - **Rigid rotation of non-square (2x3) pixels**: SedonaDB reports −0.7137 
for a true −π/6; Spark recovers −π/6 exactly. This is a stronger case than 
shear: Spark's formula is the angle of the grid's actual column-axis direction 
`(scaleX, skewY)`, so it decomposes any rigid rotation correctly regardless of 
pixel shape, while `atan2(-skewX, scaleX)` mixes the row axis's skew into the 
answer.
   - **Shear** (scaleX=0.2, skewX=0.06, skewY=0.08): −0.2915 vs −0.3805.
   
   ### The open decision
   
   #1221 (`RS_GeoTransform`) ports Spark's decomposition, so its `thetaI` uses 
Spark's formula — once it lands, `RS_Rotation(r) != RS_GeoTransform(r).thetaI` 
under shear in SedonaDB, an internal inconsistency Spark doesn't have. The 
non-square-rigid finding above suggests aligning `RS_Rotation` to Spark's 
formula (it's the geometrically meaningful decomposition, and the change would 
flip these xfails to passes); this PR only catalogs, it doesn't change the 
kernel.
   
   Aside, noted while probing and out of scope here: SedonaDB evaluates `-0.0 = 
0.0` as `false` in SQL where Spark (and IEEE) say `true`.
   
   ### Verification
   
   `integration/spark-parity` locally: `24 passed, 18 xfailed` (the module adds 
3 passed / 4 xfailed). This branch carries the #1217 lane, so CI runs the suite 
too.
   


-- 
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]

Reply via email to