00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <ppl-config.h>
00025
00026 #include "Grid_Generator.defs.hh"
00027 #include <iostream>
00028 #include <sstream>
00029
00030 namespace PPL = Parma_Polyhedra_Library;
00031
00032 void
00033 PPL::Grid_Generator::throw_invalid_argument(const char* method,
00034 const char* reason) const {
00035 std::ostringstream s;
00036 s << "PPL::Grid_Generator::" << method << ":" << std::endl
00037 << reason << ".";
00038 throw std::invalid_argument(s.str());
00039 }
00040
00041 PPL::Grid_Generator
00042 PPL::Grid_Generator::parameter(const Linear_Expression& e,
00043 Coefficient_traits::const_reference d) {
00044 if (d == 0)
00045 throw std::invalid_argument("PPL::parameter(e, d):\n"
00046 "d == 0.");
00047
00048 Linear_Expression ec(e,
00049 e.space_dimension() + 2);
00050 Generator g(ec, Generator::RAY, NECESSARILY_CLOSED);
00051 g[0] = 0;
00052
00053
00054 Grid_Generator gg(g);
00055 gg.set_divisor(d);
00056
00057
00058
00059 if (d < 0)
00060 for (dimension_type i = gg.size(); i-- > 0; )
00061 neg_assign(gg[i]);
00062
00063 return gg;
00064 }
00065
00066 PPL::Grid_Generator
00067 PPL::Grid_Generator::grid_point(const Linear_Expression& e,
00068 Coefficient_traits::const_reference d) {
00069 if (d == 0)
00070 throw std::invalid_argument("PPL::grid_point(e, d):\n"
00071 "d == 0.");
00072
00073 Linear_Expression ec(e,
00074 e.space_dimension() + 2);
00075 Generator g(ec, Generator::POINT, NECESSARILY_CLOSED);
00076 g[0] = d;
00077
00078
00079 Grid_Generator gg(g);
00080
00081
00082
00083 if (d < 0)
00084 for (dimension_type i = gg.size(); i-- > 0; )
00085 neg_assign(gg[i]);
00086
00087
00088 gg.normalize();
00089 return gg;
00090 }
00091
00092 PPL::Grid_Generator
00093 PPL::Grid_Generator::grid_line(const Linear_Expression& e) {
00094
00095 if (e.all_homogeneous_terms_are_zero())
00096 throw std::invalid_argument("PPL::grid_line(e):\n"
00097 "e == 0, but the origin cannot be a line.");
00098
00099
00100 Linear_Expression ec(e,
00101 e.space_dimension() + 2);
00102 Generator g(ec, Generator::LINE, NECESSARILY_CLOSED);
00103 g[0] = 0;
00104
00105
00106 Grid_Generator gg(g);
00107
00108
00109 gg.strong_normalize();
00110 return gg;
00111 }
00112
00113 void
00114 PPL::Grid_Generator::coefficient_swap(Grid_Generator& y) {
00115
00116
00117
00118 if (y.is_line())
00119 set_is_line();
00120 else
00121 set_is_ray_or_point();
00122 PPL_ASSERT(size() > 0);
00123 PPL_ASSERT(y.size() > 0);
00124 dimension_type sz = size() - 1;
00125 dimension_type y_sz = y.size() - 1;
00126
00127 std::swap(operator[](sz), y[y_sz]);
00128 for (dimension_type j = (sz > y_sz ? y_sz : sz); j-- > 0; )
00129 std::swap(operator[](j), y[j]);
00130 }
00131
00132 void
00133 PPL::Grid_Generator::ascii_dump(std::ostream& s) const {
00134 const Grid_Generator& x = *this;
00135 const dimension_type x_size = x.size();
00136 s << "size " << x_size << " ";
00137 for (dimension_type i = 0; i < x_size; ++i)
00138 s << x[i] << ' ';
00139 switch (x.type()) {
00140 case Generator::LINE:
00141 s << "L";
00142 break;
00143 case Generator::RAY:
00144 s << "Q";
00145 break;
00146 case Generator::POINT:
00147 s << "P";
00148 break;
00149 }
00150 s << "\n";
00151 }
00152
00153 PPL_OUTPUT_DEFINITIONS(Grid_Generator)
00154
00155 bool
00156 PPL::Grid_Generator::ascii_load(std::istream& s) {
00157 std::string str;
00158 if (!(s >> str) || str != "size")
00159 return false;
00160 dimension_type new_size;
00161 if (!(s >> new_size))
00162 return false;
00163
00164 Row& x = *this;
00165 const dimension_type old_size = x.size();
00166 if (new_size < old_size)
00167 x.shrink(new_size);
00168 else if (new_size > old_size) {
00169 Row y(new_size, Row::Flags());
00170 x.swap(y);
00171 }
00172
00173 for (dimension_type col = 0; col < new_size; ++col)
00174 if (!(s >> x[col]))
00175 return false;
00176
00177 if (!(s >> str))
00178 return false;
00179 if (str == "L")
00180 set_is_line();
00181 else if (str == "P" || str == "Q")
00182 set_is_ray_or_point();
00183 else
00184 return false;
00185
00186 return true;
00187 }
00188
00189 void
00190 PPL::Grid_Generator::set_is_parameter() {
00191 if (is_line())
00192 set_is_parameter_or_point();
00193 else if (!is_line_or_parameter()) {
00194
00195 Generator::operator[](size() - 1) = Generator::operator[](0);
00196 Generator::operator[](0) = 0;
00197 }
00198 }
00199
00200 bool
00201 PPL::Grid_Generator::is_equivalent_to(const Grid_Generator& y) const {
00202 const Grid_Generator& x = *this;
00203 dimension_type x_space_dim = x.space_dimension();
00204 if (x_space_dim != y.space_dimension())
00205 return false;
00206
00207 const Type x_type = x.type();
00208 if (x_type != y.type())
00209 return false;
00210
00211 Grid_Generator tmp = *this;
00212 Grid_Generator tmp_y = y;
00213 dimension_type& last = x_space_dim;
00214 ++last;
00215 if (x_type == POINT || x_type == LINE) {
00216 tmp[last] = 0;
00217 tmp_y[last] = 0;
00218 }
00219
00220 tmp.Row::normalize();
00221 tmp_y.Row::normalize();
00222
00223 while (last-- > 0)
00224 if (tmp[last] != tmp_y[last])
00225 return false;
00226 return true;
00227 }
00228
00229 bool
00230 PPL::Grid_Generator::is_equal_to(const Grid_Generator& y) const {
00231 if (type() != y.type())
00232 return false;
00233 for (dimension_type col = (is_parameter() ? size() : size() - 1);
00234 col-- > 0; )
00235 if (Generator::operator[](col) != y.Generator::operator[](col))
00236 return false;
00237 return true;
00238 }
00239
00240 bool
00241 PPL::Grid_Generator::all_homogeneous_terms_are_zero() const {
00242
00243 for (dimension_type i = size() - 1; --i > 0; )
00244 if (operator[](i) != 0)
00245 return false;
00246 return true;
00247 }
00248
00249 void
00250 PPL::Grid_Generator::scale_to_divisor(Coefficient_traits::const_reference d) {
00251 if (is_parameter_or_point()) {
00252 if (d == 0)
00253 throw std::invalid_argument("PPL::Grid_Generator::scale_to_divisor(d):\n"
00254 "d == 0.");
00255
00256 PPL_DIRTY_TEMP_COEFFICIENT(factor);
00257 exact_div_assign(factor, d, divisor());
00258 set_divisor(d);
00259 PPL_ASSERT(factor > 0);
00260 if (factor > 1)
00261 for (dimension_type col = size() - 2; col >= 1; --col)
00262 Generator::operator[](col) *= factor;
00263 }
00264 }
00265
00266 const PPL::Grid_Generator* PPL::Grid_Generator::zero_dim_point_p = 0;
00267
00268 void
00269 PPL::Grid_Generator::initialize() {
00270 PPL_ASSERT(zero_dim_point_p == 0);
00271 zero_dim_point_p
00272 = new Grid_Generator(grid_point());
00273 }
00274
00275 void
00276 PPL::Grid_Generator::finalize() {
00277 PPL_ASSERT(zero_dim_point_p != 0);
00278 delete zero_dim_point_p;
00279 zero_dim_point_p = 0;
00280 }
00281
00283 std::ostream&
00284 PPL::IO_Operators::operator<<(std::ostream& s, const Grid_Generator& g) {
00285 bool need_divisor = false;
00286 bool extra_parentheses = false;
00287 const dimension_type num_variables = g.space_dimension();
00288 Grid_Generator::Type t = g.type();
00289 switch (t) {
00290 case Grid_Generator::LINE:
00291 s << "l(";
00292 break;
00293 case Grid_Generator::PARAMETER:
00294 s << "q(";
00295 if (g[num_variables + 1] == 1)
00296 break;
00297 goto any_point;
00298 case Grid_Generator::POINT:
00299 s << "p(";
00300 if (g[0] > 1) {
00301 any_point:
00302 need_divisor = true;
00303 dimension_type num_non_zero_coefficients = 0;
00304 for (dimension_type v = 0; v < num_variables; ++v)
00305 if (g[v+1] != 0)
00306 if (++num_non_zero_coefficients > 1) {
00307 extra_parentheses = true;
00308 s << "(";
00309 break;
00310 }
00311 }
00312 break;
00313 }
00314
00315 PPL_DIRTY_TEMP_COEFFICIENT(gv);
00316 bool first = true;
00317 for (dimension_type v = 0; v < num_variables; ++v) {
00318 gv = g[v+1];
00319 if (gv != 0) {
00320 if (!first) {
00321 if (gv > 0)
00322 s << " + ";
00323 else {
00324 s << " - ";
00325 neg_assign(gv);
00326 }
00327 }
00328 else
00329 first = false;
00330 if (gv == -1)
00331 s << "-";
00332 else if (gv != 1)
00333 s << gv << "*";
00334 s << PPL::Variable(v);
00335 }
00336 }
00337 if (first)
00338
00339 s << 0;
00340 if (extra_parentheses)
00341 s << ")";
00342 if (need_divisor)
00343 s << "/" << g.divisor();
00344 s << ")";
00345 return s;
00346 }
00347
00349 std::ostream&
00350 PPL::IO_Operators::operator<<(std::ostream& s,
00351 const Grid_Generator::Type& t) {
00352 const char* n = 0;
00353 switch (t) {
00354 case Grid_Generator::LINE:
00355 n = "LINE";
00356 break;
00357 case Grid_Generator::PARAMETER:
00358 n = "PARAMETER";
00359 break;
00360 case Generator::POINT:
00361 n = "POINT";
00362 break;
00363 }
00364 s << n;
00365 return s;
00366 }
00367
00368 bool
00369 PPL::Grid_Generator::OK() const {
00370 if (!is_necessarily_closed()) {
00371 #ifndef NDEBUG
00372 std::cerr << "Grid_Generator should be necessarily closed."
00373 << std::endl;
00374 #endif
00375 return false;
00376 }
00377
00378
00379 if (size() < 1) {
00380 #ifndef NDEBUG
00381 std::cerr << "Grid_Generator has fewer coefficients than the minimum "
00382 << "allowed:" << std::endl
00383 << "size is " << size() << ", minimum is 1." << std::endl;
00384 #endif
00385 return false;
00386 }
00387
00388 switch (type()) {
00389 case Grid_Generator::LINE:
00390 if (operator[](0) != 0) {
00391 #ifndef NDEBUG
00392 std::cerr << "Inhomogeneous terms of lines must be zero!"
00393 << std::endl;
00394 #endif
00395 return false;
00396 }
00397 break;
00398
00399 case Grid_Generator::PARAMETER:
00400 if (operator[](0) != 0) {
00401 #ifndef NDEBUG
00402 std::cerr << "Inhomogeneous terms of parameters must be zero!"
00403 << std::endl;
00404 #endif
00405 return false;
00406 }
00407
00408
00409 case Grid_Generator::POINT:
00410 if (divisor() <= 0) {
00411 #ifndef NDEBUG
00412 std::cerr << "Points and parameters must have positive divisors!"
00413 << std::endl;
00414 #endif
00415 return false;
00416 }
00417 break;
00418
00419 }
00420
00421
00422 return true;
00423 }