1 // Copyright (c) 2016 Adrien Guinet <adrien@guinet.me> 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above copyright 9 // notice, this list of conditions and the following disclaimer in the 10 // documentation and/or other materials provided with the distribution. 11 // * Neither the name of the <organization> nor the 12 // names of its contributors may be used to endorse or promote products 13 // derived from this software without specific prior written permission. 14 // 15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 // DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 19 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26 #ifndef PETANQUE_APP_H 27 #define PETANQUE_APP_H 28 29 #include <pa/exports.h> 30 #include <pa/matrix.h> 31 #include <pa/vector.h> 32 33 #include <utility> 34 35 namespace pa { 36 37 // Represents an affine application, as X:->M*X+V 38 class PA_API AffApp 39 { 40 public: 41 struct InvalidSizes: public std::exception 42 { InvalidSizesInvalidSizes43 InvalidSizes(Matrix const&, Vector const&) 44 { } 45 46 public: whatInvalidSizes47 const char* what() const noexcept override 48 { 49 return "incompatible sizes of M and V: expected M a square matrix of the size of V."; 50 } 51 }; 52 53 public: AffApp(Matrix const & M,Vector const & V)54 AffApp(Matrix const& M, Vector const& V): 55 _M(M), 56 _V(V) 57 { 58 check_sizes(M, V); 59 } 60 AffApp(Matrix && M,Vector && V)61 AffApp(Matrix&& M, Vector&& V): 62 _M(M), 63 _V(V) 64 { 65 check_sizes(_M, _V); 66 } 67 AffApp(Matrix const & M,Vector && V)68 AffApp(Matrix const& M, Vector&& V): 69 _M(M), 70 _V(std::move(V)) 71 { 72 check_sizes(M, V); 73 } 74 AffApp(Matrix && M,Vector const & V)75 AffApp(Matrix&& M, Vector const& V): 76 _M(std::move(M)), 77 _V(V) 78 { 79 check_sizes(M, V); 80 } 81 AffApp(AffApp const & app)82 AffApp(AffApp const& app): 83 AffApp(app.matrix(), app.cst()) 84 { } 85 AffApp(AffApp && app)86 AffApp(AffApp&& app): 87 AffApp(std::move(app._M), std::move(app._V)) 88 { } 89 90 public: set_Matrix(Matrix const & M)91 void set_Matrix(Matrix const& M) 92 { 93 check_sizes(M, _V); 94 _M = M; 95 } 96 set_Vector(Vector const & V)97 void set_Vector(Vector const& V) 98 { 99 check_sizes(_M, V); 100 _V = V; 101 } 102 set_Matrix(Matrix && M)103 void set_Matrix(Matrix&& M) 104 { 105 check_sizes(M, _V); 106 _M = std::move(M); 107 } 108 set_Vector(Vector & V)109 void set_Vector(Vector& V) 110 { 111 check_sizes(_M, V); 112 _V = std::move(V); 113 } 114 matrix()115 Matrix const& matrix() const { return _M; } cst()116 Vector const& cst() const { return _V; } 117 118 public: operator()119 Vector operator()(Vector const& X) const 120 { 121 return matrix()*X+cst(); 122 } 123 124 public: 125 inline AffApp& operator=(AffApp const& o) 126 { 127 if (&o != this) { 128 _M = o.matrix(); _V = o.cst(); 129 } 130 return *this; 131 } 132 133 inline AffApp& operator=(AffApp&& o) 134 { 135 if (&o != this) { 136 _M = std::move(o.matrix()); _V = std::move(o.cst()); 137 } 138 return *this; 139 } 140 141 private: check_sizes(Matrix const & M,Vector const & V)142 static void check_sizes(Matrix const& M, Vector const& V) 143 { 144 if (M.nlines() != V.size()) { 145 throw InvalidSizes(M, V); 146 } 147 } 148 149 private: 150 Matrix _M; 151 Vector _V; 152 }; 153 154 // Represents an application defined through a vector 155 class PA_API VectorApp 156 { 157 public: VectorApp(Vector const & symbols,Vector const & V)158 VectorApp(Vector const& symbols, Vector const& V) 159 { 160 set(symbols, V); 161 } 162 VectorApp(VectorApp const & o)163 VectorApp(VectorApp const& o): 164 _V(o._V) 165 { } 166 VectorApp(VectorApp && o)167 VectorApp(VectorApp&& o): 168 _V(std::move(o._V)) 169 { } 170 171 public: 172 void set(Vector const& symbols, Vector const& V); vector()173 Vector const& vector() const { return _V; } 174 175 public: 176 Vector operator()(Vector const& x) const; 177 178 private: 179 Vector _V; 180 }; 181 182 // Represents a generic application, as X:->NL(X) + M*X + V 183 class PA_API App 184 { 185 public: App(VectorApp const & NL,AffApp const & aff)186 App(VectorApp const& NL, AffApp const& aff): 187 _NL(NL), 188 _aff(aff) 189 { 190 check_sizes(NL, aff); 191 } 192 App(VectorApp && NL,AffApp && aff)193 App(VectorApp&& NL, AffApp&& aff): 194 _NL(std::move(NL)), 195 _aff(std::move(aff)) 196 { 197 check_sizes(_NL, _aff); 198 } 199 App(VectorApp const & NL,Matrix const & M,Vector const & V)200 App(VectorApp const& NL, Matrix const& M, Vector const& V): 201 _NL(NL), 202 _aff(M, V) 203 { 204 check_sizes(NL, _aff); 205 } 206 App(VectorApp && NL,Matrix && M,Vector && V)207 App(VectorApp&& NL, Matrix&& M, Vector&& V): 208 _NL(std::move(NL)), 209 _aff(std::forward<Matrix>(M), std::forward<Vector>(V)) 210 { 211 check_sizes(_NL, _aff); 212 } 213 App(App const & o)214 App(App const &o): 215 _NL(o._NL), 216 _aff(o._aff) 217 { } 218 App(App && o)219 App(App&& o): 220 _NL(std::move(o._NL)), 221 _aff(std::move(o._aff)) 222 { } 223 224 public: nl()225 VectorApp const& nl() const { return _NL; } 226 affine()227 AffApp const& affine() const { return _aff; } cst()228 Vector const& cst() const { return _aff.cst(); } matrix()229 Matrix const& matrix() const { return _aff.matrix(); } 230 231 public: check_sizes(VectorApp const &,AffApp const &)232 static void check_sizes(VectorApp const&, AffApp const&) { } 233 234 public: operator()235 Vector operator()(Vector const& X) const 236 { 237 return nl()(X) + affine()(X); 238 } 239 240 private: 241 VectorApp _NL; 242 AffApp _aff; 243 }; 244 245 } 246 247 #endif 248