From 4e0a42259fdbfafc9298dc634bedeee07a9ea32f Mon Sep 17 00:00:00 2001 From: Cam Hutchison Date: Sat, 8 Feb 2025 21:08:15 +1100 Subject: [PATCH 1/3] svg: Prevent code with fused instructions Add a floating point conversion when multiplying when scaling coordinates so that the multiplication does not get fused with an adjacent addition or subtraction. This causes two instructions to be generated, a MUL and a ADD/SUB, instead of a single FMADD or FMSUB. A fused instruction has different rounding so ends up giving slightly different results to two instructions. This was causing different values in the SVGs generated between AMD64 and ARM64. Link: https://go.dev/ref/spec#Floating_point_operators --- pkg/cli/svg/runtime.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/cli/svg/runtime.go b/pkg/cli/svg/runtime.go index b540e816..eeaa04bd 100644 --- a/pkg/cli/svg/runtime.go +++ b/pkg/cli/svg/runtime.go @@ -90,7 +90,14 @@ func (rt *GraphicsPlatform) transformY(y float64) float64 { } func (rt *GraphicsPlatform) scale(s float64) float64 { - return scaleFactor * s + // The float64 cast here acts as a barrier against a fused multiply/ + // subtraction ARM64 instruction so that this multiply and a subtraction + // done by the caller of this function are not fused into a single ARM64 + // instruction. This causes rounding differences when it is not used + // and causes the generated SVG files to have slight differences depending + // on which platform it is run. + // https://go.dev/ref/spec#Floating_point_operators + return float64(scaleFactor * s) } func (rt *GraphicsPlatform) nonDefaultAttr() Attr { From 8ce6ebc409a272c53a1b19058a57cebd295a3680 Mon Sep 17 00:00:00 2001 From: Cam Hutchison Date: Sat, 8 Feb 2025 21:11:58 +1100 Subject: [PATCH 2/3] Revert "labs: Rework random rectangle generation" This should not be needed now that we have identified the cause of the difference being fused instructions, which are no longer generated. Commit: 6f2a6750181637891ad649199ef2680ea116271b --- frontend/lab/samples/ifs/img/randrect.evy | 16 +- frontend/lab/samples/ifs/img/randrect.svg | 420 ++++++++++++++++++---- 2 files changed, 364 insertions(+), 72 deletions(-) diff --git a/frontend/lab/samples/ifs/img/randrect.evy b/frontend/lab/samples/ifs/img/randrect.evy index 337e833f..dee923da 100644 --- a/frontend/lab/samples/ifs/img/randrect.evy +++ b/frontend/lab/samples/ifs/img/randrect.evy @@ -1,19 +1,11 @@ fill (hsl 270 100 50 10) width 0.2 for range 60 - x := roundedRand1 * 100 - y := roundedRand1 * 100 - s1 := roundedRand1 * 25 + 2 - s2 := roundedRand1 * 25 + 2 + x := (rand1) * 100 + y := (rand1) * 100 + s1 := (rand1) * 25 + 2 + s2 := (rand1) * 25 + 2 move x-s1*0.5 y-s2*0.5 rect s1 s2 end - -// roundedRand1 is a rounding rand1 function, to avoid rounding differences on -// Mac and Linux. -func roundedRand1:num - r := rand1 * 1024 - r = round r - return r / 1024 -end diff --git a/frontend/lab/samples/ifs/img/randrect.svg b/frontend/lab/samples/ifs/img/randrect.svg index bc7b339f..4533d72c 100644 --- a/frontend/lab/samples/ifs/img/randrect.svg +++ b/frontend/lab/samples/ifs/img/randrect.svg @@ -9,65 +9,365 @@ > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 31f9dca73693a1522714647819e2b7ad4372ca97 Mon Sep 17 00:00:00 2001 From: Cam Hutchison Date: Sat, 8 Feb 2025 21:56:52 +1100 Subject: [PATCH 3/3] labs: Remove unnecessary parens in randrect Remove the parens around `rand1` in `randrect.evy` as they are no longer needed due to a recent change that allows niladic function calls in expressions without parens. Since this PR is in this file now, let's make it read nicer. There are probably other evy files that could have this change - one day we may find them. --- frontend/lab/samples/ifs/img/randrect.evy | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/lab/samples/ifs/img/randrect.evy b/frontend/lab/samples/ifs/img/randrect.evy index dee923da..a933d1bf 100644 --- a/frontend/lab/samples/ifs/img/randrect.evy +++ b/frontend/lab/samples/ifs/img/randrect.evy @@ -1,10 +1,10 @@ fill (hsl 270 100 50 10) width 0.2 for range 60 - x := (rand1) * 100 - y := (rand1) * 100 - s1 := (rand1) * 25 + 2 - s2 := (rand1) * 25 + 2 + x := rand1 * 100 + y := rand1 * 100 + s1 := rand1 * 25 + 2 + s2 := rand1 * 25 + 2 move x-s1*0.5 y-s2*0.5 rect s1 s2