Experiments on calculating reciprocal of square root

BUG=
R=reed@google.com, rmistry@chromium.org, bsalomon@google.com, tomhudson@chromium.org, tomhudson@google.com

Author: yang.gu@intel.com

Review URL: https://chromiumcodereview.appspot.com/21755002

git-svn-id: http://skia.googlecode.com/svn/trunk@10671 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/MathBench.cpp b/bench/MathBench.cpp
index 32a89d6..c2b600c 100644
--- a/bench/MathBench.cpp
+++ b/bench/MathBench.cpp
@@ -93,44 +93,58 @@
     typedef MathBench INHERITED;
 };
 
-class SlowISqrtMathBench : public MathBench {
-public:
-    SlowISqrtMathBench(void* param) : INHERITED(param, "slowIsqrt") {}
-protected:
-    virtual void performTest(float* SK_RESTRICT dst,
-                              const float* SK_RESTRICT src,
-                              int count) {
-        for (int i = 0; i < count; ++i) {
-            dst[i] = 1.0f / sk_float_sqrt(src[i]);
-        }
-    }
-private:
-    typedef MathBench INHERITED;
-};
+class InvSqrtBench : public SkBenchmark {
+    enum {
+        ARRAY = SkBENCHLOOP(1000),
+        LOOP = SkBENCHLOOP(5000),
+    };
+    float fData[ARRAY];
+    const char *type;
 
-static inline float SkFastInvSqrt(float x) {
-    float xhalf = 0.5f*x;
-    int i = *SkTCast<int*>(&x);
-    i = 0x5f3759df - (i>>1);
-    x = *SkTCast<float*>(&i);
-    x = x*(1.5f-xhalf*x*x);
-//    x = x*(1.5f-xhalf*x*x); // this line takes err from 10^-3 to 10^-6
-    return x;
-}
-
-class FastISqrtMathBench : public MathBench {
 public:
-    FastISqrtMathBench(void* param) : INHERITED(param, "fastIsqrt") {}
-protected:
-    virtual void performTest(float* SK_RESTRICT dst,
-                              const float* SK_RESTRICT src,
-                              int count) {
-        for (int i = 0; i < count; ++i) {
-            dst[i] = SkFastInvSqrt(src[i]);
-        }
+    InvSqrtBench(void* param, const char *type)
+        : INHERITED(param)
+        , type(type) {
     }
+
+    // just so the compiler doesn't remove our loops
+    virtual void process(int) {}
+
+protected:
+    virtual void onPreDraw() SK_OVERRIDE {
+        SkRandom rand;
+        for (int i = 0; i < ARRAY; ++i) {
+            fData[i] = rand.nextRangeF(0, 10000);
+        }
+
+        fIsRendering = false;
+    }
+
+    virtual void onDraw(SkCanvas*) {
+        float accum = 0;
+
+        if (strcmp(type, "float_slow") == 0) {
+            for (int j = 0; j < LOOP; ++j)
+                for (int i = 0; i < ARRAY; ++i)
+                    accum += 1.0f / sk_float_sqrt(fData[i]);
+        } else if (strcmp(type, "float_fast") == 0) {
+            for (int j = 0; j < LOOP; ++j)
+                for (int i = 0; i < ARRAY; ++i)
+                    accum += SkFloatInvSqrt(fData[i]);
+        }
+
+        this->process(accum);
+    }
+
+    virtual const char* onGetName() {
+        fName.printf("math_inv_sqrt");
+        fName.appendf("_%s", type);
+        return fName.c_str();
+    }
+
 private:
-    typedef MathBench INHERITED;
+    SkString    fName;
+    typedef SkBenchmark INHERITED;
 };
 
 static inline uint32_t QMul64(uint32_t value, U8CPU alpha) {
@@ -523,8 +537,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 DEF_BENCH( return new NoOpMathBench(p); )
-DEF_BENCH( return new SlowISqrtMathBench(p); )
-DEF_BENCH( return new FastISqrtMathBench(p); )
+DEF_BENCH( return new InvSqrtBench(p, "float_slow"); )
+DEF_BENCH( return new InvSqrtBench(p, "float_fast"); )
 DEF_BENCH( return new QMul64Bench(p); )
 DEF_BENCH( return new QMul32Bench(p); )