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