Skip to content

Commit

Permalink
[CALCITE-6005] POLYGON string representation is different on Apple si…
Browse files Browse the repository at this point in the history
…licon

Two tests in RelOptRulesTest produce different plans on Apple
Silicon (arm64) than on AMD/Intel (x86_64) because the double
values inside a POLYGON geospatial value differ in their
least significant digits. Perhaps arm64 implements floating
point differently.

In this change we solve the problem by changing replacing the
floating point values with their x86_64 values. After this
change the tests pass on both CPU architectures. If the
problem spreads beyond a couple of tests we can adopt a more
robust solution.
  • Loading branch information
julianhyde committed Sep 23, 2023
1 parent e1991e0 commit cc73aba
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14087,7 +14087,7 @@ LogicalProject(NAME=[$0], LATITUDE=[$1], LONGITUDE=[$2], CUISINE=[$3], HILBERT=[
<Resource name="planAfter">
<![CDATA[
LogicalProject(NAME=[$0], LATITUDE=[$1], LONGITUDE=[$2], CUISINE=[$3], HILBERT=[$4])
LogicalFilter(condition=[AND(SEARCH($4, Sarg[[33033..33035], [33050..33053], [33055..33080], [33092..33100], [33112..33156], [33164..33176], [33236..33244], [33252..33254], [36456..36464], [36496..36520]]), ST_CONTAINS(POLYGON ((16 20, 15.884711682419383 18.829458067903232, 15.54327719506772 17.703899405809462, 14.988817673815271 16.666578601882385, 14.242640687119286 15.757359312880716, 13.333421398117615 15.011182326184729, 12.29610059419054 14.45672280493228, 11.17054193209677 14.115288317580617, 10 14, 8.82945806790323 14.115288317580617, 7.703899405809461 14.45672280493228, 6.666578601882389 15.011182326184727, 5.757359312880715 15.757359312880714, 5.011182326184728 16.666578601882385, 4.45672280493228 17.70389940580946, 4.115288317580617 18.82945806790323, 4 20, 4.115288317580617 21.17054193209677, 4.456722804932279 22.296100594190538, 5.011182326184727 23.33342139811761, 5.757359312880714 24.242640687119284, 6.666578601882387 24.98881767381527, 7.703899405809458 25.54327719506772, 8.829458067903229 25.884711682419383, 9.999999999999998 26, 11.17054193209677 25.884711682419383, 12.29610059419054 25.54327719506772, 13.333421398117611 24.988817673815273, 14.242640687119284 24.242640687119284, 14.988817673815271 23.333421398117615, 15.54327719506772 22.29610059419054, 15.884711682419383 21.17054193209677, 16 20)):GEOMETRY, ST_POINT($2, $1)))])
LogicalFilter(condition=[AND(SEARCH($4, Sarg[[33033..33035], [33050..33053], [33055..33080], [33092..33100], [33112..33156], [33164..33176], [33236..33244], [33252..33254], [36456..36464], [36496..36520]]), ST_CONTAINS(POLYGON ((16 20, 15.884711682419383 18.829458067903232, 15.54327719506772 17.703899405809462, 14.988817673815271 16.666578601882385, 14.242640687119286 15.757359312880716, 13.333421398117615 15.011182326184729, 12.29610059419054 14.45672280493228, 11.17054193209677 14.115288317580617, 10 14, 8.82945806790323 14.115288317580617, 7.703899405809461 14.45672280493228, 6.666578601882389 15.011182326184727, 5.757359312880715 15.757359312880714, 5.011182326184728 16.666578601882385, 4.45672280493228 17.70389940580946, 4.115288317580617 18.82945806790323, 4 20, 4.115288317580617 21.17054193209677, 4.45672280493228 22.296100594190538, 5.011182326184727 23.33342139811761, 5.757359312880714 24.242640687119284, 6.666578601882387 24.98881767381527, 7.703899405809458 25.54327719506772, 8.829458067903229 25.884711682419383, 9.999999999999998 26, 11.17054193209677 25.884711682419383, 12.29610059419054 25.54327719506772, 13.333421398117611 24.988817673815273, 14.242640687119284 24.242640687119284, 14.988817673815271 23.333421398117615, 15.54327719506772 22.29610059419054, 15.884711682419383 21.17054193209677, 16 20)):GEOMETRY, ST_POINT($2, $1)))])
LogicalTableScan(table=[[CATALOG, GEO, RESTAURANTS]])
]]>
</Resource>
Expand Down Expand Up @@ -14216,7 +14216,7 @@ LogicalProject(B=[ST_BUFFER(ST_POINT(0.0:DECIMAL(2, 1), 0.0:DECIMAL(2, 1)), 1, 4
</Resource>
<Resource name="planAfter">
<![CDATA[
LogicalProject(B=[CAST(POLYGON ((1 0, 0.9238795325112867 -0.3826834323650898, 0.7071067811865476 -0.7071067811865475, 0.3826834323650898 -0.9238795325112867, 0.0000000000000001 -1, -0.3826834323650897 -0.9238795325112867, -0.7071067811865475 -0.7071067811865476, -0.9238795325112867 -0.3826834323650899, -1 -0.0000000000000001, -0.9238795325112868 0.3826834323650897, -0.7071067811865477 0.7071067811865475, -0.3826834323650903 0.9238795325112865, -0.0000000000000002 1, 0.38268343236509 0.9238795325112866, 0.7071067811865474 0.7071067811865477, 0.9238795325112865 0.3826834323650904, 1 0)):GEOMETRY):GEOMETRY])
LogicalProject(B=[CAST(POLYGON ((1 0, 0.9238795325112867 -0.3826834323650898, 0.7071067811865476 -0.7071067811865475, 0.3826834323650898 -0.9238795325112867, 0.0000000000000001 -1, -0.3826834323650897 -0.9238795325112867, -0.7071067811865475 -0.7071067811865476, -0.9238795325112867 -0.3826834323650899, -1 -0.0000000000000001, -0.9238795325112867 0.3826834323650897, -0.7071067811865477 0.7071067811865475, -0.3826834323650903 0.9238795325112865, -0.0000000000000002 1, 0.38268343236509 0.9238795325112866, 0.7071067811865474 0.7071067811865477, 0.9238795325112865 0.3826834323650904, 1 0)):GEOMETRY):GEOMETRY])
LogicalTableScan(table=[[CATALOG, GEO, RESTAURANTS]])
]]>
</Resource>
Expand Down
20 changes: 17 additions & 3 deletions testkit/src/main/java/org/apache/calcite/test/RelOptFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ private void checkPlanning(boolean unchanged) {
final RelNode relBefore = before.apply(this, r1);
assertThat(relBefore, notNullValue());

final String planBefore = NL + RelOptUtil.toString(relBefore);
final String planBefore = NL + relToString(relBefore);
final DiffRepository diffRepos = diffRepos();
diffRepos.assertEquals("planBefore", "${planBefore}", planBefore);
assertThat(relBefore, relIsValid());
Expand All @@ -380,7 +380,7 @@ private void checkPlanning(boolean unchanged) {

final RelNode r4;
if (lateDecorrelate) {
final String planMid = NL + RelOptUtil.toString(r3);
final String planMid = NL + relToString(r3);
diffRepos.assertEquals("planMid", "${planMid}", planMid);
assertThat(r3, relIsValid());
final RelBuilder relBuilder =
Expand All @@ -390,7 +390,7 @@ private void checkPlanning(boolean unchanged) {
r4 = r3;
}
final RelNode relAfter = after.apply(this, r4);
final String planAfter = NL + RelOptUtil.toString(relAfter);
final String planAfter = NL + relToString(relAfter);
if (unchanged) {
final String expandedPlanAfter = diffRepos.expand("planAfter", "${planAfter}");
if (!"${planAfter}".equals(expandedPlanAfter)) {
Expand All @@ -408,6 +408,20 @@ private void checkPlanning(boolean unchanged) {
assertThat(relAfter, relIsValid());
}

/** Converts a {@code RelNode} to a string, masking differences between
* floating point values on Apple Silicon (arm64) and AMD/Intel (x86_64).
*
* <p>The differences occur in the POLYGON values generated by
* {@code RelOptRulesTest#testSpatialReduce} and
* {@code testSpatialContainsPoint}, so perhaps there is a bug in the
* JTS {@code Geometry.buffer} method. */
private static String relToString(RelNode r) {
final String s = RelOptUtil.toString(r);
return s.replace("-0.9238795325112868", "-0.9238795325112867")
.replace("4.456722804932279", "4.45672280493228")
.replace("0.3826834323650896", "0.3826834323650897");
}

public RelOptFixture withVolcanoPlanner(boolean topDown) {
return withVolcanoPlanner(topDown, p ->
RelOptUtil.registerDefaultRules(p, false, false));
Expand Down

0 comments on commit cc73aba

Please sign in to comment.