lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] master efc0881 4/4: Throw on length error in PETE ve


From: Greg Chicares
Subject: [lmi-commits] [lmi] master efc0881 4/4: Throw on length error in PETE vector assignment
Date: Fri, 19 Mar 2021 08:04:31 -0400 (EDT)

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

    Throw on length error in PETE vector assignment
    
    Hold vector references rather than iterators in PETE leaf nodes;
    test conformability when assigning.
    
    'SizeLeaf' is taken from one of the PETE examples, for conformability
    checking. 'LengthLeaf' was added to support ascertaining vector length
    directly. Ideally only one or the other would be used for both purposes.
    
    * tools/pete-2.1.1/et_vector.hpp: As described above.
    * et_vector_0_test.cpp: Test length determination and conformability
      check.
    * expression_template_0_test.cpp: Adapted a unit test for which PETE now
      diagnoses a known error.
    
    Many years ago, it was faster not to test conformability, but now gcc
    optimizes better. Before and after 'expression_template_0_test' results
    for x86_64-pc-linux-gnu (i686-w64-mingw32 results are similar):
    
        [before this commit]
      Speed tests: array length 10
      valarray typical: 7.735e-06 s mean;          7 us least of 1293 runs
      PETE typical    : 8.821e-06 s mean;          8 us least of 1134 runs
      Speed tests: array length 100
      valarray typical: 4.514e-05 s mean;         45 us least of 222 runs
      PETE typical    : 4.720e-05 s mean;         46 us least of 212 runs
      Speed tests: array length 1000
      valarray typical: 2.855e-04 s mean;        284 us least of 100 runs
      PETE typical    : 3.123e-04 s mean;        305 us least of 100 runs
    
        [after this commit]
      Speed tests: array length 10
      valarray typical: 7.763e-06 s mean;          7 us least of 1289 runs
      PETE typical    : 8.823e-06 s mean;          8 us least of 1134 runs
      Speed tests: array length 100
      valarray typical: 4.512e-05 s mean;         45 us least of 222 runs
      PETE typical    : 4.734e-05 s mean;         47 us least of 212 runs
      Speed tests: array length 1000
      valarray typical: 3.800e-04 s mean;        379 us least of 100 runs
      PETE typical    : 3.108e-04 s mean;        306 us least of 100 runs
    
    Curiously, the length-1000 measurements for std::valarray differ greatly
    on successive runs, and that phenomenon is reproducible.
    
    Speed, as measured in 'Speed_*', would seem to have improved, but that
    is not to be believed: only PETE has changed, and it has not become
    faster. Rather, the speed noted in commit 60503e65f has been regained,
    after having been slightly impaired in recent commits for no plausible
    reason other than noise.
---
 Speed_gcc_i686-w64-mingw32     |  12 ++---
 Speed_gcc_x86_64-pc-linux-gnu  |  12 ++---
 Speed_gcc_x86_64-w64-mingw32   |  12 ++---
 et_vector_0_test.cpp           |  15 +++++++
 expression_template_0_test.cpp |  10 +++--
 tools/pete-2.1.1/et_vector.hpp | 100 +++++++++++++++++++++++++++++++++++++----
 6 files changed, 132 insertions(+), 29 deletions(-)

diff --git a/Speed_gcc_i686-w64-mingw32 b/Speed_gcc_i686-w64-mingw32
index dee941b..bf3a369 100644
--- a/Speed_gcc_i686-w64-mingw32
+++ b/Speed_gcc_i686-w64-mingw32
@@ -1,7 +1,7 @@
 Test speed:
-  naic, no solve      : 5.244e-02 s mean;      51935 us least of  20 runs
-  naic, specamt solve : 1.015e-01 s mean;      97949 us least of  10 runs
-  naic, ee prem solve : 8.994e-02 s mean;      89272 us least of  12 runs
-  finra, no solve     : 1.566e-02 s mean;      15304 us least of  64 runs
-  finra, specamt solve: 5.949e-02 s mean;      57138 us least of  17 runs
-  finra, ee prem solve: 5.351e-02 s mean;      52885 us least of  19 runs
+  naic, no solve      : 5.132e-02 s mean;      50831 us least of  20 runs
+  naic, specamt solve : 9.683e-02 s mean;      95857 us least of  11 runs
+  naic, ee prem solve : 8.840e-02 s mean;      87203 us least of  12 runs
+  finra, no solve     : 1.545e-02 s mean;      15221 us least of  65 runs
+  finra, specamt solve: 5.671e-02 s mean;      56072 us least of  18 runs
+  finra, ee prem solve: 5.214e-02 s mean;      51567 us least of  20 runs
diff --git a/Speed_gcc_x86_64-pc-linux-gnu b/Speed_gcc_x86_64-pc-linux-gnu
index ef581b9..7fe59fe 100644
--- a/Speed_gcc_x86_64-pc-linux-gnu
+++ b/Speed_gcc_x86_64-pc-linux-gnu
@@ -1,7 +1,7 @@
 Test speed:
-  naic, no solve      : 1.940e-02 s mean;      18303 us least of  52 runs
-  naic, specamt solve : 3.401e-02 s mean;      33583 us least of  30 runs
-  naic, ee prem solve : 3.096e-02 s mean;      30626 us least of  33 runs
-  finra, no solve     : 5.301e-03 s mean;       5129 us least of 100 runs
-  finra, specamt solve: 1.937e-02 s mean;      18994 us least of  52 runs
-  finra, ee prem solve: 1.790e-02 s mean;      17598 us least of  56 runs
+  naic, no solve      : 1.861e-02 s mean;      18182 us least of  54 runs
+  naic, specamt solve : 3.357e-02 s mean;      33203 us least of  30 runs
+  naic, ee prem solve : 3.066e-02 s mean;      30416 us least of  33 runs
+  finra, no solve     : 5.252e-03 s mean;       5067 us least of 100 runs
+  finra, specamt solve: 1.918e-02 s mean;      18954 us least of  53 runs
+  finra, ee prem solve: 1.769e-02 s mean;      17544 us least of  57 runs
diff --git a/Speed_gcc_x86_64-w64-mingw32 b/Speed_gcc_x86_64-w64-mingw32
index 2a08127..4d320da 100644
--- a/Speed_gcc_x86_64-w64-mingw32
+++ b/Speed_gcc_x86_64-w64-mingw32
@@ -1,7 +1,7 @@
 Test speed:
-  naic, no solve      : 2.619e-02 s mean;      25818 us least of  39 runs
-  naic, specamt solve : 4.550e-02 s mean;      44896 us least of  22 runs
-  naic, ee prem solve : 4.165e-02 s mean;      41072 us least of  25 runs
-  finra, no solve     : 9.603e-03 s mean;       9196 us least of 100 runs
-  finra, specamt solve: 2.780e-02 s mean;      26638 us least of  36 runs
-  finra, ee prem solve: 2.606e-02 s mean;      24534 us least of  39 runs
+  naic, no solve      : 2.588e-02 s mean;      25412 us least of  39 runs
+  naic, specamt solve : 4.446e-02 s mean;      44021 us least of  23 runs
+  naic, ee prem solve : 4.071e-02 s mean;      40347 us least of  25 runs
+  finra, no solve     : 9.436e-03 s mean;       9260 us least of 100 runs
+  finra, specamt solve: 2.637e-02 s mean;      26108 us least of  38 runs
+  finra, ee prem solve: 2.450e-02 s mean;      24231 us least of  41 runs
diff --git a/et_vector_0_test.cpp b/et_vector_0_test.cpp
index 17d2230..57bfd18 100644
--- a/et_vector_0_test.cpp
+++ b/et_vector_0_test.cpp
@@ -34,6 +34,21 @@ int test_main(int, char*[])
     LMI_TEST(r0 == v0);
     }
 
+    // Test length determination.
+    {
+    std::vector<double> v0 = {0.5, 1.5, 2.5};
+    std::vector<double> v1 = {2.0, 3.0, 4.0};
+    LMI_TEST_EQUAL(3, forEach(v0, LengthLeaf(), MaxCombine()));
+    LMI_TEST_EQUAL(3, forEach(v0 / v1 + v0 * v1, LengthLeaf(), MaxCombine()));
+    }
+
+    // Test non-conformable assignment.
+    {
+    std::vector<double> v0 = {0.0, 1.25, 2.5};
+    std::vector<double> v1 = {0.0, 1.25, 2.5, 3.75};
+    LMI_TEST_THROW(v0 *= v1, std::runtime_error, "");
+    }
+
     // Test peteCast().
     {
     std::vector<double> v0 = {0.0, 1.25, 2.5};
diff --git a/expression_template_0_test.cpp b/expression_template_0_test.cpp
index 8624a42..c2f5cf8 100644
--- a/expression_template_0_test.cpp
+++ b/expression_template_0_test.cpp
@@ -494,10 +494,14 @@ void test_pete_assignment()
 // though these still wouldn't compile:
 //  std::vector<double> v7c << v0 - v1;
 //  std::vector<double> v7d(v0 - v1);
-// and, although this compiles:
-    std::vector<double> v7e; v7e << v0 - v1;
-// it doesn't do what one might hope--instead, the vector is empty:
+// and,
+    std::vector<double> v7e;
+// although this would compile:
+//  v7e << v0 - v1;
+// it wouldn't do what one might hope--instead, the result would be
+// empty, as PETE diagnoses:
     LMI_TEST(0 == v7e.size());
+    LMI_TEST_THROW(v7e << v0 - v1, std::runtime_error, "");
 
 // On the other hand, this syntax is almost natural, even though it's
 // silly to add zero to everything.
diff --git a/tools/pete-2.1.1/et_vector.hpp b/tools/pete-2.1.1/et_vector.hpp
index 443ce22..b03e323 100644
--- a/tools/pete-2.1.1/et_vector.hpp
+++ b/tools/pete-2.1.1/et_vector.hpp
@@ -45,8 +45,11 @@
 #include "config.hpp"
 #endif // 0
 
+#include "ssize_lmi.hpp"
+
 #include "PETE/PETE.h"
 
+#include <stdexcept>
 #include <vector>
 
 // Include "et_vector_operators.hpp" last because it's generated
@@ -70,25 +73,106 @@
 #   pragma GCC diagnostic pop
 #endif // defined __GNUC__
 
-/// Create vector-iterator leaves.
+/// Create vector-reference leaves.
 
 template<class T>
 struct CreateLeaf<std::vector<T>>
 {
-    typedef typename std::vector<T>::const_iterator Leaf_t;
-    static Leaf_t make(std::vector<T> const& v) {return v.begin();}
+    typedef Reference<std::vector<T>> Leaf_t;
+    static Leaf_t make(std::vector<T> const& v) {return Leaf_t(v);}
+};
+
+/// Compare vector size with a stored value.
+
+class SizeLeaf
+{
+  public:
+    SizeLeaf(int s) : length_(s) {}
+    SizeLeaf(SizeLeaf const& model) : length_(model.length_) {}
+    bool operator()(int s) const {return length_ == s;}
+
+  private:
+    int length_;
+};
+
+template<class T>
+struct LeafFunctor<Scalar<T>, SizeLeaf>
+{
+    typedef bool Type_t;
+    static bool apply(Scalar<T> const&, SizeLeaf const&)
+    {
+        return true; // Scalars conform to any vector's length.
+    }
+};
+
+template<class T>
+struct LeafFunctor<std::vector<T>, SizeLeaf>
+{
+    typedef bool Type_t;
+    static bool apply(std::vector<T> const& v, SizeLeaf const& s)
+    {
+        return s(lmi::ssize(v));
+    }
+};
+
+template<class T>
+struct LeafFunctor<std::vector<T>, EvalLeaf1>
+{
+    typedef T Type_t;
+    static Type_t apply(std::vector<T> const& vec, EvalLeaf1 const& f)
+    {
+        return vec[f.val1()];
+    }
+};
+
+/// Compare vector size with a stored value.
+
+struct LengthLeaf {};
+
+template<class T, class Allocator>
+struct LeafFunctor<std::vector<T, Allocator>, LengthLeaf>
+{
+    typedef int Type_t;
+    static Type_t apply(std::vector<T, Allocator> const& v, LengthLeaf const&)
+        {return lmi::ssize(v);}
+};
+
+template<class T>
+struct LeafFunctor<T, LengthLeaf>
+{
+    typedef int Type_t;
+    static Type_t apply(T const& a, LengthLeaf const&)
+        {return 0;}
+};
+
+struct MaxCombine
+{
+    PETE_EMPTY_CONSTRUCTORS(MaxCombine)
+};
+
+template<class Op>
+struct Combine2<int, int, Op, MaxCombine>
+{
+    typedef int Type_t;
+    static Type_t combine(int a, int b, MaxCombine)
+    {
+        if(a < b) return b; else return a;
+    }
 };
 
 /// All PETE assignment operators call evaluate().
 
 template<class T, class Op, class U>
-inline void evaluate(std::vector<T>& t, Op const& op, U const& u)
+inline void evaluate(std::vector<T>& t, Op const& op, Expression<U> const& u)
 {
-    typedef typename std::vector<T>::iterator svi;
-    for(svi i = t.begin(); i != t.end(); ++i)
+    if(!forEach(u, SizeLeaf(lmi::ssize(t)), AndCombine()))
+        {
+        throw std::runtime_error("Error: LHS and RHS don't conform.");
+        }
+
+    for(int i = 0; i < lmi::ssize(t); ++i)
         {
-        op(*i, forEach(u, DereferenceLeaf(), OpCombine()));
-        forEach(u, IncrementLeaf(), NullCombine());
+        op(t[i], forEach(u, EvalLeaf1(i), OpCombine()));
         }
 }
 



reply via email to

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