lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 7473332: Efficiently determine whether a vect


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 7473332: Efficiently determine whether a vector<double> is all boolean-valued
Date: Sun, 28 Mar 2021 13:48:15 -0400 (EDT)

branch: master
commit 747333211e5cadceb9c3d417930081d240228472
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Efficiently determine whether a vector<double> is all boolean-valued
    
    For x86_64-pc-linux-gnu gcc-10.2, PETE is fastest:
      mete_eq0a 2.024e-07 s mean;          0 us least of 49399 runs
      mete_eq0b 2.014e-07 s mean;          0 us least of 49661 runs
      mete_eq0c 1.745e-07 s mean;          0 us least of 57313 runs
      mete_eq1a 1.408e-07 s mean;          0 us least of 71035 runs
      mete_eq1b 1.423e-07 s mean;          0 us least of 70268 runs
      mete_eq1c 2.118e-07 s mean;          0 us least of 47224 runs
      mete_eq1x 2.038e-07 s mean;          0 us least of 49067 runs
    while for i686-w64-mingw32 gcc-8.3, all take about the same time.
    
    The crucial conclusion is that writing code as close as possible to
    C++ extended with an APL declaration like the standard asm-declaration:
      APL {"∧/X∨.=0 1"};   // More idiomatic. (APL '=' means C '=='.)
      APL {"∧/(X=1)∨X=0"}; // Doesn't require constructing vector{0, 1}.
    by using PETE
      ∧/   (X=1)                      ∨  X=0
      AllOf(EqualTo(true, bit_valued) || EqualTo(false, bit_valued));
    incurs no speed penalty in the particular case studied (determining
    whether a 100-element vector<double> is all boolean-valued).
    
    It's curious that
      ∧/(X=1)∨(X=0)  ⍝ all are either =1 or =0
    is faster than
      ~∨/(X≠1)∧(X≠0) ⍝ none is both   ≠1 and ≠0
    and perhaps less surprising that
      ∧/X=~~X        ⍝ each equals its boolean NOT(NOT)
    is not the fastest.
---
 et_vector_test.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 92 insertions(+), 5 deletions(-)

diff --git a/et_vector_test.cpp b/et_vector_test.cpp
index e3f34e4..181c288 100644
--- a/et_vector_test.cpp
+++ b/et_vector_test.cpp
@@ -23,9 +23,94 @@
 
 #include "ssize_lmi.hpp"
 #include "test_tools.hpp"
+#include "timer.hpp"
 
 #include <functional>                   // multiplies(), negate(), plus()
 
+// A vector of boolean values, represented as double, such as
+// might result from querying lmi's database.
+static std::vector<double> const bit_valued =
+    {0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0
+    ,1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
+    ,0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0
+    ,1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
+    ,0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0
+    ,1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
+    ,0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0
+    ,1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
+    ,0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0
+    ,1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
+    };
+
+bool mete_eq0a()
+{
+    for(auto const& i : bit_valued)
+        {
+        if(false != i && true != i)
+            return false;
+        }
+    return true;
+}
+
+bool mete_eq0b()
+{
+    for(auto const& i : bit_valued)
+        {
+        if(0.0 != i && 1.0 != i)
+            return false;
+        }
+    return true;
+}
+
+bool mete_eq0c()
+{
+    for(auto const& i : bit_valued)
+        {
+        if(i != !!i)
+            return false;
+        }
+    return true;
+}
+
+bool mete_eq1a()
+{
+    return AllOf(EqualTo(true, bit_valued) || EqualTo(false, bit_valued));
+}
+
+bool mete_eq1b()
+{
+    return AllOf(EqualTo(1.0, bit_valued) || EqualTo(0.0, bit_valued));
+}
+
+bool mete_eq1c()
+{
+    return AllOf(EqualTo(bit_valued, !!bit_valued));
+}
+
+bool mete_eq1x()
+{
+    return !AnyOf(UnequalTo(true, bit_valued) && UnequalTo(false, bit_valued));
+}
+
+void assay_speed()
+{
+    LMI_TEST_EQUAL(true, mete_eq0a());
+    LMI_TEST_EQUAL(true, mete_eq0b());
+    LMI_TEST_EQUAL(true, mete_eq0c());
+    LMI_TEST_EQUAL(true, mete_eq1a());
+    LMI_TEST_EQUAL(true, mete_eq1b());
+    LMI_TEST_EQUAL(true, mete_eq1c());
+    LMI_TEST_EQUAL(true, mete_eq1x());
+    std::cout << "Speed tests:\n";
+    std::cout << "  mete_eq0a " << TimeAnAliquot(mete_eq0a) << '\n';
+    std::cout << "  mete_eq0b " << TimeAnAliquot(mete_eq0b) << '\n';
+    std::cout << "  mete_eq0c " << TimeAnAliquot(mete_eq0c) << '\n';
+    std::cout << "  mete_eq1a " << TimeAnAliquot(mete_eq1a) << '\n';
+    std::cout << "  mete_eq1b " << TimeAnAliquot(mete_eq1b) << '\n';
+    std::cout << "  mete_eq1c " << TimeAnAliquot(mete_eq1c) << '\n';
+    std::cout << "  mete_eq1x " << TimeAnAliquot(mete_eq1x) << '\n';
+}
+
 int test_main(int, char*[])
 {
     {
@@ -210,12 +295,14 @@ int test_main(int, char*[])
     // using NOT NOT to turn values into booleans, but, using PETE
     // with std::vector, "!!V" returns a vector<bool>; ET !! perhaps
     // boolean operators should therefore be amended to return 'int'.
-    LMI_TEST_EQUAL(true , AllOf(EqualTo(true, v0) ||  EqualTo(false, v0)));
-    LMI_TEST_EQUAL(true , AllOf(EqualTo(true, v1) ||  EqualTo(false, v1)));
-    LMI_TEST_EQUAL(true , AllOf(EqualTo(true, v2) ||  EqualTo(false, v2)));
-    LMI_TEST_EQUAL(false, AllOf(EqualTo(true, v3) ||  EqualTo(false, v3)));
-    LMI_TEST_EQUAL(false, AllOf(EqualTo(true, v4) ||  EqualTo(false, v4)));
+    LMI_TEST_EQUAL(true , AllOf(EqualTo(true, v0) || EqualTo(false, v0)));
+    LMI_TEST_EQUAL(true , AllOf(EqualTo(true, v1) || EqualTo(false, v1)));
+    LMI_TEST_EQUAL(true , AllOf(EqualTo(true, v2) || EqualTo(false, v2)));
+    LMI_TEST_EQUAL(false, AllOf(EqualTo(true, v3) || EqualTo(false, v3)));
+    LMI_TEST_EQUAL(false, AllOf(EqualTo(true, v4) || EqualTo(false, v4)));
     }
 
+    assay_speed();
+
     return 0;
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]