[PATCH] Implement sin/cos for sphereflake test-suite

Renato Golin renato.golin at linaro.org
Mon Mar 17 09:32:56 PDT 2014


Hi robertlytton, ddunbar,

This code works with Clang on ARM, x86_64 and AArch64, generating the same image (and MD5 sum), but GCC still generates a different image on -O2/-O3 and it might be because of the additional sqrt() call, which I'll look into next. But this should make all C-based tests pass under Clang, anyway.

I've plotted the sin/cos results with gnuplot and the accuracy is reasonably good, and given the simplicity, it'll be hard for compilers to mess this up in terms of reproducibility, which is what we care in the test.

http://llvm-reviews.chandlerc.com/D3098

Files:
  SingleSource/Benchmarks/Misc-C++/Large/sphereflake.cpp
  SingleSource/Benchmarks/Misc-C++/Large/sphereflake.reference_output

Index: SingleSource/Benchmarks/Misc-C++/Large/sphereflake.cpp
===================================================================
--- SingleSource/Benchmarks/Misc-C++/Large/sphereflake.cpp
+++ SingleSource/Benchmarks/Misc-C++/Large/sphereflake.cpp
@@ -147,18 +147,55 @@
 // Implementations of sin() and cos() may vary slightly in the accuracy of
 // their results, typically only in the least significant bit.  Round to make
 // the results consistent across platforms.
-typedef union { double d; unsigned long long ll; } dbl_ll_union;
+#define FACT3 6
+#define FACT5 120
+#define PI    3.141592656
+#define PI2   6.283185307
+#define PI_2  1.570796327
+#define PI3_2 4.712388984
+
+static double LLVMpow(double d, int n) {
+  int i;
+  double res = d;
+  if (n == 0)
+    return 1;
+  for (i=1; i<n; i++)
+    res *= d;
+  return res;
+}
+
 static double LLVMsin(double d) {
-  dbl_ll_union u;
-  u.d = sin(d);
-  u.ll = (u.ll + 1) & ~1ULL;
-  return u.d;
+  double sign = 1.0;
+
+  /* move into 2PI area */
+  while (d < 0)
+    d += PI2;
+  while (d > PI2)
+    d -= PI2;
+  /* move into PI/2 area */
+  if (d > PI3_2) {
+    d = PI2 - d;
+    sign = -1.0;
+  } else if (d > PI) {
+    d -= PI;
+    sign = -1.0;
+  } else if (d > PI_2) {
+    d = PI - d;
+  }
+  /* series terms */
+  double f3 = LLVMpow(d, 3)/FACT3;
+  double f5 = LLVMpow(d, 5)/FACT5;
+  d = sign * (d - f3 + f5);
+  /* saturate */
+  if (d > 1.0)
+    d = 1.0;
+  if (d < -1.0)
+    d = -1.0;
+  return d;
 }
+
 static double LLVMcos(double d) {
-  dbl_ll_union u;
-  u.d = cos(d);
-  u.ll = (u.ll + 1) & ~1ULL;
-  return u.d;
+  return LLVMsin(d + PI_2);
 }
 // LLVM LOCAL end
 
Index: SingleSource/Benchmarks/Misc-C++/Large/sphereflake.reference_output
===================================================================
--- SingleSource/Benchmarks/Misc-C++/Large/sphereflake.reference_output
+++ SingleSource/Benchmarks/Misc-C++/Large/sphereflake.reference_output
@@ -1 +1 @@
-064dd68da3963cf8d246e133a4f10486
+a0a1a950b3e237efde1acee62f1fe08b
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3098.1.patch
Type: text/x-patch
Size: 2021 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140317/06297e88/attachment.bin>


More information about the llvm-commits mailing list