1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Various sanity tests with exceptions:
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//  - no memory leak when a custom scalar type trow an exceptions
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//  - todo: complete the list of tests!
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_STACK_ALLOCATION_LIMIT 100000000
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "main.h"
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct my_exception
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  my_exception() {}
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  ~my_exception() {}
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass ScalarWithExceptions
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions() { init(); }
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions(const float& _v) { init(); *v = _v; }
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions(const ScalarWithExceptions& other) { init(); *v = *(other.v); }
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ~ScalarWithExceptions() {
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      delete v;
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      instances--;
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void init() {
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      v = new float;
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      instances++;
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions operator+(const ScalarWithExceptions& other) const
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      countdown--;
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(countdown<=0)
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        throw my_exception();
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return ScalarWithExceptions(*v+*other.v);
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions operator-(const ScalarWithExceptions& other) const
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { return ScalarWithExceptions(*v-*other.v); }
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions operator*(const ScalarWithExceptions& other) const
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { return ScalarWithExceptions((*v)*(*other.v)); }
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions& operator+=(const ScalarWithExceptions& other)
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { *v+=*other.v; return *this; }
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions& operator-=(const ScalarWithExceptions& other)
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { *v-=*other.v; return *this; }
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions& operator=(const ScalarWithExceptions& other)
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { *v = *(other.v); return *this; }
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    bool operator==(const ScalarWithExceptions& other) const
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { return *v==*other.v; }
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    bool operator!=(const ScalarWithExceptions& other) const
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { return *v!=*other.v; }
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    float* v;
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    static int instances;
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    static int countdown;
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezScalarWithExceptions real(const ScalarWithExceptions &x) { return x; }
737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezScalarWithExceptions imag(const ScalarWithExceptions & ) { return 0; }
747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezScalarWithExceptions conj(const ScalarWithExceptions &x) { return x; }
757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathint ScalarWithExceptions::instances = 0;
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathint ScalarWithExceptions::countdown = 0;
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define CHECK_MEMLEAK(OP) {                                 \
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ScalarWithExceptions::countdown = 100;                  \
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    int before = ScalarWithExceptions::instances;           \
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    bool exception_thrown = false;                         \
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    try { OP; }                              \
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    catch (my_exception) {                                  \
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      exception_thrown = true;                              \
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      VERIFY(ScalarWithExceptions::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    } \
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY(exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)); \
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid memoryleak()
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,1> VectorType;
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,Dynamic> MatrixType;
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    int n = 50;
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VectorType v0(n), v1(n);
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MatrixType m0(n,n), m1(n,n), m2(n,n);
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    v0.setOnes(); v1.setOnes();
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m0.setOnes(); m1.setOnes(); m2.setOnes();
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CHECK_MEMLEAK(v0 = m0 * m1 * v1);
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CHECK_MEMLEAK(m2 = m0 * m1 * m2);
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CHECK_MEMLEAK((v0+v1).dot(v0+v1));
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(ScalarWithExceptions::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP)); \
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid test_exceptions()
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  CALL_SUBTEST( memoryleak() );
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
114